mirror of
https://github.com/php/php-src.git
synced 2026-03-24 00:02:20 +01:00
Fixed bug #63882 (zend_std_compare_objects crash on recursion)
This commit is contained in:
1
NEWS
1
NEWS
@@ -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)
|
||||
|
||||
15
Zend/tests/bug63882.phpt
Normal file
15
Zend/tests/bug63882.phpt
Normal file
@@ -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
|
||||
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user