krakjoe / pthreads

Threading for PHP - Share Nothing, Do Everything :)
Other
3.47k stars 501 forks source link

heap-use-after-free/segmentation fault/runtime issues #920

Open eazrael opened 5 years ago

eazrael commented 5 years ago

Environment

PHP 7.2.14 (cli) (built: Jan 31 2019 21:15:56) ( ZTS ) Zend Engine v3.2.0, Copyright (c) 1998-2018 Zend Technologies pthreads Version => 3.2.1dev

Summary

I see this issue on two different physical machines with different Linux flavours (Ubuntu Server 18.4.4 in VM and Slackware 14.2 on bare metal).

I try to make a "closed loop" allowing Threaded tasks to submit new tasks back into the pool via a Volatile queue being polled by the main thread controlling the pool. I hope I did not overengineer this..

Anyways, on both machines this behaves very bad. Before compiling the most visible issue was data missing in mid processing the threaded object:

class MyTask extends Threaded 
{    
    public function __construct(string $name, int $ttl, int $count = 0) 
...
    public function run() : void
    {
            echo "+Task " . $x . " running with ttl " . $this->ttl ." and count ". $this->count. "\n"; 
            $child = new MyTask($x, $this->ttl - 1, $this->count + 1);
     }
}

Fatal error: Uncaught TypeError: Argument 1 passed to MyTask::__construct() must be of the type string, null given,

After recompiling with --with-pthreads-sanitize AS reports very soon a "heap-use-after-free".


==14934==ERROR: AddressSanitizer: heap-use-after-free on address 0x608000004220 at pc 0x7fd70dc24f0d bp 0x7fd70d1fe940 sp 0x7fd70d1fe930
    #0 0x7fd70dc24f0c in pthreads_monitor_check /root/pthreads-master/src/monitor.c:67
    #1 0x7fd70dc15653 in pthreads_routine_run_function /root/pthreads-master/src/object.c:455
    #2 0x7fd70dc43167 in pthreads_routine /root/pthreads-master/src/object.c:516
    #3 0x7fd7140eb6da in start_thread (/lib/x86_64-linux-gnu/libpthread.so.0+0x76da)
    #4 0x7fd713a5388e in __clone (/lib/x86_64-linux-gnu/libc.so.6+0x12188e)

0x608000004220 is located 0 bytes inside of 96-byte region [0x608000004220,0x608000004280)
freed by thread T1 here:
    #0 0x7fd714b9e7b8 in __interceptor_free (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xde7b8)
    #1 0x7fd70dc43d68 in pthreads_base_free /root/pthreads-master/src/object.c:353
    #2 0x5568e4e03983 in zend_objects_store_del /root/php-7.2.14/Zend/zend_objects_API.c:189

previously allocated by thread T1 here:
    #0 0x7fd714b9ed38 in __interceptor_calloc (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xded38)
    #1 0x7fd70dc24dcb in pthreads_monitor_alloc /root/pthreads-master/src/monitor.c:33
    #2 0x7fd70dc41786 in pthreads_base_ctor /root/pthreads-master/src/object.c:311
    #3 0x7fd70dc42270 in pthreads_threaded_ctor /root/pthreads-master/src/object.c:166
    #4 0x5568e4dc3a7a in _object_and_properties_init /root/php-7.2.14/Zend/zend_API.c:1332

Thread T2 created by T0 here:
    #0 0x7fd714af7d2f in __interceptor_pthread_create (/usr/lib/x86_64-linux-gnu/libasan.so.4+0x37d2f)
    #1 0x7fd70dc4369c in pthreads_start /root/pthreads-master/src/object.c:396
    #2 0x7fd70dc18793 in zim_Thread_start classes/thread.h:97
    #3 0x5568e4daedd5 in zend_call_function /root/php-7.2.14/Zend/zend_execute_API.c:834
    #4 0x556800000000  (<unknown module>)
    #5 0x625000000000  (<unknown module>)

Thread T1 created by T0 here:
    #0 0x7fd714af7d2f in __interceptor_pthread_create (/usr/lib/x86_64-linux-gnu/libasan.so.4+0x37d2f)
    #1 0x7fd70dc4369c in pthreads_start /root/pthreads-master/src/object.c:396
    #2 0x7fd70dc18793 in zim_Thread_start classes/thread.h:97
    #3 0x5568e4daedd5 in zend_call_function /root/php-7.2.14/Zend/zend_execute_API.c:834

SUMMARY: AddressSanitizer: heap-use-after-free /root/pthreads-master/src/monitor.c:67 in pthreads_monitor_check
Shadow bytes around the buggy address:
  0x0c107fff87f0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
  0x0c107fff8800: fa fa fa fa fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c107fff8810: fa fa fa fa fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c107fff8820: fa fa fa fa fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c107fff8830: fa fa fa fa fd fd fd fd fd fd fd fd fd fd fd fd
=>0x0c107fff8840: fa fa fa fa[fd]fd fd fd fd fd fd fd fd fd fd fd
  0x0c107fff8850: fa fa fa fa fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c107fff8860: fa fa fa fa fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c107fff8870: fa fa fa fa fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c107fff8880: fa fa fa fa fd fd fd fd fd fd fd fd fd fd fd fd
  0x0c107fff8890: fa fa fa fa fd fd fd fd fd fd fd fd fd fd fd fd
Shadow byte legend (one shadow byte represents 8 application bytes):
  Addressable:           00
  Partially addressable: 01 02 03 04 05 06 07 
  Heap left redzone:       fa
  Freed

 heap region:       fd
  Stack left redzone:      f1
  Stack mid redzone:       f2
  Stack right redzone:     f3
  Stack after return:      f5
  Stack use after scope:   f8
  Global redzone:          f9
  Global init order:       f6
  Poisoned by user:        f7
  Container overflow:      fc
  Array cookie:            ac
  Intra object redzone:    bb
  ASan internal:           fe
  Left alloca redzone:     ca
  Right alloca redzone:    cb
==14934==ABORTING

Two completely different systems report the same.

My test program is attached, Sorry that this is so messy, after each fail I made it more noisy. Example output is also attached output.txt threadtest2.php.txt