Skip to content

Commit ffaee27

Browse files
committed
Fixed bug #76427 (Segfault in zend_objects_store_put)
1 parent eebad01 commit ffaee27

File tree

6 files changed

+33
-7
lines changed

6 files changed

+33
-7
lines changed

NEWS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ PHP NEWS
33
?? ??? ????, PHP 7.3.0alpha2
44

55
- Core:
6+
. Fixed bug #76427 (Segfault in zend_objects_store_put). (Laruence)
67
. Fixed bug #76422 (ftruncate fails on files > 2GB). (Anatol)
78

89
- EXIF:

Zend/tests/generators/bug76427.phpt

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
--TEST--
2+
Bug #76427 (Segfault in zend_objects_store_put)
3+
--FILE--
4+
<?php
5+
$func = function () {
6+
yield 2;
7+
};
8+
9+
$a = new stdclass();
10+
$b = new stdclass();
11+
$a->b = $b;
12+
$b->a = $a;
13+
14+
$func = $a->func = $func();
15+
16+
unset($b);
17+
unset($a);
18+
unset($func);
19+
20+
var_dump(gc_collect_cycles());
21+
22+
?>
23+
--EXPECT--
24+
int(4)

Zend/zend_gc.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1401,8 +1401,8 @@ ZEND_API int zend_gc_collect_cycles(void)
14011401
GC_DELREF(obj);
14021402
}
14031403
}
1404-
SET_OBJ_BUCKET_NUMBER(EG(objects_store).object_buckets[obj->handle], EG(objects_store).free_list_head);
1405-
EG(objects_store).free_list_head = obj->handle;
1404+
1405+
ZEND_OBJECTS_STORE_ADD_TO_FREE_LIST(obj->handle);
14061406
current->ref = GC_MAKE_GARBAGE(((char*)obj) - obj->handlers->offset);
14071407
} else if (GC_TYPE(p) == IS_ARRAY) {
14081408
zend_array *arr = (zend_array*)p;

Zend/zend_generators.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -145,7 +145,8 @@ ZEND_API void zend_generator_close(zend_generator *generator, zend_bool finished
145145
}
146146

147147
/* Free closure object */
148-
if (EX_CALL_INFO() & ZEND_CALL_CLOSURE) {
148+
if ((EX_CALL_INFO() & ZEND_CALL_CLOSURE) &&
149+
EXPECTED(GC_TYPE(ZEND_CLOSURE_OBJECT(EX(func))) == IS_OBJECT)) {
149150
OBJ_RELEASE(ZEND_CLOSURE_OBJECT(EX(func)));
150151
}
151152

Zend/zend_objects_API.c

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -150,10 +150,6 @@ ZEND_API void ZEND_FASTCALL zend_objects_store_put(zend_object *object)
150150
EG(objects_store).object_buckets[handle] = object;
151151
}
152152

153-
#define ZEND_OBJECTS_STORE_ADD_TO_FREE_LIST(handle) \
154-
SET_OBJ_BUCKET_NUMBER(EG(objects_store).object_buckets[handle], EG(objects_store).free_list_head); \
155-
EG(objects_store).free_list_head = handle;
156-
157153
ZEND_API void ZEND_FASTCALL zend_objects_store_del(zend_object *object) /* {{{ */
158154
{
159155
/* Make sure we hold a reference count during the destructor call

Zend/zend_objects_API.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@
3737
(o) = (zend_object*)((((zend_uintptr_t)(n)) << 1) | OBJ_BUCKET_INVALID); \
3838
} while (0)
3939

40+
#define ZEND_OBJECTS_STORE_ADD_TO_FREE_LIST(h) do { \
41+
SET_OBJ_BUCKET_NUMBER(EG(objects_store).object_buckets[(h)], EG(objects_store).free_list_head); \
42+
EG(objects_store).free_list_head = (h); \
43+
} while (0)
4044

4145
#define OBJ_RELEASE(obj) zend_object_release(obj)
4246

0 commit comments

Comments
 (0)