mirror of
https://github.com/php/php-src.git
synced 2024-09-22 02:17:32 +00:00
Fixed bug #43918 (Segmentation fault in garbage collector)
This commit is contained in:
parent
b989cba092
commit
58433c9b11
44
Zend/tests/bug43918.phpt
Normal file
44
Zend/tests/bug43918.phpt
Normal file
@ -0,0 +1,44 @@
|
||||
--TEST--
|
||||
Bug #43918 (Segmentation fault in garbage collector)
|
||||
--SKIPIF--
|
||||
<?php if (!extension_loaded("simplexml")) print "skip"; ?>
|
||||
--FILE--
|
||||
<?php
|
||||
$xmlstr = <<<XML
|
||||
<?xml version='1.0' standalone='yes'?>
|
||||
<movies>
|
||||
<movie>
|
||||
<title>TEST</title>
|
||||
</movie>
|
||||
<movie>
|
||||
<title>TEST</title>
|
||||
</movie>
|
||||
<movie>
|
||||
<title>TEST</title>
|
||||
</movie>
|
||||
<movie>
|
||||
<title>TEST</title>
|
||||
</movie>
|
||||
<movie>
|
||||
<title>TEST</title>
|
||||
</movie>
|
||||
<movie>
|
||||
<title>TEST</title>
|
||||
</movie>
|
||||
<movie>
|
||||
<title>TEST</title>
|
||||
</movie>
|
||||
</movies>
|
||||
XML;
|
||||
|
||||
$Array = array( );
|
||||
for( $XX = 0; $XX < 2000; ++$XX )
|
||||
{
|
||||
$Array[] = $xml = new SimpleXMLElement($xmlstr);
|
||||
}
|
||||
|
||||
gc_collect_cycles( );
|
||||
echo "ok\n";
|
||||
?>
|
||||
--EXPECT--
|
||||
ok
|
@ -47,6 +47,7 @@ static void root_buffer_dtor(zend_gc_globals *gc_globals TSRMLS_DC)
|
||||
static void gc_globals_ctor_ex(zend_gc_globals *gc_globals TSRMLS_DC)
|
||||
{
|
||||
gc_globals->gc_enabled = 0;
|
||||
gc_globals->gc_active = 0;
|
||||
|
||||
gc_globals->buf = NULL;
|
||||
|
||||
@ -156,8 +157,11 @@ ZEND_API void gc_zval_possible_root(zval *zv TSRMLS_DC)
|
||||
zv->refcount__gc++;
|
||||
gc_collect_cycles(TSRMLS_C);
|
||||
zv->refcount__gc--;
|
||||
GC_ZVAL_SET_PURPLE(zv);
|
||||
newRoot = GC_G(unused);
|
||||
if (!newRoot) {
|
||||
return;
|
||||
}
|
||||
GC_ZVAL_SET_PURPLE(zv);
|
||||
}
|
||||
|
||||
GC_G(unused) = newRoot->prev;
|
||||
@ -183,7 +187,8 @@ ZEND_API void gc_zobj_possible_root(zval *zv TSRMLS_DC)
|
||||
{
|
||||
struct _store_object *obj;
|
||||
|
||||
if (UNEXPECTED(Z_OBJ_HT_P(zv)->get_properties == NULL)) {
|
||||
if (UNEXPECTED(Z_OBJ_HT_P(zv)->get_properties == NULL ||
|
||||
EG(objects_store).object_buckets == NULL)) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -203,9 +208,12 @@ ZEND_API void gc_zobj_possible_root(zval *zv TSRMLS_DC)
|
||||
zv->refcount__gc++;
|
||||
gc_collect_cycles(TSRMLS_C);
|
||||
zv->refcount__gc--;
|
||||
newRoot = GC_G(unused);
|
||||
if (!newRoot) {
|
||||
return;
|
||||
}
|
||||
obj = &EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(zv)].bucket.obj;
|
||||
GC_SET_PURPLE(obj->buffered);
|
||||
newRoot = GC_G(unused);
|
||||
}
|
||||
|
||||
GC_G(unused) = newRoot->prev;
|
||||
@ -240,7 +248,7 @@ static void zval_scan_black(zval *pz TSRMLS_DC)
|
||||
{
|
||||
GC_ZVAL_SET_BLACK(pz);
|
||||
|
||||
if (Z_TYPE_P(pz) == IS_OBJECT) {
|
||||
if (Z_TYPE_P(pz) == IS_OBJECT && EG(objects_store).object_buckets) {
|
||||
struct _store_object *obj = &EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].bucket.obj;
|
||||
|
||||
obj->refcount++;
|
||||
@ -282,7 +290,7 @@ static void zval_mark_grey(zval *pz TSRMLS_DC)
|
||||
GC_BENCH_INC(zval_marked_grey);
|
||||
GC_ZVAL_SET_COLOR(pz, GC_GREY);
|
||||
|
||||
if (Z_TYPE_P(pz) == IS_OBJECT) {
|
||||
if (Z_TYPE_P(pz) == IS_OBJECT && EG(objects_store).object_buckets) {
|
||||
struct _store_object *obj = &EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].bucket.obj;
|
||||
|
||||
obj->refcount--;
|
||||
@ -309,7 +317,7 @@ static void gc_mark_roots(TSRMLS_D)
|
||||
gc_root_buffer *current = GC_G(roots).next;
|
||||
|
||||
while (current != &GC_G(roots)) {
|
||||
if (current->handle) {
|
||||
if (current->handle && EG(objects_store).object_buckets) {
|
||||
struct _store_object *obj = &EG(objects_store).object_buckets[current->handle].bucket.obj;
|
||||
|
||||
if (GC_GET_COLOR(obj->buffered) == GC_PURPLE) {
|
||||
@ -337,15 +345,17 @@ static void gc_mark_roots(TSRMLS_D)
|
||||
|
||||
static void zobj_scan(zval *pz TSRMLS_DC)
|
||||
{
|
||||
struct _store_object *obj = &EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].bucket.obj;
|
||||
if (EG(objects_store).object_buckets) {
|
||||
struct _store_object *obj = &EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(pz)].bucket.obj;
|
||||
|
||||
if (GC_GET_COLOR(obj->buffered) == GC_GREY) {
|
||||
if (obj->refcount > 0) {
|
||||
zobj_scan_black(obj, pz TSRMLS_CC);
|
||||
} else {
|
||||
GC_SET_COLOR(obj->buffered, GC_WHITE);
|
||||
if (EXPECTED(Z_OBJ_HANDLER_P(pz, get_properties) != NULL)) {
|
||||
zend_hash_apply(Z_OBJPROP_P(pz), (apply_func_t) children_scan TSRMLS_CC);
|
||||
if (GC_GET_COLOR(obj->buffered) == GC_GREY) {
|
||||
if (obj->refcount > 0) {
|
||||
zobj_scan_black(obj, pz TSRMLS_CC);
|
||||
} else {
|
||||
GC_SET_COLOR(obj->buffered, GC_WHITE);
|
||||
if (EXPECTED(Z_OBJ_HANDLER_P(pz, get_properties) != NULL)) {
|
||||
zend_hash_apply(Z_OBJPROP_P(pz), (apply_func_t) children_scan TSRMLS_CC);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -400,14 +410,16 @@ static void gc_scan_roots(TSRMLS_D)
|
||||
|
||||
static void zobj_collect_white(zval *pz TSRMLS_DC)
|
||||
{
|
||||
zend_object_handle handle = Z_OBJ_HANDLE_P(pz);
|
||||
struct _store_object *obj = &EG(objects_store).object_buckets[handle].bucket.obj;
|
||||
if (EG(objects_store).object_buckets) {
|
||||
zend_object_handle handle = Z_OBJ_HANDLE_P(pz);
|
||||
struct _store_object *obj = &EG(objects_store).object_buckets[handle].bucket.obj;
|
||||
|
||||
if (obj->buffered == (gc_root_buffer*)GC_WHITE) {
|
||||
GC_SET_BLACK(obj->buffered);
|
||||
if (obj->buffered == (gc_root_buffer*)GC_WHITE) {
|
||||
GC_SET_BLACK(obj->buffered);
|
||||
|
||||
if (EXPECTED(Z_OBJ_HANDLER_P(pz, get_properties) != NULL)) {
|
||||
zend_hash_apply(Z_OBJPROP_P(pz), (apply_func_t) children_collect_white TSRMLS_CC);
|
||||
if (EXPECTED(Z_OBJ_HANDLER_P(pz, get_properties) != NULL)) {
|
||||
zend_hash_apply(Z_OBJPROP_P(pz), (apply_func_t) children_collect_white TSRMLS_CC);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -446,7 +458,7 @@ static void gc_collect_roots(TSRMLS_D)
|
||||
gc_root_buffer *current = GC_G(roots).next;
|
||||
|
||||
while (current != &GC_G(roots)) {
|
||||
if (current->handle) {
|
||||
if (current->handle && EG(objects_store).object_buckets) {
|
||||
struct _store_object *obj = &EG(objects_store).object_buckets[current->handle].bucket.obj;
|
||||
zval z;
|
||||
|
||||
@ -472,11 +484,16 @@ ZEND_API int gc_collect_cycles(TSRMLS_D)
|
||||
if (GC_G(roots).next != &GC_G(roots)) {
|
||||
zval_gc_info *p, *q;
|
||||
|
||||
if (GC_G(gc_active)) {
|
||||
return 0;
|
||||
}
|
||||
GC_G(gc_runs)++;
|
||||
GC_G(zval_to_free) = NULL;
|
||||
gc_mark_roots(TSRMLS_C);
|
||||
GC_G(gc_active) = 1;
|
||||
gc_scan_roots(TSRMLS_C);
|
||||
gc_collect_roots(TSRMLS_C);
|
||||
GC_G(gc_active) = 0;
|
||||
|
||||
p = GC_G(zval_to_free);
|
||||
GC_G(zval_to_free) = NULL;
|
||||
|
@ -98,6 +98,7 @@ typedef struct _zval_gc_info {
|
||||
|
||||
typedef struct _zend_gc_globals {
|
||||
zend_bool gc_enabled;
|
||||
zend_bool gc_active;
|
||||
|
||||
gc_root_buffer *buf; /* preallocated arrays of buffers */
|
||||
gc_root_buffer roots; /* list of possible roots of cycles */
|
||||
|
@ -1081,6 +1081,9 @@ static HashTable * sxe_get_prop_hash(zval *object, int is_debug TSRMLS_DC) /* {{
|
||||
zend_hash_init(rv, 0, NULL, ZVAL_PTR_DTOR, 0);
|
||||
}
|
||||
else if (sxe->properties) {
|
||||
if (GC_G(gc_active)) {
|
||||
return sxe->properties;
|
||||
}
|
||||
zend_hash_clean(sxe->properties);
|
||||
rv = sxe->properties;
|
||||
} else {
|
||||
|
Loading…
Reference in New Issue
Block a user