[PATCH] [ZE] (critical?) object comparison recursion bug
| From: | Wez Furlong | Date: | Sun, 29 Sep 2002 11:50:32 +0000 |
| Subject: | [PATCH] [ZE] (critical?) object comparison recursion bug | ||
| References: | 1 | Groups: | php.dev |
| Request: | Send a blank email to php-dev+get-88735@lists.php.net to get a copy of this message | ||
Here's a patch for the ZE which shortcuts the recursive comparisions
if the object properties hash tables are at the same address (therefore,
the objects are the same object).
This should save a few cycles for non-recursive objects too.
Additionally, when comparing hash tables, this patch changes the
recursion protection to return indicating that the tables are not the
same rather than raising a fatal error. I'd feel happier if we could
control this behaviour via a flag, as it is not always the best thing
to do. (Perhaps we should only enable this when checking for identity for
objects?).
--Wez.
On 09/29/02, "Wez Furlong" <wez@thebrainroom.com> wrote:
> The code below produces:
>
> Fatal error: Nesting level too deep - recursive dependency?
> in test.php on line 24
>
> This is should not happen since the objects being compared are
> the same object, so there should be no need to recusively compare the
> objects.
> Additionally, I think the comparison should bail out (without a fatal
> error) when the objects are not the same and when a recursive dependency
> is found.
>
> IMHO, this is a critical problem that should be fixed for 4.3, since it
> prevents anyone from using OO with references in a reasonable way.
>
>
> <?php
> class A {
> var $b;
>
> function A()
> {
> $this->b =& new B($this);
> }
> }
>
> class B {
> var $a;
>
> function B(&$a)
> {
> $this->a =& $a;
> }
> }
>
> $one =& new A;
> $two =& $one;
>
> if ($one == $two) { // <-- fatal error here
> echo "Same object\n";
> } else {
> echo "not the same object\n";
> }
> ?>
>
> --
> Wez Furlong
> The Brain Room Ltd.
>
>
> --
> PHP Development Mailing List <http://www.php.net/>
> To unsubscribe, visit: http://www.php.net/unsub.php
Index: zend_operators.c =================================================================== RCS file: /repository/Zend/zend_operators.c,v retrieving revision 1.125 diff -u -r1.125 zend_operators.c --- zend_operators.c 26 Sep 2002 18:39:28 -0000 1.125 +++ zend_operators.c 29 Sep 2002 11:34:19 -0000 @@ -1245,7 +1245,7 @@ if (Z_OBJCE_P(op1) != Z_OBJCE_P(op2)) { result->value.lval = 0; } else { - if (zend_hash_compare(Z_OBJPROP_P(op1), Z_OBJPROP_P(op2), (compare_func_t) hash_zval_identical_function, 1 TSRMLS_CC)==0) { + if (Z_OBJPROP_P(op1) == Z_OBJPROP_P(op2) || zend_hash_compare(Z_OBJPROP_P(op1), Z_OBJPROP_P(op2), (compare_func_t) hash_zval_identical_function, 1 TSRMLS_CC)==0) { result->value.lval = 1; } else { result->value.lval = 0; @@ -1725,7 +1725,11 @@ ZEND_API void zend_compare_symbol_tables(zval *result, HashTable *ht1, HashTable *ht2 TSRMLS_DC) { result->type = IS_LONG; - result->value.lval = zend_hash_compare(ht1, ht2, (compare_func_t) hash_zval_compare_function, 0 TSRMLS_CC); + if (ht1 == ht2) { + result->value.lval = 0; + } else { + result->value.lval = zend_hash_compare(ht1, ht2, (compare_func_t) hash_zval_compare_function, 0 TSRMLS_CC); + } }
Index: zend_operators.c =================================================================== RCS file: /repository/Zend/zend_operators.c,v retrieving revision 1.125 diff -u -r1.125 zend_operators.c --- zend_operators.c 26 Sep 2002 18:39:28 -0000 1.125 +++ zend_operators.c 29 Sep 2002 11:34:19 -0000 @@ -1245,7 +1245,7 @@ if (Z_OBJCE_P(op1) != Z_OBJCE_P(op2)) { result->value.lval = 0; } else { - if (zend_hash_compare(Z_OBJPROP_P(op1), Z_OBJPROP_P(op2), (compare_func_t) hash_zval_identical_function, 1 TSRMLS_CC)==0) { + if (Z_OBJPROP_P(op1) == Z_OBJPROP_P(op2) || zend_hash_compare(Z_OBJPROP_P(op1), Z_OBJPROP_P(op2), (compare_func_t) hash_zval_identical_function, 1 TSRMLS_CC)==0) { result->value.lval = 1; } else { result->value.lval = 0; @@ -1725,7 +1725,11 @@ ZEND_API void zend_compare_symbol_tables(zval *result, HashTable *ht1, HashTable *ht2 TSRMLS_DC) { result->type = IS_LONG; - result->value.lval = zend_hash_compare(ht1, ht2, (compare_func_t) hash_zval_compare_function, 0 TSRMLS_CC); + if (ht1 == ht2) { + result->value.lval = 0; + } else { + result->value.lval = zend_hash_compare(ht1, ht2, (compare_func_t) hash_zval_compare_function, 0 TSRMLS_CC); + } }