com php-src: Fixed bug #70805 (Segmentation faults whilst running Drupal 8 test suite): NEWS Zend/tests/bug70805.phpt Zend/tests/bug70 805_1.phpt
Zend/tests/bug70805_2. phpt Zend/zend_gc.c Zend/zend_hash.c Zend/zend_ vm_def.h Zend/zend_vm_execute.h

From: Date: Wed, 04 Nov 2015 01:53:56 +0000
Subject: com php-src: Fixed bug #70805 (Segmentation faults whilst running Drupal 8 test suite): NEWS Zend/tests/bug70805.phpt Zend/tests/bug70 805_1.phpt
Zend/tests/bug70805_2. phpt Zend/zend_gc.c Zend/zend_hash.c Zend/zend_ vm_def.h Zend/zend_vm_execute.h
Groups: php.cvs 
Request: Send a blank email to php-cvs+get-89586@lists.php.net to get a copy of this message
Commit: 2f2653aa7758cd586f1daff288146740dd5fa61b Author: Xinchen Hui <laruence@gmail.com> Tue, 3 Nov 2015 17:53:56 -0800 Parents: d7ff107654acb5dc682773bb0b369a7e593056d8 Branches: PHP-7.0 master Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=2f2653aa7758cd586f1daff288146740dd5fa61b Log: Fixed bug #70805 (Segmentation faults whilst running Drupal 8 test suite) Bugs: https://bugs.php.net/70805 Changed paths: M NEWS A Zend/tests/bug70805.phpt A Zend/tests/bug70805_1.phpt A Zend/tests/bug70805_2.phpt M Zend/zend_gc.c M Zend/zend_hash.c M Zend/zend_vm_def.h M Zend/zend_vm_execute.h

