summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikita Popov <nikita.ppv@gmail.com>2019-08-26 17:48:05 +0200
committerNikita Popov <nikita.ppv@gmail.com>2019-08-26 17:49:37 +0200
commit589542f50cbaf2bfc88aea79092df9db54f75ac6 (patch)
tree45290742014449a3a2f224ec0e8495c61c421517
parent1e82a2d659aac6ef95a6820d4f6ac3684e07bcad (diff)
downloadphp-git-589542f50cbaf2bfc88aea79092df9db54f75ac6.tar.gz
Remove properties HT from nested GC data
The properties HT may be a GC root itself, so we need to remove it. I'm not sure this issue actually applies to PHP 7.2, but committing it there to be safe. As seen from the test case, the handling here is rather buggy on 7.2.
-rw-r--r--Zend/tests/gc_042.phpt26
-rw-r--r--Zend/zend_gc.c4
2 files changed, 30 insertions, 0 deletions
diff --git a/Zend/tests/gc_042.phpt b/Zend/tests/gc_042.phpt
new file mode 100644
index 0000000000..a7c40fe1ff
--- /dev/null
+++ b/Zend/tests/gc_042.phpt
@@ -0,0 +1,26 @@
+--TEST--
+Object properties HT may need to be removed from nested data
+--FILE--
+<?php
+
+class Test {
+ public function __destruct() {
+ $GLOBALS['x'] = $this;
+ }
+}
+
+$t = new Test;
+$t->x = new stdClass;
+$t->x->t = $t;
+$a = (array) $t->x;
+unset($t, $a);
+gc_collect_cycles();
+var_dump($x);
+
+// TODO: The destructor *should* be running here, but doesn't.
+// This works in PHP >= 7.3 though.
+
+?>
+--EXPECTF--
+Notice: Undefined variable: x in %s on line %d
+NULL
diff --git a/Zend/zend_gc.c b/Zend/zend_gc.c
index d98598cc48..1b6d53a83d 100644
--- a/Zend/zend_gc.c
+++ b/Zend/zend_gc.c
@@ -1007,6 +1007,10 @@ tail_call:
ref = Z_COUNTED_P(zv);
goto tail_call;
}
+ if (GC_ADDRESS(GC_INFO(ht)) != 0 && GC_REF_GET_COLOR(ht) == GC_BLACK) {
+ GC_TRACE_REF(ht, "removing from buffer");
+ GC_REMOVE_FROM_BUFFER(ht);
+ }
} else {
return;
}