summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authortwosee <twose@qq.com>2020-07-11 14:37:25 +0800
committertwosee <twose@qq.com>2020-07-11 14:37:25 +0800
commit56dec3cc73829cefe9817d4c59ea3873dde1f443 (patch)
treee2de57ae772f783c3bb6f5ef080c3bdf303565fb
parent150504e6b1ea2b2eac3177c8cff2657a243da22c (diff)
downloadphp-git-56dec3cc73829cefe9817d4c59ea3873dde1f443.tar.gz
Fixed bug #79830 introduced by fixing bug #79821
This also fixes memory error in debug_zval_dump and var_export.
-rw-r--r--ext/standard/tests/bug79821.phpt20
-rw-r--r--ext/standard/var.c42
2 files changed, 37 insertions, 25 deletions
diff --git a/ext/standard/tests/bug79821.phpt b/ext/standard/tests/bug79821.phpt
index cf1d27e128..53c28ccf0f 100644
--- a/ext/standard/tests/bug79821.phpt
+++ b/ext/standard/tests/bug79821.phpt
@@ -3,16 +3,18 @@ Bug #79821 (array grow during var_dump)
--FILE--
<?php
-$foo = $bar = [];
-for ($i = 0; $i < 3; $i++) {
- $foo = [$foo, [&$bar]];
+foreach (['var_dump', 'debug_zval_dump', 'var_export'] as $output) {
+ $foo = $bar = [];
+ for ($i = 0; $i < 3; $i++) {
+ $foo = [$foo, [&$bar]];
+ }
+ ob_start(function (string $buffer) use (&$bar) {
+ $bar[][] = null;
+ return '';
+ }, 64);
+ $output($foo[0]);
+ ob_end_clean();
}
-ob_start(function (string $buffer) use (&$bar) {
- $bar[][] = null;
- return '';
-}, 1);
-var_dump($foo[0]);
-ob_end_clean();
echo "OK\n";
diff --git a/ext/standard/var.c b/ext/standard/var.c
index 241880b903..618b34bea7 100644
--- a/ext/standard/var.c
+++ b/ext/standard/var.c
@@ -117,22 +117,26 @@ again:
break;
case IS_ARRAY:
myht = Z_ARRVAL_P(struc);
- if (level > 1 && !(GC_FLAGS(myht) & GC_IMMUTABLE)) {
- if (GC_IS_RECURSIVE(myht)) {
- PUTS("*RECURSION*\n");
- return;
+ if (!(GC_FLAGS(myht) & GC_IMMUTABLE)) {
+ if (level > 1) {
+ if (GC_IS_RECURSIVE(myht)) {
+ PUTS("*RECURSION*\n");
+ return;
+ }
+ GC_PROTECT_RECURSION(myht);
}
GC_ADDREF(myht);
- GC_PROTECT_RECURSION(myht);
}
count = zend_array_count(myht);
php_printf("%sarray(%d) {\n", COMMON, count);
-
ZEND_HASH_FOREACH_KEY_VAL_IND(myht, num, key, val) {
php_array_element_dump(val, num, key, level);
} ZEND_HASH_FOREACH_END();
- if (level > 1 && !(GC_FLAGS(myht) & GC_IMMUTABLE)) {
- GC_UNPROTECT_RECURSION(myht);
+ if (!(GC_FLAGS(myht) & GC_IMMUTABLE)) {
+ if (level > 1) {
+ GC_UNPROTECT_RECURSION(myht);
+ }
+ GC_DELREF(myht);
}
if (level > 1) {
php_printf("%*c", level-1, ' ');
@@ -285,20 +289,26 @@ again:
break;
case IS_ARRAY:
myht = Z_ARRVAL_P(struc);
- if (level > 1 && !(GC_FLAGS(myht) & GC_IMMUTABLE)) {
- if (GC_IS_RECURSIVE(myht)) {
- PUTS("*RECURSION*\n");
- return;
+ if (!(GC_FLAGS(myht) & GC_IMMUTABLE)) {
+ if (level > 1) {
+ if (GC_IS_RECURSIVE(myht)) {
+ PUTS("*RECURSION*\n");
+ return;
+ }
+ GC_PROTECT_RECURSION(myht);
}
- GC_PROTECT_RECURSION(myht);
+ GC_ADDREF(myht);
}
count = zend_array_count(myht);
php_printf("%sarray(%d) refcount(%u){\n", COMMON, count, Z_REFCOUNTED_P(struc) ? Z_REFCOUNT_P(struc) : 1);
ZEND_HASH_FOREACH_KEY_VAL_IND(myht, index, key, val) {
zval_array_element_dump(val, index, key, level);
} ZEND_HASH_FOREACH_END();
- if (level > 1 && !(GC_FLAGS(myht) & GC_IMMUTABLE)) {
- GC_UNPROTECT_RECURSION(myht);
+ if (!(GC_FLAGS(myht) & GC_IMMUTABLE)) {
+ if (level > 1) {
+ GC_UNPROTECT_RECURSION(myht);
+ }
+ GC_DELREF(myht);
}
if (is_temp) {
zend_hash_destroy(myht);
@@ -497,6 +507,7 @@ again:
zend_error(E_WARNING, "var_export does not handle circular references");
return;
}
+ GC_ADDREF(myht);
GC_PROTECT_RECURSION(myht);
}
if (level > 1) {
@@ -507,7 +518,6 @@ again:
ZEND_HASH_FOREACH_KEY_VAL_IND(myht, index, key, val) {
php_array_element_export(val, index, key, level, buf);
} ZEND_HASH_FOREACH_END();
-
if (!(GC_FLAGS(myht) & GC_IMMUTABLE)) {
GC_UNPROTECT_RECURSION(myht);
GC_DELREF(myht);