diff --git a/NEWS b/NEWS index d3f0137..3a0b712 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,10 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? 2015, PHP 7.0.1 +- Core: + . Fixed bug #70805 (Segmentation faults whilst running Drupal 8 test suite). + (Dmitry, Laruence) + - Opcache: . Fixed bug #70656 (require() statement broken after opcache_reset() or a few hours of use). (Laruence) diff --git a/Zend/tests/bug70805.phpt b/Zend/tests/bug70805.phpt new file mode 100644 index 0000000..256f52e --- /dev/null +++ b/Zend/tests/bug70805.phpt @@ -0,0 +1,46 @@ +--TEST-- +Bug #70805 (Segmentation faults whilst running Drupal 8 test suite) +--FILE-- +<?php +class A { +} + +class B { +} + +class C { + public function __destruct() { + if (isset($GLOBALS["a"])) { + unset($GLOBALS["array"]); + unset($GLOBALS["a"]); // this will be called in gc_colloct_roots and put $a into gc roots buf + } + } +} + +$a = new A; +$a->b = new B; +$a->b->a = $a; + +$i = 0; + +$c = new A; +$array = array($c); //This is used to leave a room for $GLOBALS["a"] +unset($c); + +while ($i++ < 9997) { + $t = []; + $t[] = &$t; + unset($t); +} +$t = [new C]; +$t[] = &$t; +unset($t); // This is used to trigger C::__destruct while doing gc_colloct_roots + +$e = $a; +unset($a); // This one can not be putted into roots buf because it's full, thus gc_colloct_roots will be called, + // but C::__destructor which is called in gc_colloct_roots will put $a into buf + // which will make $a be putted into gc roots buf twice +var_dump(gc_collect_cycles()); +?> +--EXPECT-- +int(0) diff --git a/Zend/tests/bug70805_1.phpt b/Zend/tests/bug70805_1.phpt new file mode 100644 index 0000000..0225b4c --- /dev/null +++ b/Zend/tests/bug70805_1.phpt @@ -0,0 +1,43 @@ +--TEST-- +Bug #70805 (Segmentation faults whilst running Drupal 8 test suite) (Crash) +--FILE-- +<?php +class A { +} + +class B { +} + +class C { + public function __destruct() { + if (isset($GLOBALS["a"])) { + unset($GLOBALS["array"]); + unset($GLOBALS["a"]); + } + } +} + +$a = new A; +$a->b = new B; +$a->b->a = $a; + +$i = 0; + +$c = new A; +$array = array($c); +unset($c); + +while ($i++ < 9997) { + $t = []; + $t[] = &$t; + unset($t); +} +$t = [new C]; +$t[] = &$t; +unset($t); +unset($a); + +var_dump(gc_collect_cycles()); +?> +--EXPECT-- +int(2) diff --git a/Zend/tests/bug70805_2.phpt b/Zend/tests/bug70805_2.phpt new file mode 100644 index 0000000..a9b1168 --- /dev/null +++ b/Zend/tests/bug70805_2.phpt @@ -0,0 +1,37 @@ +--TEST-- +Bug #70805 (Segmentation faults whilst running Drupal 8 test suite) (Memleak) +--FILE-- +<?php +class A { +} + +class B { +} + +class C { + public function __destruct() { + if (isset($GLOBALS["a"])) { + unset($GLOBALS["a"]); + } + } +} + +$a = new A; +$a->b = new B; +$a->b->a = $a; + +$i = 0; + +while ($i++ < 9998) { + $t = []; + $t[] = &$t; + unset($t); +} +$t = [new C]; +$t[] = &$t; +unset($t); + +unset($a); +var_dump(gc_collect_cycles()); +--EXPECT-- +int(2) diff --git a/Zend/zend_gc.c b/Zend/zend_gc.c index e223a49..74c5348 100644 --- a/Zend/zend_gc.c +++ b/Zend/zend_gc.c @@ -242,6 +242,13 @@ ZEND_API void ZEND_FASTCALL gc_possible_root(zend_refcounted *ref) GC_REFCOUNT(ref)++; gc_collect_cycles(); GC_REFCOUNT(ref)--; + if (UNEXPECTED(GC_REFCOUNT(ref)) == 0) { + zval_dtor_func_for_ptr(ref); + return; + } + if (UNEXPECTED(GC_INFO(ref))) { + return; + } newRoot = GC_G(unused); if (!newRoot) { #if ZEND_GC_DEBUG diff --git a/Zend/zend_hash.c b/Zend/zend_hash.c index 8a8ef29..52868cf 100644 --- a/Zend/zend_hash.c +++ b/Zend/zend_hash.c @@ -1049,9 +1049,13 @@ ZEND_API int ZEND_FASTCALL zend_hash_del_ind(HashTable *ht, zend_string *key) return FAILURE; } else { if (ht->pDestructor) { - ht->pDestructor(data); + zval tmp; + ZVAL_COPY_VALUE(&tmp, data); + ZVAL_UNDEF(data); + ht->pDestructor(&tmp); + } else { + ZVAL_UNDEF(data); } - ZVAL_UNDEF(data); } } else { _zend_hash_del_el_ex(ht, idx, p, prev); diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index ad6dc58..1fc343b 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -5513,8 +5513,14 @@ ZEND_VM_HANDLER(74, ZEND_UNSET_VAR, CONST|TMPVAR|CV, UNUSED|CONST|VAR) ZVAL_UNDEF(var); zval_dtor_func_for_ptr(garbage); } else { - GC_ZVAL_CHECK_POSSIBLE_ROOT(var); - ZVAL_UNDEF(var); + zval *z = var; + ZVAL_DEREF(z); + if (Z_COLLECTABLE_P(z) && UNEXPECTED(!Z_GC_INFO_P(z))) { + ZVAL_UNDEF(var); + gc_possible_root(Z_COUNTED_P(z)); + } else { + ZVAL_UNDEF(var); + } } } else { ZVAL_UNDEF(var); diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 97e08b7..dcf0f07 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -6105,8 +6105,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CONST_CONST_HAN ZVAL_UNDEF(var); zval_dtor_func_for_ptr(garbage); } else { - GC_ZVAL_CHECK_POSSIBLE_ROOT(var); - ZVAL_UNDEF(var); + zval *z = var; + ZVAL_DEREF(z); + if (Z_COLLECTABLE_P(z) && UNEXPECTED(!Z_GC_INFO_P(z))) { + ZVAL_UNDEF(var); + gc_possible_root(Z_COUNTED_P(z)); + } else { + ZVAL_UNDEF(var); + } } } else { ZVAL_UNDEF(var); @@ -7034,8 +7040,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CONST_VAR_HANDL ZVAL_UNDEF(var); zval_dtor_func_for_ptr(garbage); } else { - GC_ZVAL_CHECK_POSSIBLE_ROOT(var); - ZVAL_UNDEF(var); + zval *z = var; + ZVAL_DEREF(z); + if (Z_COLLECTABLE_P(z) && UNEXPECTED(!Z_GC_INFO_P(z))) { + ZVAL_UNDEF(var); + gc_possible_root(Z_COUNTED_P(z)); + } else { + ZVAL_UNDEF(var); + } } } else { ZVAL_UNDEF(var); @@ -7894,8 +7906,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CONST_UNUSED_HA ZVAL_UNDEF(var); zval_dtor_func_for_ptr(garbage); } else { - GC_ZVAL_CHECK_POSSIBLE_ROOT(var); - ZVAL_UNDEF(var); + zval *z = var; + ZVAL_DEREF(z); + if (Z_COLLECTABLE_P(z) && UNEXPECTED(!Z_GC_INFO_P(z))) { + ZVAL_UNDEF(var); + gc_possible_root(Z_COUNTED_P(z)); + } else { + ZVAL_UNDEF(var); + } } } else { ZVAL_UNDEF(var); @@ -32128,8 +32146,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CV_CONST_HANDLE ZVAL_UNDEF(var); zval_dtor_func_for_ptr(garbage); } else { - GC_ZVAL_CHECK_POSSIBLE_ROOT(var); - ZVAL_UNDEF(var); + zval *z = var; + ZVAL_DEREF(z); + if (Z_COLLECTABLE_P(z) && UNEXPECTED(!Z_GC_INFO_P(z))) { + ZVAL_UNDEF(var); + gc_possible_root(Z_COUNTED_P(z)); + } else { + ZVAL_UNDEF(var); + } } } else { ZVAL_UNDEF(var); @@ -33412,8 +33436,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CV_VAR_HANDLER( ZVAL_UNDEF(var); zval_dtor_func_for_ptr(garbage); } else { - GC_ZVAL_CHECK_POSSIBLE_ROOT(var); - ZVAL_UNDEF(var); + zval *z = var; + ZVAL_DEREF(z); + if (Z_COLLECTABLE_P(z) && UNEXPECTED(!Z_GC_INFO_P(z))) { + ZVAL_UNDEF(var); + gc_possible_root(Z_COUNTED_P(z)); + } else { + ZVAL_UNDEF(var); + } } } else { ZVAL_UNDEF(var); @@ -34642,8 +34672,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CV_UNUSED_HANDL ZVAL_UNDEF(var); zval_dtor_func_for_ptr(garbage); } else { - GC_ZVAL_CHECK_POSSIBLE_ROOT(var); - ZVAL_UNDEF(var); + zval *z = var; + ZVAL_DEREF(z); + if (Z_COLLECTABLE_P(z) && UNEXPECTED(!Z_GC_INFO_P(z))) { + ZVAL_UNDEF(var); + gc_possible_root(Z_COUNTED_P(z)); + } else { + ZVAL_UNDEF(var); + } } } else { ZVAL_UNDEF(var); @@ -41847,8 +41883,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_TMPVAR_CONST_HA ZVAL_UNDEF(var); zval_dtor_func_for_ptr(garbage); } else { - GC_ZVAL_CHECK_POSSIBLE_ROOT(var); - ZVAL_UNDEF(var); + zval *z = var; + ZVAL_DEREF(z); + if (Z_COLLECTABLE_P(z) && UNEXPECTED(!Z_GC_INFO_P(z))) { + ZVAL_UNDEF(var); + gc_possible_root(Z_COUNTED_P(z)); + } else { + ZVAL_UNDEF(var); + } } } else { ZVAL_UNDEF(var); @@ -42432,8 +42474,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_TMPVAR_VAR_HAND ZVAL_UNDEF(var); zval_dtor_func_for_ptr(garbage); } else { - GC_ZVAL_CHECK_POSSIBLE_ROOT(var); - ZVAL_UNDEF(var); + zval *z = var; + ZVAL_DEREF(z); + if (Z_COLLECTABLE_P(z) && UNEXPECTED(!Z_GC_INFO_P(z))) { + ZVAL_UNDEF(var); + gc_possible_root(Z_COUNTED_P(z)); + } else { + ZVAL_UNDEF(var); + } } } else { ZVAL_UNDEF(var); @@ -42834,8 +42882,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_TMPVAR_UNUSED_H ZVAL_UNDEF(var); zval_dtor_func_for_ptr(garbage); } else { - GC_ZVAL_CHECK_POSSIBLE_ROOT(var); - ZVAL_UNDEF(var); + zval *z = var; + ZVAL_DEREF(z); + if (Z_COLLECTABLE_P(z) && UNEXPECTED(!Z_GC_INFO_P(z))) { + ZVAL_UNDEF(var); + gc_possible_root(Z_COUNTED_P(z)); + } else { + ZVAL_UNDEF(var); + } } } else { ZVAL_UNDEF(var);
« previous php.cvs (#89586) next »