Skip to content

Commit f9e8678

Browse files
committed
Fixed bug #63882 (zend_std_compare_objects crash on recursion)
1 parent f3b1b85 commit f9e8678

File tree

5 files changed

+44
-0
lines changed

5 files changed

+44
-0
lines changed

NEWS

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ PHP NEWS
55
- Core:
66
. Fixed bug #63943 (Bad warning text from strpos() on empty needle).
77
(Laruence)
8+
. Fixed bug #63882 (zend_std_compare_objects crash on recursion). (Dmitry)
89

910
- Litespeed:
1011
. Fixed bug #63228 (-Werror=format-security error in lsapi code). (George)

Zend/tests/bug63882.phpt

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
--TEST--
2+
Bug #63882 (zend_std_compare_objects crash on recursion)
3+
--FILE--
4+
<?php
5+
class Test { public $x = 5; }
6+
7+
$testobj1 = new Test;
8+
$testobj2 = new Test;
9+
$testobj1->x = $testobj1;
10+
$testobj2->x = $testobj2;
11+
12+
var_dump($testobj1 == $testobj2);
13+
?>
14+
--EXPECTF--
15+
Fatal error: Nesting level too deep - recursive dependency? in %sbug63882.php on line 9

Zend/zend_object_handlers.c

+26
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,17 @@
3535
#define Z_OBJ_P(zval_p) \
3636
((zend_object*)(EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(zval_p)].bucket.obj.object))
3737

38+
#define Z_OBJ_PROTECT_RECURSION(zval_p) \
39+
do { \
40+
if (EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(zval_p)].apply_count++ >= 3) { \
41+
zend_error(E_ERROR, "Nesting level too deep - recursive dependency?"); \
42+
} \
43+
} while (0)
44+
45+
46+
#define Z_OBJ_UNPROTECT_RECURSION(zval_p) \
47+
EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(zval_p)].apply_count--
48+
3849
/*
3950
__X accessors explanation:
4051
@@ -1319,28 +1330,43 @@ static int zend_std_compare_objects(zval *o1, zval *o2 TSRMLS_DC) /* {{{ */
13191330
}
13201331
if (!zobj1->properties && !zobj2->properties) {
13211332
int i;
1333+
1334+
Z_OBJ_PROTECT_RECURSION(o1);
1335+
Z_OBJ_PROTECT_RECURSION(o2);
13221336
for (i = 0; i < zobj1->ce->default_properties_count; i++) {
13231337
if (zobj1->properties_table[i]) {
13241338
if (zobj2->properties_table[i]) {
13251339
zval result;
13261340

13271341
if (compare_function(&result, zobj1->properties_table[i], zobj2->properties_table[i] TSRMLS_CC)==FAILURE) {
1342+
Z_OBJ_UNPROTECT_RECURSION(o1);
1343+
Z_OBJ_UNPROTECT_RECURSION(o2);
13281344
return 1;
13291345
}
13301346
if (Z_LVAL(result) != 0) {
1347+
Z_OBJ_UNPROTECT_RECURSION(o1);
1348+
Z_OBJ_UNPROTECT_RECURSION(o2);
13311349
return Z_LVAL(result);
13321350
}
13331351
} else {
1352+
Z_OBJ_UNPROTECT_RECURSION(o1);
1353+
Z_OBJ_UNPROTECT_RECURSION(o2);
13341354
return 1;
13351355
}
13361356
} else {
13371357
if (zobj2->properties_table[i]) {
1358+
Z_OBJ_UNPROTECT_RECURSION(o1);
1359+
Z_OBJ_UNPROTECT_RECURSION(o2);
13381360
return 1;
13391361
} else {
1362+
Z_OBJ_UNPROTECT_RECURSION(o1);
1363+
Z_OBJ_UNPROTECT_RECURSION(o2);
13401364
return 0;
13411365
}
13421366
}
13431367
}
1368+
Z_OBJ_UNPROTECT_RECURSION(o1);
1369+
Z_OBJ_UNPROTECT_RECURSION(o2);
13441370
return 0;
13451371
} else {
13461372
if (!zobj1->properties) {

Zend/zend_objects_API.c

+1
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,7 @@ ZEND_API zend_object_handle zend_objects_store_put(void *object, zend_objects_st
117117
obj = &EG(objects_store).object_buckets[handle].bucket.obj;
118118
EG(objects_store).object_buckets[handle].destructor_called = 0;
119119
EG(objects_store).object_buckets[handle].valid = 1;
120+
EG(objects_store).object_buckets[handle].apply_count = 0;
120121

121122
obj->refcount = 1;
122123
GC_OBJ_INIT(obj);

Zend/zend_objects_API.h

+1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ typedef void (*zend_objects_store_clone_t)(void *object, void **object_clone TSR
3131
typedef struct _zend_object_store_bucket {
3232
zend_bool destructor_called;
3333
zend_bool valid;
34+
zend_uchar apply_count;
3435
union _store_bucket {
3536
struct _store_object {
3637
void *object;

0 commit comments

Comments
 (0)