php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #80894 GC-related crash after using __debugInfo()
Submitted: 2021-03-22 11:28 UTC Modified: 2021-03-24 17:55 UTC
From: tstarling@php.net Assigned: stas (profile)
Status: Wont fix Package: Reproducible crash
PHP Version: 7.3Git-2021-03-22 (Git) OS: Linux
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: tstarling@php.net
New email:
PHP Version: OS:

 

 [2021-03-22 11:28 UTC] tstarling@php.net
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]


Patches

Pull Requests

Pull requests:

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2021-03-22 11:35 UTC] tstarling@php.net
The following pull request has been associated:

Patch Name: Fix bug #80894: properly free debuginfo
On GitHub:  https://github.com/php/php-src/pull/6794
Patch:      https://github.com/php/php-src/pull/6794.patch
 [2021-03-22 11:36 UTC] tstarling@php.net
You will need to merge https://github.com/php/php-src/pull/6793 to reproduce the bug with AddressSanitizer.
 [2021-03-24 12:20 UTC] cmb@php.net
-Assigned To: +Assigned To: stas
 [2021-03-24 12:20 UTC] cmb@php.net
PHP-7.3 only receives security support[1], and this doesn't look
like a security issue according to our classification[2].  If it
is indeed not a security issue, and PHP-7.4+ is not affected, this
would be not a bug.

Stas, what do you think?

[1] <https://www.php.net/supported-versions.php>
[2] <https://wiki.php.net/security>
 [2021-03-24 17:55 UTC] stas@php.net
-Status: Assigned +Status: Wont fix
 [2021-03-24 17:55 UTC] stas@php.net
Doesn't look like security issue, so since the timer for 7,3 has run out, this would be a "won't fix".
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Sat Nov 09 10:01:28 2024 UTC