diff options
author | Dmitry Stogov <dmitry@zend.com> | 2013-01-09 11:30:50 +0400 |
---|---|---|
committer | Dmitry Stogov <dmitry@zend.com> | 2013-01-09 11:30:50 +0400 |
commit | f9e8678dd3a41ed8a100d8201153a41d6fd25f2e (patch) | |
tree | e13f64fafe27b54d62eb708554ccbc55383557ce | |
parent | f3b1b8516906fe900e521216c8f01e362790af30 (diff) | |
download | php-git-f9e8678dd3a41ed8a100d8201153a41d6fd25f2e.tar.gz |
Fixed bug #63882 (zend_std_compare_objects crash on recursion)
-rw-r--r-- | NEWS | 1 | ||||
-rw-r--r-- | Zend/tests/bug63882.phpt | 15 | ||||
-rw-r--r-- | Zend/zend_object_handlers.c | 26 | ||||
-rw-r--r-- | Zend/zend_objects_API.c | 1 | ||||
-rw-r--r-- | Zend/zend_objects_API.h | 1 |
5 files changed, 44 insertions, 0 deletions
@@ -5,6 +5,7 @@ PHP NEWS - Core: . Fixed bug #63943 (Bad warning text from strpos() on empty needle). (Laruence) + . Fixed bug #63882 (zend_std_compare_objects crash on recursion). (Dmitry) - Litespeed: . Fixed bug #63228 (-Werror=format-security error in lsapi code). (George) diff --git a/Zend/tests/bug63882.phpt b/Zend/tests/bug63882.phpt new file mode 100644 index 0000000000..0cc1babd49 --- /dev/null +++ b/Zend/tests/bug63882.phpt @@ -0,0 +1,15 @@ +--TEST-- +Bug #63882 (zend_std_compare_objects crash on recursion) +--FILE-- +<?php +class Test { public $x = 5; } + +$testobj1 = new Test; +$testobj2 = new Test; +$testobj1->x = $testobj1; +$testobj2->x = $testobj2; + +var_dump($testobj1 == $testobj2); +?> +--EXPECTF-- +Fatal error: Nesting level too deep - recursive dependency? in %sbug63882.php on line 9 diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c index a76dfb38ac..3881c0e870 100644 --- a/Zend/zend_object_handlers.c +++ b/Zend/zend_object_handlers.c @@ -35,6 +35,17 @@ #define Z_OBJ_P(zval_p) \ ((zend_object*)(EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(zval_p)].bucket.obj.object)) +#define Z_OBJ_PROTECT_RECURSION(zval_p) \ + do { \ + if (EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(zval_p)].apply_count++ >= 3) { \ + zend_error(E_ERROR, "Nesting level too deep - recursive dependency?"); \ + } \ + } while (0) + + +#define Z_OBJ_UNPROTECT_RECURSION(zval_p) \ + EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(zval_p)].apply_count-- + /* __X accessors explanation: @@ -1319,28 +1330,43 @@ static int zend_std_compare_objects(zval *o1, zval *o2 TSRMLS_DC) /* {{{ */ } if (!zobj1->properties && !zobj2->properties) { int i; + + Z_OBJ_PROTECT_RECURSION(o1); + Z_OBJ_PROTECT_RECURSION(o2); for (i = 0; i < zobj1->ce->default_properties_count; i++) { if (zobj1->properties_table[i]) { if (zobj2->properties_table[i]) { zval result; if (compare_function(&result, zobj1->properties_table[i], zobj2->properties_table[i] TSRMLS_CC)==FAILURE) { + Z_OBJ_UNPROTECT_RECURSION(o1); + Z_OBJ_UNPROTECT_RECURSION(o2); return 1; } if (Z_LVAL(result) != 0) { + Z_OBJ_UNPROTECT_RECURSION(o1); + Z_OBJ_UNPROTECT_RECURSION(o2); return Z_LVAL(result); } } else { + Z_OBJ_UNPROTECT_RECURSION(o1); + Z_OBJ_UNPROTECT_RECURSION(o2); return 1; } } else { if (zobj2->properties_table[i]) { + Z_OBJ_UNPROTECT_RECURSION(o1); + Z_OBJ_UNPROTECT_RECURSION(o2); return 1; } else { + Z_OBJ_UNPROTECT_RECURSION(o1); + Z_OBJ_UNPROTECT_RECURSION(o2); return 0; } } } + Z_OBJ_UNPROTECT_RECURSION(o1); + Z_OBJ_UNPROTECT_RECURSION(o2); return 0; } else { if (!zobj1->properties) { diff --git a/Zend/zend_objects_API.c b/Zend/zend_objects_API.c index 4f3561e3d7..1fe5d0c199 100644 --- a/Zend/zend_objects_API.c +++ b/Zend/zend_objects_API.c @@ -117,6 +117,7 @@ ZEND_API zend_object_handle zend_objects_store_put(void *object, zend_objects_st obj = &EG(objects_store).object_buckets[handle].bucket.obj; EG(objects_store).object_buckets[handle].destructor_called = 0; EG(objects_store).object_buckets[handle].valid = 1; + EG(objects_store).object_buckets[handle].apply_count = 0; obj->refcount = 1; GC_OBJ_INIT(obj); diff --git a/Zend/zend_objects_API.h b/Zend/zend_objects_API.h index c973b7a20c..a6ea9b8c02 100644 --- a/Zend/zend_objects_API.h +++ b/Zend/zend_objects_API.h @@ -31,6 +31,7 @@ typedef void (*zend_objects_store_clone_t)(void *object, void **object_clone TSR typedef struct _zend_object_store_bucket { zend_bool destructor_called; zend_bool valid; + zend_uchar apply_count; union _store_bucket { struct _store_object { void *object; |