|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
[2020-02-11 17:15 UTC] changochen1 at gmail dot com
Description:
------------
Segfault in php_array_element_dump.
PHP version:
```
PHP 8.0.0-dev (cli) (built: Jan 31 2020 21:52:09) ( NTS )
```
Run script:
```
php -f poc.php
```
Stack dump:
```
=================================================================
==301720==ERROR: AddressSanitizer: SEGV on unknown address 0x000000000014 (pc 0x000000bc05f1 bp 0x7ffcdd24dec0 sp 0x7ffcdd24dea0 T0)
#0 0xbc05f0 in php_array_element_dump (/home/rxz226/php-src/bld_asan/sapi/cli/php+0xbc05f0)
#1 0xbc12df in php_var_dump (/home/rxz226/php-src/bld_asan/sapi/cli/php+0xbc12df)
#2 0xbc062a in php_array_element_dump (/home/rxz226/php-src/bld_asan/sapi/cli/php+0xbc062a)
#3 0xbc12df in php_var_dump (/home/rxz226/php-src/bld_asan/sapi/cli/php+0xbc12df)
#4 0xbc2184 in zif_var_dump (/home/rxz226/php-src/bld_asan/sapi/cli/php+0xbc2184)
#5 0x123b7e9 in execute_ex (/home/rxz226/php-src/bld_asan/sapi/cli/php+0x123b7e9)
#6 0x127aab7 in zend_execute (/home/rxz226/php-src/bld_asan/sapi/cli/php+0x127aab7)
#7 0xe43dfb in zend_execute_scripts (/home/rxz226/php-src/bld_asan/sapi/cli/php+0xe43dfb)
#8 0xcab3b7 in php_execute_script (/home/rxz226/php-src/bld_asan/sapi/cli/php+0xcab3b7)
#9 0x1280971 in do_cli (/home/rxz226/php-src/bld_asan/sapi/cli/php+0x1280971)
#10 0x1282acb in main (/home/rxz226/php-src/bld_asan/sapi/cli/php+0x1282acb)
#11 0x7f55f1ee282f in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x2082f)
#12 0x428a78 in _start (/home/rxz226/php-src/bld_asan/sapi/cli/php+0x428a78)
AddressSanitizer can not provide additional info.
SUMMARY: AddressSanitizer: SEGV ??:0 php_array_element_dump
```
Test script:
---------------
<?php
$strings = array ( 'into' , 'info' , 'inf' , 'infinity' , 'infin' , 'inflammable' ) ;
foreach ( $strings as $v ) { var_dump ( [ ++ $GLOBALS ] ) ;
$a [ $b = 0 ] [ ] [ 2 ] ++ ;
unset ( $GLOBALS [ is_subclass_of ( ob_start ( function ( $name ) { $GLOBALS [ ] = & $obj ;
var_dump ( $name ) ;
}
, 1 ) , 'dooh' ) [ ++ $i ] ] ) ;
}
PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
|
|||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Sat Oct 25 14:00:01 2025 UTC |
this is simply because the dumping array is resized(reallocaed). a simple reproduced script is: $obj = range(0, 5); ob_start ( function ( $name ) { $GLOBALS[] = &$obj; } , 1 ) ; var_dump ( $GLOBALS) ; I am not sure how to fix this with a reasonable cost@laruence I don't think this is $GLOBALS specific. For example: $obj = range(0, 5); ob_start(function($name) use (&$obj) { static $i = 0; if ($i++ == 5) $obj["foo"] = "bar"; }, 1); var_dump([&$obj]);hmm, nop: $obj = new Stdclass(); $obj->arr = [1, 2, 3, 4, 5]; $obj->arr = &$obj->arr; ob_start ( function ( $name ) use($obj){ $obj->arr[] = 1; } , 1) ; var_dump($obj);okey, made a patch against 7.4: diff --git a/Zend/zend_hash.c b/Zend/zend_hash.c index 7a251ec..5dd4983 100644 --- a/Zend/zend_hash.c +++ b/Zend/zend_hash.c @@ -2073,6 +2073,9 @@ ZEND_API HashTable* ZEND_FASTCALL zend_array_dup(HashTable *source) target->nInternalPointer = source->nInternalPointer; memcpy(HT_GET_DATA_ADDR(target), HT_GET_DATA_ADDR(source), HT_USED_SIZE(source)); } else if (HT_FLAGS(source) & HASH_FLAG_PACKED) { + if (UNEXPECTED(GC_IS_RECURSIVE(source))) { + GC_PROTECT_RECURSION(target); + } HT_FLAGS(target) = HT_FLAGS(source) & HASH_FLAG_MASK; target->nTableMask = HT_MIN_MASK; target->nNumUsed = source->nNumUsed; @@ -2092,6 +2095,9 @@ ZEND_API HashTable* ZEND_FASTCALL zend_array_dup(HashTable *source) zend_array_dup_packed_elements(source, target, 1); } } else { + if (UNEXPECTED(GC_IS_RECURSIVE(source))) { + GC_PROTECT_RECURSION(target); + } HT_FLAGS(target) = HT_FLAGS(source) & HASH_FLAG_MASK; target->nTableMask = source->nTableMask; target->nNextFreeElement = source->nNextFreeElement; diff --git a/ext/standard/var.c b/ext/standard/var.c index 3f7db8f..c1fe15a 100644 --- a/ext/standard/var.c +++ b/ext/standard/var.c @@ -129,6 +129,7 @@ again: return; } GC_PROTECT_RECURSION(myht); + GC_ADDREF(myht); } count = zend_array_count(myht); php_printf("%sarray(%d) {\n", COMMON, count); @@ -138,6 +139,9 @@ again: } ZEND_HASH_FOREACH_END(); if (!(GC_FLAGS(myht) & GC_IMMUTABLE)) { GC_UNPROTECT_RECURSION(myht); + if (GC_DELREF(myht) == 0) { + zend_array_destroy(myht); + } } if (level > 1) { php_printf("%*c", level-1, ' '); running test, not sure about the gc_protected inheritance part, @nikic do you see any problems?