orthecreedence / cl-async

Asynchronous IO library for Common Lisp.
MIT License
272 stars 40 forks source link

Possible memory corruption #147

Open libre-man opened 7 years ago

libre-man commented 7 years ago

In streamish.lisp on line 148 the buffer given to uv-write is freed immediately after the function returns. However according to the libuv documention this is not correct as the buffer may only be freed after the callback as been called.

So the buffer could be used after the free which will result in memory errors and in the best case in a segfault and worst case possible security issues.

orthecreedence commented 7 years ago

Great catch! I'll see about fixing this.

muyinliu commented 4 years ago

also (uv:free-req req) in the same function write-to-uvstream, details:

while running a very simple demo with SBCL v1.3.21, cl-libuv f811e500 and cl-async f5eb6a3d:

(ql:quickload '(cl-async bordeaux-threads))

(defun tcp-server ()
  (as:tcp-server nil 5000
                 (lambda (sock data)
                   (as:write-socket-data sock data))
                 :event-cb (lambda (event)
                             (format *terminal-io* "event: ~A~%" event)))
  (as:signal-handler as:+sigint+
                     (lambda (sig)
                       (declare (ignore sig))
                       (as:exit-event-loop))))

(bt:make-thread #'(lambda ()
                    (as:start-event-loop #'tcp-server))
                :name "cl-async-event-loop-thread")

(defun test ()
  (as:start-event-loop
   (lambda ()
     (as:tcp-connect "127.0.0.1" 5000
                     (lambda (socket data)
                       (unless (as:socket-closed-p socket)
                         (format *terminal-io* "socket-closed~%")
                         (as:close-socket socket))
                       (format *terminal-io* "~A" (babel:octets-to-string data)))
                     :event-cb (lambda (event)
                                 (format *terminal-io* "event: ~A~%" event))
                     :connect-cb (lambda (socket)
                                   (dotimes (var 4)
                                     (as:write-socket-data socket
                                                           (format nil "hello~A" var))))))))

occur memory fault:

sbcl(41527,0xb000e000) malloc: *** error for object 0x202e70: incorrect checksum for freed object - object was probably modified after being freed.
*** set a breakpoint in malloc_error_break to debug
fatal error encountered in SBCL pid 41527(tid 0xb000e000):
SIGABRT received.

Error opening /dev/tty: Device not configured
Welcome to LDB, a low-level debugger for the Lisp runtime environment.
ldb> backtrace
Backtrace:
   0: Foreign function __pthread_kill, pc = 0x7fff64fbab66, fp = 0x824c1e0
   1: Foreign function abort, pc = 0x7fff64f161ae, fp = 0x824c210
   2: Foreign function szone_error, pc = 0x7fff6501fb58, fp = 0x824c330
   3: Foreign function tiny_free_list_remove_ptr, pc = 0x7fff650157a5, fp = 0x824c350
   4: Foreign function tiny_free_no_lock, pc = 0x7fff6502ab46, fp = 0x824c3e0
   5: Foreign function free_tiny, pc = 0x7fff6502b2d2, fp = 0x824c440
   6: LIBUV::FREE-REQ, pc = 0x22a7acad, fp = 0x824c468
   7: CL-ASYNC::STREAMISH-WRITE-CB, (FLET "H0" :IN CL-ASYNC::STREAMISH-WRITE-CB), (LAMBDA () :IN CL-ASYNC::STREAMISH-WRITE-CB), (LAMBDA () :IN CL-ASYNC::STREAMISH-WRITE-CB), pc = 0x22af9be1, fp = 0x824c500
   8: CL-ASYNC-UTIL::CALL-WITH-CALLBACK-RESTARTS, (LAMBDA (STREAM) :IN CL-ASYNC-UTIL::CALL-WITH-CALLBACK-RESTARTS), (LAMBDA () :IN CL-ASYNC-UTIL::CALL-WITH-CALLBACK-RESTARTS), (LAMBDA (STREAM) :IN CL-ASYNC-UTIL::CALL-WITH-CALLBACK-RESTARTS), (LAMBDA () :IN CL-ASYNC-UTIL::CALL-WITH-CALLBACK-RESTARTS), (LAMBDA (COND) :IN "/Users/muyinliu/quicklisp/local-projects/cl-async/src/util/error.lisp"), (LAMBDA (COND) :IN "/Users/muyinliu/quicklisp/local-projects/cl-async/src/util/error.lisp"), (LAMBDA (COND) :IN "/Users/muyinliu/quicklisp/local-projects/cl-async/src/util/error.lisp"), (LAMBDA (STREAM) :IN CL-ASYNC-UTIL::CALL-WITH-CALLBACK-RESTARTS), (LAMBDA () :IN CL-ASYNC-UTIL::CALL-WITH-CALLBACK-RESTARTS), pc = 0x22ae957c, fp = 0x824c770
   9: CL-ASYNC::STREAMISH-WRITE-CB, (FLET "H0" :IN CL-ASYNC::STREAMISH-WRITE-CB), (LAMBDA () :IN CL-ASYNC::STREAMISH-WRITE-CB), (LAMBDA () :IN CL-ASYNC::STREAMISH-WRITE-CB), pc = 0x22af96bd, fp = 0x824c868
  10: (SB-C::TOP-LEVEL-FORM (LET* ((HASHTABLE CFFI-SYS::*CALLBACKS*) (NEW1 (SB-ALIEN::ALIEN-SAP <??? lowtag 3>))) (SB-KERNEL::%PUTHASH (QUOTE CL-ASYNC::STREAMISH-SHUTDOWN-CB) HASHTABLE NEW1))), (LAMBDA (SB-ALIEN::ARGS-POINTER SB-ALIEN::RESULT-POINTER FUNCTION) :IN "/Users/muyinliu/quicklisp/local-projects/cl-async/src/streamish.lisp"), pc = 0x22af6c66, fp = 0x824c8b0
  11: Foreign function call_into_lisp, pc = 0x11d6de, fp = 0x824c8f0
  12: Foreign function funcall3, pc = 0x1034c6, fp = 0x824c930
  13: Foreign function, pc = 0x20100727, fp = 0x824c940
  14: Foreign function, pc = 0x1004e622f3, fp = 0x824c9b0
  15: Foreign function uv__stream_io, pc = 0x180f4d, fp = 0x824cb80
  16: Foreign function uv_run, pc = 0x178af7, fp = 0x824cbf0
  17: LIBUV::UV-RUN, pc = 0x22a49ce6, fp = 0x824cc58
  18: CL-ASYNC::START-EVENT-LOOP, (FLET SB-THREAD::WITH-MUTEX-THUNK :IN CL-ASYNC::START-EVENT-LOOP), (FLET SB-THREAD::WITH-MUTEX-THUNK :IN CL-ASYNC::START-EVENT-LOOP), pc = 0x22aed6a9, fp = 0x824cd30
  19: SB-INT::SIMPLE-EVAL-IN-LEXENV, (LAMBDA (&OPTIONAL SB-IMPL::VARS) :IN SB-INT::SIMPLE-EVAL-IN-LEXENV), (LAMBDA (&OPTIONAL SB-IMPL::FUNS) :IN SB-INT::SIMPLE-EVAL-IN-LEXENV), (LAMBDA (SB-IMPL::TEMP) :IN SB-INT::SIMPLE-EVAL-IN-LEXENV), (LAMBDA (STREAM) :IN SB-INT::SIMPLE-EVAL-IN-LEXENV), (LAMBDA () :IN SB-INT::SIMPLE-EVAL-IN-LEXENV), (FLET "H0" :IN SB-INT::SIMPLE-EVAL-IN-LEXENV), pc = 0x21b2ca3f, fp = 0x824ce60
  20: EVAL, pc = 0x21b2b1d2, fp = 0x824ce78
  21: SWANK::EVAL-REGION, pc = 0x2286d3ae, fp = 0x824cef0
  22: SWANK-REPL::REPL-EVAL, (LAMBDA () :IN SWANK-REPL::REPL-EVAL), (LAMBDA () :IN SWANK-REPL::REPL-EVAL), (LAMBDA () :IN SWANK-REPL::REPL-EVAL), pc = 0x228a14d6, fp = 0x824cf28
  23: SWANK-REPL::TRACK-PACKAGE, pc = 0x228a185c, fp = 0x824cfa0
  24: SWANK::CALL-WITH-RETRY-RESTART, (LAMBDA (STREAM1) :IN SWANK::CALL-WITH-RETRY-RESTART), (LAMBDA () :IN SWANK::CALL-WITH-RETRY-RESTART), pc = 0x2285082d, fp = 0x824d070
  25: SWANK::CALL-WITH-BUFFER-SYNTAX, pc = 0x22868181, fp = 0x824d098
  26: SWANK-REPL::REPL-EVAL, (LAMBDA () :IN SWANK-REPL::REPL-EVAL), (LAMBDA () :IN SWANK-REPL::REPL-EVAL), (LAMBDA () :IN SWANK-REPL::REPL-EVAL), pc = 0x228a12f6, fp = 0x824d0d0
  27: SB-INT::SIMPLE-EVAL-IN-LEXENV, (LAMBDA (&OPTIONAL SB-IMPL::VARS) :IN SB-INT::SIMPLE-EVAL-IN-LEXENV), (LAMBDA (&OPTIONAL SB-IMPL::FUNS) :IN SB-INT::SIMPLE-EVAL-IN-LEXENV), (LAMBDA (SB-IMPL::TEMP) :IN SB-INT::SIMPLE-EVAL-IN-LEXENV), (LAMBDA (STREAM) :IN SB-INT::SIMPLE-EVAL-IN-LEXENV), (LAMBDA () :IN SB-INT::SIMPLE-EVAL-IN-LEXENV), (FLET "H0" :IN SB-INT::SIMPLE-EVAL-IN-LEXENV), pc = 0x21b2ca3f, fp = 0x824d208
  28: EVAL, pc = 0x21b2b1d2, fp = 0x824d220
  29: SWANK::EVAL-FOR-EMACS, (FLET "H0" :IN SWANK::EVAL-FOR-EMACS), pc = 0x2286b36f, fp = 0x824d330
  30: SWANK::PROCESS-REQUESTS, pc = 0x22858ec1, fp = 0x824d360
  31: SWANK::HANDLE-REQUESTS, (LAMBDA () :IN SWANK::HANDLE-REQUESTS), (LAMBDA () :IN SWANK::HANDLE-REQUESTS), (LAMBDA (&OPTIONAL SWANK::V) :IN SWANK::HANDLE-REQUESTS), (LAMBDA (COND) :IN "/Users/muyinliu/quicklisp/dists/quicklisp/software/slime-2.14/swank.lisp"), (LAMBDA (STREAM) :IN SWANK::HANDLE-REQUESTS), (LAMBDA (&REST SB-IMPL::TEMP) :IN SWANK::HANDLE-REQUESTS), (FLET "H0" :IN SWANK::HANDLE-REQUESTS), (LAMBDA () :IN SWANK::HANDLE-REQUESTS), (FLET "H0" :IN SWANK::HANDLE-REQUESTS), (FLET "H0" :IN SWANK::HANDLE-REQUESTS), (LAMBDA () :IN SWANK::HANDLE-REQUESTS), (FLET "H0" :IN SWANK::HANDLE-REQUESTS), pc = 0x228584c8, fp = 0x824d4e0
  32: SWANK::HANDLE-REQUESTS, (LAMBDA () :IN SWANK::HANDLE-REQUESTS), (LAMBDA () :IN SWANK::HANDLE-REQUESTS), (LAMBDA (&OPTIONAL SWANK::V) :IN SWANK::HANDLE-REQUESTS), (LAMBDA (COND) :IN "/Users/muyinliu/quicklisp/dists/quicklisp/software/slime-2.14/swank.lisp"), (LAMBDA (STREAM) :IN SWANK::HANDLE-REQUESTS), (LAMBDA (&REST SB-IMPL::TEMP) :IN SWANK::HANDLE-REQUESTS), (FLET "H0" :IN SWANK::HANDLE-REQUESTS), (LAMBDA () :IN SWANK::HANDLE-REQUESTS), (FLET "H0" :IN SWANK::HANDLE-REQUESTS), (FLET "H0" :IN SWANK::HANDLE-REQUESTS), (LAMBDA () :IN SWANK::HANDLE-REQUESTS), (FLET "H0" :IN SWANK::HANDLE-REQUESTS), pc = 0x22857cfc, fp = 0x824d600
  33: SWANK/SBCL::CALL-WITH-BREAK-HOOK, pc = 0x22829f08, fp = 0x824d620
  34: (FLET SWANK/BACKEND::CALL-WITH-DEBUGGER-HOOK :IN "/Users/muyinliu/quicklisp/dists/quicklisp/software/slime-2.14/swank/sbcl.lisp"), (LAMBDA (CONDITION) :IN SWANK/BACKEND::CALL-WITH-DEBUGGER-HOOK), pc = 0x2282ad85, fp = 0x824d658
  35: SWANK::CALL-WITH-BINDINGS, pc = 0x22843290, fp = 0x824d6e0
  36: SWANK::HANDLE-REQUESTS, (LAMBDA () :IN SWANK::HANDLE-REQUESTS), (LAMBDA () :IN SWANK::HANDLE-REQUESTS), (LAMBDA (&OPTIONAL SWANK::V) :IN SWANK::HANDLE-REQUESTS), (LAMBDA (COND) :IN "/Users/muyinliu/quicklisp/dists/quicklisp/software/slime-2.14/swank.lisp"), (LAMBDA (STREAM) :IN SWANK::HANDLE-REQUESTS), (LAMBDA (&REST SB-IMPL::TEMP) :IN SWANK::HANDLE-REQUESTS), (FLET "H0" :IN SWANK::HANDLE-REQUESTS), (LAMBDA () :IN SWANK::HANDLE-REQUESTS), (FLET "H0" :IN SWANK::HANDLE-REQUESTS), (FLET "H0" :IN SWANK::HANDLE-REQUESTS), (LAMBDA () :IN SWANK::HANDLE-REQUESTS), (FLET "H0" :IN SWANK::HANDLE-REQUESTS), pc = 0x22857881, fp = 0x824d898
  37: SB-THREAD::INITIAL-THREAD-FUNCTION-TRAMPOLINE, (FLET SB-THREAD::WITH-MUTEX-THUNK :IN SB-THREAD::INITIAL-THREAD-FUNCTION-TRAMPOLINE), (LAMBDA (COND) :IN "SYS:SRC;CODE;TARGET-THREAD.LISP"), (LAMBDA (STREAM) :IN SB-THREAD::INITIAL-THREAD-FUNCTION-TRAMPOLINE), (LAMBDA () :IN SB-THREAD::INITIAL-THREAD-FUNCTION-TRAMPOLINE), (FLET SB-THREAD::WITH-SYSTEM-MUTEX-THUNK :IN SB-THREAD::INITIAL-THREAD-FUNCTION-TRAMPOLINE), (FLET SB-THREAD::WITH-SYSTEM-MUTEX-THUNK :IN SB-THREAD::INITIAL-THREAD-FUNCTION-TRAMPOLINE), pc = 0x21e3cb0f, fp = 0x824d9e0
  38: SB-THREAD::INITIAL-THREAD-FUNCTION-TRAMPOLINE, (FLET SB-THREAD::WITH-MUTEX-THUNK :IN SB-THREAD::INITIAL-THREAD-FUNCTION-TRAMPOLINE), (LAMBDA (COND) :IN "SYS:SRC;CODE;TARGET-THREAD.LISP"), (LAMBDA (STREAM) :IN SB-THREAD::INITIAL-THREAD-FUNCTION-TRAMPOLINE), (LAMBDA () :IN SB-THREAD::INITIAL-THREAD-FUNCTION-TRAMPOLINE), (FLET SB-THREAD::WITH-SYSTEM-MUTEX-THUNK :IN SB-THREAD::INITIAL-THREAD-FUNCTION-TRAMPOLINE), (FLET SB-THREAD::WITH-SYSTEM-MUTEX-THUNK :IN SB-THREAD::INITIAL-THREAD-FUNCTION-TRAMPOLINE), pc = 0x21e3c127, fp = 0x824db90
  39: SB-THREAD::CALL-WITH-MUTEX, pc = 0x21b15cf2, fp = 0x824dc38
  40: SB-THREAD::CALL-WITH-MUTEX, pc = 0x21b15959, fp = 0x824dce0
  41: SB-THREAD::INITIAL-THREAD-FUNCTION-TRAMPOLINE, (FLET SB-THREAD::WITH-MUTEX-THUNK :IN SB-THREAD::INITIAL-THREAD-FUNCTION-TRAMPOLINE), (LAMBDA (COND) :IN "SYS:SRC;CODE;TARGET-THREAD.LISP"), (LAMBDA (STREAM) :IN SB-THREAD::INITIAL-THREAD-FUNCTION-TRAMPOLINE), (LAMBDA () :IN SB-THREAD::INITIAL-THREAD-FUNCTION-TRAMPOLINE), (FLET SB-THREAD::WITH-SYSTEM-MUTEX-THUNK :IN SB-THREAD::INITIAL-THREAD-FUNCTION-TRAMPOLINE), (FLET SB-THREAD::WITH-SYSTEM-MUTEX-THUNK :IN SB-THREAD::INITIAL-THREAD-FUNCTION-TRAMPOLINE), pc = 0x21e3ba2e, fp = 0x824de80
  42: Foreign function call_into_lisp, pc = 0x11d6de, fp = 0x824dec0
  43: Foreign function new_thread_trampoline, pc = 0x10edfe, fp = 0x824def0
  44: Foreign function _pthread_body, pc = 0x7fff65182661, fp = 0x824df20
  45: Foreign function _pthread_body, pc = 0x7fff6518250d, fp = 0x824df50
  46: Foreign function thread_start, pc = 0x7fff65181bf9, fp = 0x824df78
ldb>