|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
[2020-07-09 05:44 UTC] christopher dot broadbent at zencontrol dot com
Description: ------------ We're currently hitting a fairly random segfault inside PHP. It's reproducible on each run, but we're having difficulty making a minimal reproduction case to upload here. The builds we're using are from https://deb.sury.org/, but we're also hitting the problem on the builds from docker.io I have a capture running under the rr debugger, and have the first free with a backtrace of #0 zend_mm_free_small (bin_num=<optimized out>, ptr=0x7ff047a6caf0, heap=<optimized out>) at ./Zend/zend_alloc.c:1279 #1 zend_mm_free_heap (ptr=0x7ff047a6caf0, heap=<optimized out>) at ./Zend/zend_alloc.c:1370 #2 _efree (ptr=0x7ff047a6caf0) at ./Zend/zend_alloc.c:2550 #3 0x000056422fc1cb24 in zend_objects_store_del (object=0x7ff047a6cb18) at ./Zend/zend_objects_API.c:197 #4 0x000056422fc6c92f in zend_object_release (obj=<optimized out>) at ./Zend/zend_objects_API.h:75 #5 ZEND_DO_FCALL_SPEC_RETVAL_USED_HANDLER () at ./Zend/zend_vm_execute.h:1767 #6 execute_ex (ex=0x7ff047a6caf0) at ./Zend/zend_vm_execute.h:53830 #7 0x000056422fc6da71 in zend_execute (op_array=0x7ff04a27f2a0, return_value=<optimized out>) at ./Zend/zend_vm_execute.h:57922 #8 0x000056422fbe74b3 in zend_execute_scripts (type=type@entry=0x8, retval=0x7ff04a21ca80, retval@entry=0x0, file_count=file_count@entry=0x3) at ./Zend/zend.c:1672 #9 0x000056422fb86b70 in php_execute_script (primary_file=<optimized out>) at ./main/main.c:2621 #10 0x000056422fc6fb86 in do_cli (argc=0xb, argv=0x564230f0cf40) at ./sapi/cli/php_cli.c:961 #11 0x000056422fa4e96b in main (argc=0xb, argv=0x564230f0cf40) at ./sapi/cli/php_cli.c:1356 and the double free has a backtrace of #0 0x000056422fbc1e4b in zend_mm_free_small (bin_num=<optimized out>, ptr=0x7ff047a6caf0, heap=0x7ff04a200040) at ./Zend/zend_alloc.c:1278 #1 zend_mm_free_heap (ptr=0x7ff047a6caf0, heap=0x7ff04a200040) at ./Zend/zend_alloc.c:1370 #2 _efree (ptr=0x7ff047a6caf0) at ./Zend/zend_alloc.c:2550 #3 0x000056422fac9ce4 in zend_string_release (s=<optimized out>) at ./ext/reflection/php_reflection.c:225 #4 reflection_free_objects_storage (object=0x7ff047a6cb18) at ./ext/reflection/php_reflection.c:230 #5 0x000056422fc1cb66 in zend_objects_store_del (object=0x7ff047a6cb18) at ./Zend/zend_objects_API.c:193 #6 0x000056422fc6c92f in zend_object_release (obj=<optimized out>) at ./Zend/zend_objects_API.h:75 #7 ZEND_DO_FCALL_SPEC_RETVAL_USED_HANDLER () at ./Zend/zend_vm_execute.h:1767 #8 execute_ex (ex=0x7ff047a6caf0) at ./Zend/zend_vm_execute.h:53830 #9 0x000056422fc6da71 in zend_execute (op_array=0x7ff04a27f2a0, return_value=<optimized out>) at ./Zend/zend_vm_execute.h:57922 #10 0x000056422fbe74b3 in zend_execute_scripts (type=type@entry=0x8, retval=0x7ff04a21ca80, retval@entry=0x0, file_count=file_count@entry=0x3) at ./Zend/zend.c:1672 #11 0x000056422fb86b70 in php_execute_script (primary_file=<optimized out>) at ./main/main.c:2621 #12 0x000056422fc6fb86 in do_cli (argc=0xb, argv=0x564230f0cf40) at ./sapi/cli/php_cli.c:961 #13 0x000056422fa4e96b in main (argc=0xb, argv=0x564230f0cf40) at ./sapi/cli/php_cli.c:1356 This sticks the heap in to a state where (rr) p $heap->free_slot[8] $59 = (zend_mm_free_slot *) 0x7ff047a6caf0 (rr) p $heap->free_slot[8]->next_free_slot $60 = (zend_mm_free_slot *) 0x7ff047a6caf0 (rr) p $heap->free_slot[8]->next_free_slot->next_free_slot $61 = (zend_mm_free_slot *) 0x7ff047a6caf0 etc, and ends up segfaulting on the second-next allocation Running under valgrind gives a double free in a sightly different place: USE_ZEND_ALLOC=0 valgrind -- php our_args outputs a lot of..stuff before eventually crashing with ==29090== Invalid free() / delete / delete[] / realloc() ==29090== at 0x48369AB: free (vg_replace_malloc.c:530) ==29090== by 0x28ACE3: zend_string_release (zend_string.h:277) ==29090== by 0x28ACE3: reflection_free_objects_storage (php_reflection.c:230) ==29090== by 0x3DDB65: zend_objects_store_del (zend_objects_API.c:193) ==29090== by 0x42D92E: zend_object_release (zend_objects_API.h:75) ==29090== by 0x42D92E: ZEND_DO_FCALL_SPEC_RETVAL_USED_HANDLER (zend_vm_execute.h:1767) ==29090== by 0x42D92E: execute_ex (zend_vm_execute.h:53830) ==29090== by 0x42EA70: zend_execute (zend_vm_execute.h:57922) ==29090== by 0x3A84B2: zend_execute_scripts (zend.c:1672) ==29090== by 0x347B6F: php_execute_script (main.c:2621) ==29090== by 0x430B85: do_cli (php_cli.c:961) ==29090== by 0x20F96A: main (php_cli.c:1356) ==29090== Address 0xc432c40 is 0 bytes inside a block of size 80 free'd ==29090== at 0x48369AB: free (vg_replace_malloc.c:530) ==29090== by 0x3E3E64: zend_string_release (zend_string.h:277) ==29090== by 0x3E3E64: zend_resolve_class_type (zend_execute.c:947) ==29090== by 0x410B64: i_zend_check_property_type (zend_execute.c:961) ==29090== by 0x410B64: i_zend_verify_property_type (zend_execute.c:984) ==29090== by 0x410B64: zend_verify_property_type (zend_execute.c:993) ==29090== by 0x3DBA85: zend_std_write_property (zend_object_handlers.c:897) ==29090== by 0x3B244E: zend_update_property_ex (zend_API.c:4115) ==29090== by 0x289C4B: zim_reflection_property_setValue (php_reflection.c:5485) ==29090== by 0x42DE5F: ZEND_DO_FCALL_SPEC_RETVAL_UNUSED_HANDLER (zend_vm_execute.h:1618) ==29090== by 0x42DE5F: execute_ex (zend_vm_execute.h:53826) ==29090== by 0x42EA70: zend_execute (zend_vm_execute.h:57922) ==29090== by 0x3A84B2: zend_execute_scripts (zend.c:1672) ==29090== by 0x347B6F: php_execute_script (main.c:2621) ==29090== by 0x430B85: do_cli (php_cli.c:961) ==29090== by 0x20F96A: main (php_cli.c:1356) ==29090== Block was alloc'd at ==29090== at 0x483577F: malloc (vg_replace_malloc.c:299) ==29090== by 0x37EF38: __zend_malloc (zend_alloc.c:2976) ==29090== by 0x38629B: zend_string_alloc (zend_string.h:133) ==29090== by 0x38629B: zend_concat3 (zend_compile.c:791) ==29090== by 0x387243: zend_compile_typename (zend_compile.c:5318) ==29090== by 0x38BF6F: zend_compile_prop_decl (zend_compile.c:6100) ==29090== by 0x393EF0: zend_compile_prop_group (zend_compile.c:6178) ==29090== by 0x393EF0: zend_compile_stmt (zend_compile.c:8538) ==29090== by 0x394E46: zend_compile_stmt_list (zend_compile.c:5262) ==29090== by 0x394E46: zend_compile_stmt_list (zend_compile.c:5257) ==29090== by 0x393D59: zend_compile_stmt (zend_compile.c:8479) ==29090== by 0x395BDD: zend_compile_class_decl (zend_compile.c:6467) ==29090== by 0x396AA6: zend_compile_top_stmt (zend_compile.c:8454) ==29090== by 0x396ACF: zend_compile_top_stmt (zend_compile.c:8443) ==29090== by 0x36E844: zend_compile (zend_language_scanner.l:614) I can probably get the full run from the rr debugger uploaded, as well as the valgrind logs, if needed $ php -m [PHP Modules] amqp bcmath calendar Core ctype curl date dom exif FFI fileinfo filter ftp gettext hash iconv intl json libxml mbstring mysqli mysqlnd openssl pcntl pcre PDO pdo_mysql Phar posix rdkafka readline redis Reflection session shmop SimpleXML sockets sodium SPL standard sysvmsg sysvsem sysvshm tokenizer xml xmlreader xmlwriter xsl Zend OPcache zlib [Zend Modules] Zend OPcache Patches0001-Add-refs-to-prop-names-to-avoid-use-after-free (last revision 2020-07-15 05:44 UTC by chris-broadbent at zencontrol dot com)Pull RequestsHistoryAllCommentsChangesGit/SVN commits
|
|||||||||||||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Wed Oct 29 00:00:01 2025 UTC |
Built php 7.4.8 with software@debian-software:~/Documents/php-7.4.8$ ./configure --prefix=/home/software/php --with-openssl --with-zlib --with-curl --enable-intl --enable-mbstring --with-pdo-mysql --with-sodium --with-pear --enable-debug CFLAGS="-fsanitize=address" CXXFLAGS="-fsanitize=address" running then gives me the output software@debian-software:~/Documents/zencontrol/gateway$ USE_ZEND_ALLOC=0 ~/php/bin/php vendor/phpunit/phpunit/phpunit --group default --configuration phpunit.xml --filter "/(Gateway\\\\Chris\\\\Heres\\\\Your\\\\Test\\\\Reproduction\\\\Of\\\\Segfault\\\\SeggyTest::testTesties)( .*)?$/" --test-suffix SeggyTest.php tests/Chris/Heres/Your/Test/Reproduction/Of/Segfault PHPUnit 8.4.1 by Sebastian Bergmann and contributors. Runtime: PHP 7.4.8 Configuration: /home/software/Documents/zencontrol/gateway/phpunit.xml ================================================================= ==30325==ERROR: AddressSanitizer: heap-use-after-free on address 0x607000165804 at pc 0x5653a1555e1e bp 0x7ffc99079730 sp 0x7ffc99079728 READ of size 4 at 0x607000165804 thread T0 #0 0x5653a1555e1d in zend_string_addref /home/software/Documents/php-7.4.8/Zend/zend_string.h:117 #1 0x5653a156046d in reflection_type_factory /home/software/Documents/php-7.4.8/ext/reflection/php_reflection.c:1165 #2 0x5653a158ae55 in zim_reflection_property_getType /home/software/Documents/php-7.4.8/ext/reflection/php_reflection.c:5623 #3 0x5653a1c65114 in ZEND_DO_FCALL_SPEC_RETVAL_USED_HANDLER /home/software/Documents/php-7.4.8/Zend/zend_vm_execute.h:1730 #4 0x5653a1d91a7b in execute_ex /home/software/Documents/php-7.4.8/Zend/zend_vm_execute.h:53828 #5 0x5653a1d9dc18 in zend_execute /home/software/Documents/php-7.4.8/Zend/zend_vm_execute.h:57920 #6 0x5653a1b491ef in zend_execute_scripts /home/software/Documents/php-7.4.8/Zend/zend.c:1678 #7 0x5653a19e78a8 in php_execute_script /home/software/Documents/php-7.4.8/main/main.c:2621 #8 0x5653a1da426b in do_cli /home/software/Documents/php-7.4.8/sapi/cli/php_cli.c:964 #9 0x5653a1da6515 in main /home/software/Documents/php-7.4.8/sapi/cli/php_cli.c:1359 #10 0x7f017115a09a in __libc_start_main ../csu/libc-start.c:308 #11 0x5653a0f224c9 in _start (/home/software/php/bin/php+0x6064c9) 0x607000165804 is located 4 bytes inside of 80-byte region [0x607000165800,0x607000165850) freed by thread T0 here: #0 0x7f01740defb0 in __interceptor_free (/lib/x86_64-linux-gnu/libasan.so.5+0xe8fb0) #1 0x5653a1ab64d6 in _efree_custom /home/software/Documents/php-7.4.8/Zend/zend_alloc.c:2426 #2 0x5653a1ab66f2 in _efree /home/software/Documents/php-7.4.8/Zend/zend_alloc.c:2546 #3 0x5653a1c36d5d in zend_string_release /home/software/Documents/php-7.4.8/Zend/zend_string.h:277 #4 0x5653a1c3f7f9 in zend_resolve_class_type /home/software/Documents/php-7.4.8/Zend/zend_execute.c:947 #5 0x5653a1c3f9e1 in i_zend_check_property_type /home/software/Documents/php-7.4.8/Zend/zend_execute.c:961 #6 0x5653a1c3fcc1 in i_zend_verify_property_type /home/software/Documents/php-7.4.8/Zend/zend_execute.c:984 #7 0x5653a1c3fd12 in zend_verify_property_type /home/software/Documents/php-7.4.8/Zend/zend_execute.c:993 #8 0x5653a1c13073 in zend_std_write_property /home/software/Documents/php-7.4.8/Zend/zend_object_handlers.c:897 #9 0x5653a1b7269b in zend_update_property_ex /home/software/Documents/php-7.4.8/Zend/zend_API.c:4115 #10 0x5653a15898c5 in zim_reflection_property_setValue /home/software/Documents/php-7.4.8/ext/reflection/php_reflection.c:5485 #11 0x5653a1c6433e in ZEND_DO_FCALL_SPEC_RETVAL_UNUSED_HANDLER /home/software/Documents/php-7.4.8/Zend/zend_vm_execute.h:1618 #12 0x5653a1d91a4b in execute_ex /home/software/Documents/php-7.4.8/Zend/zend_vm_execute.h:53824 #13 0x5653a1d9dc18 in zend_execute /home/software/Documents/php-7.4.8/Zend/zend_vm_execute.h:57920 #14 0x5653a1b491ef in zend_execute_scripts /home/software/Documents/php-7.4.8/Zend/zend.c:1678 #15 0x5653a19e78a8 in php_execute_script /home/software/Documents/php-7.4.8/main/main.c:2621 #16 0x5653a1da426b in do_cli /home/software/Documents/php-7.4.8/sapi/cli/php_cli.c:964 #17 0x5653a1da6515 in main /home/software/Documents/php-7.4.8/sapi/cli/php_cli.c:1359 #18 0x7f017115a09a in __libc_start_main ../csu/libc-start.c:308 previously allocated by thread T0 here: #0 0x7f01740df330 in __interceptor_malloc (/lib/x86_64-linux-gnu/libasan.so.5+0xe9330) #1 0x5653a1ab85ff in __zend_malloc /home/software/Documents/php-7.4.8/Zend/zend_alloc.c:2976 #2 0x5653a1ab63f6 in _malloc_custom /home/software/Documents/php-7.4.8/Zend/zend_alloc.c:2417 #3 0x5653a1ab6647 in _emalloc /home/software/Documents/php-7.4.8/Zend/zend_alloc.c:2536 #4 0x5653a1ab8c29 in zend_string_alloc Zend/zend_string.h:133 #5 0x5653a1abf605 in zend_concat3 /home/software/Documents/php-7.4.8/Zend/zend_compile.c:791 #6 0x5653a1abf70d in zend_concat_names /home/software/Documents/php-7.4.8/Zend/zend_compile.c:802 #7 0x5653a1abf7bc in zend_prefix_with_ns /home/software/Documents/php-7.4.8/Zend/zend_compile.c:808 #8 0x5653a1ac0136 in zend_resolve_class_name /home/software/Documents/php-7.4.8/Zend/zend_compile.c:944 #9 0x5653a1ac01fc in zend_resolve_class_name_ast /home/software/Documents/php-7.4.8/Zend/zend_compile.c:954 #10 0x5653a1ae09ee in zend_compile_typename /home/software/Documents/php-7.4.8/Zend/zend_compile.c:5318 #11 0x5653a1ae68f1 in zend_compile_prop_decl /home/software/Documents/php-7.4.8/Zend/zend_compile.c:6100 #12 0x5653a1ae6f25 in zend_compile_prop_group /home/software/Documents/php-7.4.8/Zend/zend_compile.c:6178 #13 0x5653a1afa741 in zend_compile_stmt /home/software/Documents/php-7.4.8/Zend/zend_compile.c:8538 #14 0x5653a1ae03c2 in zend_compile_stmt_list /home/software/Documents/php-7.4.8/Zend/zend_compile.c:5262 #15 0x5653a1afa5bb in zend_compile_stmt /home/software/Documents/php-7.4.8/Zend/zend_compile.c:8479 #16 0x5653a1ae91a1 in zend_compile_class_decl /home/software/Documents/php-7.4.8/Zend/zend_compile.c:6467 #17 0x5653a1afa21a in zend_compile_top_stmt /home/software/Documents/php-7.4.8/Zend/zend_compile.c:8454 #18 0x5653a1afa040 in zend_compile_top_stmt /home/software/Documents/php-7.4.8/Zend/zend_compile.c:8443 #19 0x5653a1a7023a in zend_compile Zend/zend_language_scanner.l:614 #20 0x5653a1a706f4 in compile_file Zend/zend_language_scanner.l:650 #21 0x5653a150fff0 in phar_compile_file /home/software/Documents/php-7.4.8/ext/phar/phar.c:3299 #22 0x5653a1a709e4 in compile_filename Zend/zend_language_scanner.l:671 #23 0x5653a1c57fb1 in zend_include_or_eval /home/software/Documents/php-7.4.8/Zend/zend_execute.c:4240 #24 0x5653a1d45006 in ZEND_INCLUDE_OR_EVAL_SPEC_CV_HANDLER /home/software/Documents/php-7.4.8/Zend/zend_vm_execute.h:37728 #25 0x5653a1d9af48 in execute_ex /home/software/Documents/php-7.4.8/Zend/zend_vm_execute.h:56968 #26 0x5653a1b0a7f0 in zend_call_function /home/software/Documents/php-7.4.8/Zend/zend_execute_API.c:813 #27 0x5653a15e8487 in zif_spl_autoload_call /home/software/Documents/php-7.4.8/ext/spl/php_spl.c:452 #28 0x5653a1b0aa65 in zend_call_function /home/software/Documents/php-7.4.8/Zend/zend_execute_API.c:826 #29 0x5653a1b0c0e1 in zend_lookup_class_ex /home/software/Documents/php-7.4.8/Zend/zend_execute_API.c:995 SUMMARY: AddressSanitizer: heap-use-after-free /home/software/Documents/php-7.4.8/Zend/zend_string.h:117 in zend_string_addref Shadow bytes around the buggy address: 0x0c0e80024ab0: fd fd fd fd fd fa fa fa fa fa 00 00 00 00 00 00 0x0c0e80024ac0: 00 00 00 fa fa fa fa fa fd fd fd fd fd fd fd fd 0x0c0e80024ad0: fd fd fa fa fa fa fd fd fd fd fd fd fd fd fd fd 0x0c0e80024ae0: fa fa fa fa fd fd fd fd fd fd fd fd fd fa fa fa 0x0c0e80024af0: fa fa fd fd fd fd fd fd fd fd fd fa fa fa fa fa =>0x0c0e80024b00:[fd]fd fd fd fd fd fd fd fd fd fa fa fa fa 00 00 0x0c0e80024b10: 00 00 00 00 00 00 00 fa fa fa fa fa fd fd fd fd 0x0c0e80024b20: fd fd fd fd fd fa fa fa fa fa 00 00 00 00 00 00 0x0c0e80024b30: 00 00 00 fa fa fa fa fa 00 00 00 00 00 00 00 00 0x0c0e80024b40: 00 00 fa fa fa fa 00 00 00 00 00 00 00 00 00 fa 0x0c0e80024b50: fa fa fa fa 00 00 00 00 00 00 00 00 00 00 fa fa 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 ==30325==ABORTING I might be able to upload the reproduction case we have, but it looks like it's a fairly large amount of code, and I'm not familiar with any of it.This is probably my inexperience with the code-base, but shouldn't the implementation for ZEND_METHOD(reflection_property, __construct) by increment the ref-count for the value copied by reference->prop = *property_info; when dynam_prop is false? It seems to be the thing keeping a reference around to the deallocated string, causing the use-after-free, and I can't see anywhere in the code path where it bumps the reference count.Sorry, I meant to say bump the ref counters on reference->prop.typeI've made a change to php_reflecation.c lines 5281 to 5302, on 7.4.8 release, inside reflection_property____construct reference = (property_reference*) emalloc(sizeof(property_reference)); if (dynam_prop) { reference->prop.flags = ZEND_ACC_PUBLIC; reference->prop.name = name; reference->prop.doc_comment = NULL; reference->prop.ce = ce; reference->dynamic = 1; } else { reference->prop = *property_info; reference->dynamic = 0; + if (ZEND_TYPE_IS_NAME(reference->prop.type)) { + zend_string_addref(ZEND_TYPE_NAME(reference->prop.type)); + } } reference->unmangled_name = zend_string_copy(name); intern->ptr = reference; intern->ref_type = REF_TYPE_PROPERTY; intern->ce = ce; intern->ignore_visibility = 0; } This fixes the segfault in all the reproduction cases we've got, but I'm not familiar enough with the rest of the code to know if this is correct or causes leaks.Right you are! Minimal reproducer: <?php class Test { public stdClass $prop; } $rp = new ReflectionProperty(Test::class, 'prop'); $test = new Test; $test->prop = new stdClass; var_dump($rp->getType()->getName()); For PHP 8 this has already been fixed by https://github.com/php/php-src/commit/0e3045ae69d1b80c21b2779df721a4ad8bcda401.