Bug #79820 [Com]: double-free causing heap corruption

From: Date: Tue, 14 Jul 2020 00:41:34 +0000
Subject: Bug #79820 [Com]: double-free causing heap corruption
References: 1  Groups: php.bugs 
Request: Send a blank email to php-bugs+get-228017@lists.php.net to get a copy of this message
Edit report at https://bugs.php.net/bug.php?id=79820&edit=1 ID: 79820 Comment by: christopher dot broadbent at zencontrol dot com Reported by: christopher dot broadbent at zencontrol dot com Summary: double-free causing heap corruption Status: Open Type: Bug Package: Reproducible crash Operating System: linux debian buster PHP Version: 7.4.7 Block user comment: N Private report: N New Comment: Have build 7.4.8 from source .tar.gz file on website, it exhibits the same crash. Trying to get it built and run with sanitizers now in case they give anything useful. Previous Comments: ------------------------------------------------------------------------ [2020-07-13 23:54:05] christopher dot broadbent at zencontrol dot com Upgraded to 7.4.8, still crashes. > I can't find any version of PHP 7.4 that has a zend_string_release call in > php_reflection.c:225 This might be the inline of the release call being assigned weird line numbers as it runs? The frame #4 reflection_free_objects_storage (object=0x7ff047a6cb18) at ./ext/reflection/php_reflection.c:230 is calling: zend_string_release(ZEND_TYPE_NAME(type_ref->type)); Regardless, I've asked the package maintainer if there are any patches applied before he builds: https://github.com/oerdnj/deb.sury.org/issues/1433 I doubt that is the problem though as we're also hitting this issue on the official docker containers, and they don't seem to do any patching. Docker images: https://hub.docker.com/layers/php/library/php/7.4.8-buster/images/sha256-96e4c07b30977303a1bc53a269ea5284b3d85d4d89787948c3a594dc89a03698?context=explore Docker image source: https://github.com/docker-library/php/tree/master/7.4/buster ------------------------------------------------------------------------ [2020-07-09 08:47:51] nikic@php.net Not seeing what could cause this. Property types getting resolved while being held by reflection is something we specifically protect against. ------------------------------------------------------------------------ [2020-07-09 08:41:17] nikic@php.net On which version/commit of PHP were the gdb backtraces gathered? I can't find any version of PHP 7.4 that has a zend_string_release call in php_reflection.c:225. The valgrind trace looks more plausible. There might be some relation to https://github.com/php/php-src/commit/c9abfaec6bf61bcef6d9651827b49cc7789018fd. ------------------------------------------------------------------------ [2020-07-09 05:44:47] 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 ------------------------------------------------------------------------ -- Edit this bug report at https://bugs.php.net/bug.php?id=79820&edit=1

« previous php.bugs (#228017) next »