com php-src: Fixed incorrect recursion detection: Zend/zend_h ash.c Zend/zend_object_handlers.c tests/lang/operat
ors/operator_identical_recusion-01.phpt
| From: | Dmitry Stogov | Date: | Fri, 06 Oct 2017 08:47:11 +0000 |
| Subject: | com php-src: Fixed incorrect recursion detection: Zend/zend_h ash.c Zend/zend_object_handlers.c tests/lang/operat ors/operator_identical_recusion-01.phpt |
||
| Groups: | php.cvs | ||
| Request: | Send a blank email to php-cvs+get-99641@lists.php.net to get a copy of this message | ||
Commit: f18638ca2daf0938723a5197a1e7dcd4e7f384f8
Author: Dmitry Stogov <dmitry@zend.com> Fri, 6 Oct 2017 11:47:11 +0300
Parents: 254b74b85f0d9467c937ccee8aab02e31729d49b
Branches: master
Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=f18638ca2daf0938723a5197a1e7dcd4e7f384f8
Log:
Fixed incorrect recursion detection
Changed paths:
M Zend/zend_hash.c
M Zend/zend_object_handlers.c
A tests/lang/operators/operator_identical_recusion-01.phpt
Diff:
diff --git a/Zend/zend_hash.c b/Zend/zend_hash.c
index 07dcd26..d629c09 100644
--- a/Zend/zend_hash.c
+++ b/Zend/zend_hash.c
@@ -2369,24 +2369,21 @@ ZEND_API int zend_hash_compare(HashTable *ht1, HashTable *ht2,
compare_func_t co
return 0;
}
- /* use bitwise OR to make only one conditional jump */
- if (UNEXPECTED(GC_IS_RECURSIVE(ht1) | GC_IS_RECURSIVE(ht2))) {
+ /* It's enough to protect only one of the arrays.
+ * The second one may be referenced from the first and this may cause
+ * false recursion detection.
+ */
+ if (UNEXPECTED(GC_IS_RECURSIVE(ht1))) {
zend_error_noreturn(E_ERROR, "Nesting level too deep - recursive dependency?");
}
if (!(GC_FLAGS(ht1) & GC_IMMUTABLE)) {
GC_PROTECT_RECURSION(ht1);
}
- if (!(GC_FLAGS(ht2) & GC_IMMUTABLE)) {
- GC_PROTECT_RECURSION(ht2);
- }
result = zend_hash_compare_impl(ht1, ht2, compar, ordered);
if (!(GC_FLAGS(ht1) & GC_IMMUTABLE)) {
GC_UNPROTECT_RECURSION(ht1);
}
- if (!(GC_FLAGS(ht2) & GC_IMMUTABLE)) {
- GC_UNPROTECT_RECURSION(ht2);
- }
return result;
}
diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c
index f1412ef..6e709cd 100644
--- a/Zend/zend_object_handlers.c
+++ b/Zend/zend_object_handlers.c
@@ -1448,12 +1448,15 @@ static int zend_std_compare_objects(zval *o1, zval *o2) /* {{{ */
p2 = zobj2->properties_table;
end = p1 + zobj1->ce->default_properties_count;
+ /* It's enough to protect only one of the objects.
+ * The second one may be referenced from the first and this may cause
+ * false recursion detection.
+ */
/* use bitwise OR to make only one conditional jump */
- if (UNEXPECTED(Z_IS_RECURSIVE_P(o1) | Z_IS_RECURSIVE_P(o2))) {
+ if (UNEXPECTED(Z_IS_RECURSIVE_P(o1))) {
zend_error_noreturn(E_ERROR, "Nesting level too deep - recursive dependency?");
}
Z_PROTECT_RECURSION_P(o1);
- Z_PROTECT_RECURSION_P(o2);
do {
if (Z_TYPE_P(p1) != IS_UNDEF) {
if (Z_TYPE_P(p2) != IS_UNDEF) {
@@ -1461,23 +1464,19 @@ static int zend_std_compare_objects(zval *o1, zval *o2) /* {{{ */
if (compare_function(&result, p1, p2)==FAILURE) {
Z_UNPROTECT_RECURSION_P(o1);
- Z_UNPROTECT_RECURSION_P(o2);
return 1;
}
if (Z_LVAL(result) != 0) {
Z_UNPROTECT_RECURSION_P(o1);
- Z_UNPROTECT_RECURSION_P(o2);
return Z_LVAL(result);
}
} else {
Z_UNPROTECT_RECURSION_P(o1);
- Z_UNPROTECT_RECURSION_P(o2);
return 1;
}
} else {
if (Z_TYPE_P(p2) != IS_UNDEF) {
Z_UNPROTECT_RECURSION_P(o1);
- Z_UNPROTECT_RECURSION_P(o2);
return 1;
}
}
@@ -1485,7 +1484,6 @@ static int zend_std_compare_objects(zval *o1, zval *o2) /* {{{ */
p2++;
} while (p1 != end);
Z_UNPROTECT_RECURSION_P(o1);
- Z_UNPROTECT_RECURSION_P(o2);
return 0;
} else {
if (!zobj1->properties) {
diff --git a/tests/lang/operators/operator_identical_recusion-01.phpt
b/tests/lang/operators/operator_identical_recusion-01.phpt
new file mode 100644
index 0000000..3680e30
--- /dev/null
+++ b/tests/lang/operators/operator_identical_recusion-01.phpt
@@ -0,0 +1,10 @@
+--TEST--
+Test === operator : False recursion detection
+--FILE--
+<?php
+$n = 0;
+$a = [[$n]];
+$b = [&$a];
+var_dump($a === $b);
+--EXPECT--
+bool(false)
\ No newline at end of file