Bug #80894 [NEW]: GC-related crash after using __debugInfo()
| From: | tstarling@php.net | Date: | Mon, 22 Mar 2021 11:28:51 +0000 |
| Subject: | Bug #80894 [NEW]: GC-related crash after using __debugInfo() | ||
| Groups: | php.bugs | ||
| Request: | Send a blank email to php-bugs+get-232913@lists.php.net to get a copy of this message | ||
From: tstarling
Operating system: Linux
PHP version: 7.3Git-2021-03-22 (Git)
Package: Reproducible crash
Bug Type: Bug
Bug description:GC-related crash after using __debugInfo()
Description:
------------
While investigating a reproducible segfault encountered in automated
testing of https://gerrit.wikimedia.org/r/c/mediawiki/core/+/672845
, I
discovered that PHP 7.3's var_dump() does not correctly free the return
value of the __debugInfo() method. It uses zend_hash_destroy() instead
of zend_array_destroy(), causing the array to potentially remain in the
GC root buffer. When the GC runs, the array is freed a second time.
Compiling with AddressSanitizer helped to isolate the issue, allowing it
to be demonstrated with a short test case.
PHP 7.4+ is not affected due to the introduction of
zend_get_properties_for().
Test script:
---------------
<?php
class C {
public function __debugInfo() {
// Clone the empty array and add it to the GC buffer
$res = array_merge( [] );
return $res;
}
}
$c = new C;
var_dump( $c );
Expected result:
----------------
object(C)#1 (0) {
}
Actual result:
--------------
object(C)#1 (0) {
}
=================================================================
==914259==ERROR: AddressSanitizer: heap-use-after-free on address
0x6060000166a4 at pc 0x555556a46f9b bp 0x7fffffffac50 sp 0x7fffffffac40
READ of size 4 at 0x6060000166a4 thread T0
#0 0x555556a46f9a in gc_mark_roots /srv/php/core/Zend/zend_gc.c:976
#1 0x555556a4a928 in zend_gc_collect_cycles
/srv/php/core/Zend/zend_gc.c:1473
#2 0x55555697aba2 in shutdown_executor
/srv/php/core/Zend/zend_execute_API.c:293
#3 0x5555569b8c44 in zend_deactivate /srv/php/core/Zend/zend.c:1104
#4 0x55555685dfcd in php_request_shutdown
/srv/php/core/main/main.c:1928
#5 0x555556c20146 in do_cli /srv/php/core/sapi/cli/php_cli.c:1167
#6 0x555556c2116e in main /srv/php/core/sapi/cli/php_cli.c:1396
#7 0x7ffff653d0b2 in __libc_start_main
(/lib/x86_64-linux-gnu/libc.so.6+0x270b2)
#8 0x555555a6f46d in _start (/srv/php/core/sapi/cli/php+0x51b46d)
0x6060000166a4 is located 4 bytes inside of 56-byte region
[0x6060000166a0,0x6060000166d8)
freed by thread T0 here:
#0 0x7ffff769a7cf in __interceptor_free
(/usr/lib/x86_64-linux-gnu/libasan.so.5+0x10d7cf)
#1 0x55555692d553 in _efree /srv/php/core/Zend/zend_alloc.c:2516
#2 0x55555666d81a in php_var_dump
/srv/php/core/ext/standard/var.c:168
#3 0x55555666dd5c in zif_var_dump
/srv/php/core/ext/standard/var.c:210
#4 0x555556abb16e in ZEND_DO_ICALL_SPEC_RETVAL_UNUSED_HANDLER
/srv/php/core/Zend/zend_vm_execute.h:649
#5 0x555556c06809 in execute_ex
/srv/php/core/Zend/zend_vm_execute.h:55499
#6 0x555556c17f26 in zend_execute
/srv/php/core/Zend/zend_vm_execute.h:60935
#7 0x5555569bc397 in zend_execute_scripts
/srv/php/core/Zend/zend.c:1568
#8 0x5555568611b2 in php_execute_script
/srv/php/core/main/main.c:2637
#9 0x555556c1ee23 in do_cli /srv/php/core/sapi/cli/php_cli.c:1000
#10 0x555556c2116e in main /srv/php/core/sapi/cli/php_cli.c:1396
#11 0x7ffff653d0b2 in __libc_start_main
(/lib/x86_64-linux-gnu/libc.so.6+0x270b2)
previously allocated by thread T0 here:
#0 0x7ffff769abc8 in malloc
(/usr/lib/x86_64-linux-gnu/libasan.so.5+0x10dbc8)
#1 0x55555692f1e7 in __zend_malloc
/srv/php/core/Zend/zend_alloc.c:2909
#2 0x55555692d3f4 in _emalloc /srv/php/core/Zend/zend_alloc.c:2502
#3 0x5555569eaec0 in _zend_new_array
/srv/php/core/Zend/zend_hash.c:224
#4 0x555556514406 in php_array_merge_or_replace_wrapper
/srv/php/core/ext/standard/array.c:3796
#5 0x555556514dbe in zif_array_merge
/srv/php/core/ext/standard/array.c:3845
#6 0x555556abb78d in ZEND_DO_ICALL_SPEC_RETVAL_USED_HANDLER
/srv/php/core/Zend/zend_vm_execute.h:694
#7 0x555556c0683a in execute_ex
/srv/php/core/Zend/zend_vm_execute.h:55503
#8 0x55555697f8c9 in zend_call_function
/srv/php/core/Zend/zend_execute_API.c:756
#9 0x555556a28e02 in zend_call_method
/srv/php/core/Zend/zend_interfaces.c:103
#10 0x555556a7d979 in zend_std_get_debug_info
/srv/php/core/Zend/zend_object_handlers.c:155
#11 0x55555666d327 in php_var_dump
/srv/php/core/ext/standard/var.c:153
#12 0x55555666dd5c in zif_var_dump
/srv/php/core/ext/standard/var.c:210
#13 0x555556abb16e in ZEND_DO_ICALL_SPEC_RETVAL_UNUSED_HANDLER
/srv/php/core/Zend/zend_vm_execute.h:649
#14 0x555556c06809 in execute_ex
/srv/php/core/Zend/zend_vm_execute.h:55499
#15 0x555556c17f26 in zend_execute
/srv/php/core/Zend/zend_vm_execute.h:60935
#16 0x5555569bc397 in zend_execute_scripts
/srv/php/core/Zend/zend.c:1568
#17 0x5555568611b2 in php_execute_script
/srv/php/core/main/main.c:2637
#18 0x555556c1ee23 in do_cli /srv/php/core/sapi/cli/php_cli.c:1000
#19 0x555556c2116e in main /srv/php/core/sapi/cli/php_cli.c:1396
#20 0x7ffff653d0b2 in __libc_start_main
(/lib/x86_64-linux-gnu/libc.so.6+0x270b2)
SUMMARY: AddressSanitizer: heap-use-after-free
/srv/php/core/Zend/zend_gc.c:976 in gc_mark_roots
Shadow bytes around the buggy address:
0x0c0c7fffac80: fd fd fd fd fd fd fd fa fa fa fa fa 00 00 00 00
0x0c0c7fffac90: 00 00 00 fa fa fa fa fa fd fd fd fd fd fd fd fd
0x0c0c7fffaca0: fa fa fa fa fd fd fd fd fd fd fd fa fa fa fa fa
0x0c0c7fffacb0: 00 00 00 00 00 00 00 fa fa fa fa fa 00 00 00 00
0x0c0c7fffacc0: 00 00 00 fa fa fa fa fa fd fd fd fd fd fd fd fd
=>0x0c0c7fffacd0: fa fa fa fa[fd]fd fd fd fd fd fd fa fa fa fa fa
0x0c0c7ffface0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c0c7fffacf0: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c0c7fffad00: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c0c7fffad10: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c0c7fffad20: fa fa fa fa fa fa fa fa fa fa fa fa fa fa 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
Shadow gap: cc
==914259==ABORTING
[Inferior 1 (process 914259) exited with code 01]
--
Edit bug report at https://bugs.php.net/bug.php?id=80894&edit=1
--
Fix committed: https://bugs.php.net/fix.php?id=80894&r=fixed
Fixed in release: https://bugs.php.net/fix.php?id=80894&r=alreadyfixed
Need backtrace: https://bugs.php.net/fix.php?id=80894&r=needtrace
Need Reproduce Script: https://bugs.php.net/fix.php?id=80894&r=needscript
Try newer version: https://bugs.php.net/fix.php?id=80894&r=oldversion
Not developer issue: https://bugs.php.net/fix.php?id=80894&r=support
Expected behavior: https://bugs.php.net/fix.php?id=80894&r=notwrong
Not enough info: https://bugs.php.net/fix.php?id=80894&r=notenoughinfo
Submitted twice: https://bugs.php.net/fix.php?id=80894&r=submittedtwice
register_globals: https://bugs.php.net/fix.php?id=80894&r=globals
PHP version support discontinued: https://bugs.php.net/fix.php?id=80894&r=phptooold
Daylight Savings: https://bugs.php.net/fix.php?id=80894&r=dst
IIS Stability: https://bugs.php.net/fix.php?id=80894&r=isapi
Install GNU Sed: https://bugs.php.net/fix.php?id=80894&r=gnused
Floating point limitations: https://bugs.php.net/fix.php?id=80894&r=float
No Zend Extensions: https://bugs.php.net/fix.php?id=80894&r=nozend
MySQL Configuration Error: https://bugs.php.net/fix.php?id=80894&r=mysqlcfg