Skip to content

Commit 1b5ad03

Browse files
committed
Merge branch 'bug69227' of https://github.com/Vektah/php-src into PHP-5.5
2 parents a9d73f0 + 482500b commit 1b5ad03

File tree

3 files changed

+37
-30
lines changed

3 files changed

+37
-30
lines changed

ext/spl/spl_observer.c

Lines changed: 22 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,8 @@ typedef struct _spl_SplObjectStorage { /* {{{ */
8686
long flags;
8787
zend_function *fptr_get_hash;
8888
HashTable *debug_info;
89+
zval **gcdata;
90+
long gcdata_len;
8991
} spl_SplObjectStorage; /* }}} */
9092

9193
/* {{{ storage is an assoc aray of [zend_object_value]=>[zval *obj, zval *inf] */
@@ -107,6 +109,10 @@ void spl_SplOjectStorage_free_storage(void *object TSRMLS_DC) /* {{{ */
107109
efree(intern->debug_info);
108110
}
109111

112+
if (intern->gcdata != NULL) {
113+
efree(intern->gcdata);
114+
}
115+
110116
efree(object);
111117
} /* }}} */
112118

@@ -263,6 +269,9 @@ static zend_object_value spl_object_storage_new_ex(zend_class_entry *class_type,
263269
zend_object_std_init(&intern->std, class_type TSRMLS_CC);
264270
object_properties_init(&intern->std, class_type);
265271

272+
intern->gcdata = NULL;
273+
intern->gcdata_len = 0;
274+
266275
zend_hash_init(&intern->storage, 0, NULL, (void (*)(void *))spl_object_storage_dtor, 0);
267276

268277
retval.handle = zend_objects_store_put(intern, (zend_objects_store_dtor_t)zend_objects_destroy_object, (zend_objects_free_object_storage_t) spl_SplOjectStorage_free_storage, NULL TSRMLS_CC);
@@ -324,7 +333,6 @@ static HashTable* spl_object_storage_debug_info(zval *obj, int *is_temp TSRMLS_D
324333
*is_temp = 0;
325334

326335
props = Z_OBJPROP_P(obj);
327-
zend_hash_del(props, "\x00gcdata", sizeof("\x00gcdata"));
328336

329337
if (intern->debug_info == NULL) {
330338
ALLOC_HASHTABLE(intern->debug_info);
@@ -360,46 +368,31 @@ static HashTable* spl_object_storage_debug_info(zval *obj, int *is_temp TSRMLS_D
360368
}
361369
/* }}} */
362370

363-
/* overriden for garbage collection
364-
* This is very hacky */
371+
/* overriden for garbage collection */
365372
static HashTable *spl_object_storage_get_gc(zval *obj, zval ***table, int *n TSRMLS_DC) /* {{{ */
366373
{
367374
spl_SplObjectStorage *intern = (spl_SplObjectStorage*)zend_object_store_get_object(obj TSRMLS_CC);
368375
spl_SplObjectStorageElement *element;
369-
HashTable *props;
370376
HashPosition pos;
371-
zval *gcdata_arr = NULL,
372-
**gcdata_arr_pp;
373-
374-
props = std_object_handlers.get_properties(obj TSRMLS_CC);
375-
376-
*table = NULL;
377-
*n = 0;
377+
long i = 0;
378+
long requiredLength = intern->storage.nNumOfElements * 2;
378379

379-
/* clean \x00gcdata, as it may be out of date */
380-
if (zend_hash_find(props, "\x00gcdata", sizeof("\x00gcdata"), (void**) &gcdata_arr_pp) == SUCCESS) {
381-
gcdata_arr = *gcdata_arr_pp;
382-
zend_hash_clean(Z_ARRVAL_P(gcdata_arr));
383-
}
384-
385-
if (gcdata_arr == NULL) {
386-
MAKE_STD_ZVAL(gcdata_arr);
387-
array_init(gcdata_arr);
388-
/* don't decrease refcount of members when destroying */
389-
Z_ARRVAL_P(gcdata_arr)->pDestructor = NULL;
390-
391-
/* name starts with \x00 to make tampering in user-land more difficult */
392-
zend_hash_add(props, "\x00gcdata", sizeof("\x00gcdata"), &gcdata_arr, sizeof(gcdata_arr), NULL);
380+
if (requiredLength > intern->gcdata_len) {
381+
intern->gcdata = (zval**)erealloc(intern->gcdata, sizeof(zval*) * requiredLength);
382+
intern->gcdata_len = requiredLength;
393383
}
394384

395385
zend_hash_internal_pointer_reset_ex(&intern->storage, &pos);
396386
while (zend_hash_get_current_data_ex(&intern->storage, (void **)&element, &pos) == SUCCESS) {
397-
add_next_index_zval(gcdata_arr, element->obj);
398-
add_next_index_zval(gcdata_arr, element->inf);
387+
intern->gcdata[i++] = element->obj;
388+
intern->gcdata[i++] = element->inf;
399389
zend_hash_move_forward_ex(&intern->storage, &pos);
400390
}
401391

402-
return props;
392+
*table = intern->gcdata;
393+
*n = i;
394+
395+
return std_object_handlers.get_properties(obj TSRMLS_CC);
403396
}
404397
/* }}} */
405398

@@ -782,7 +775,7 @@ SPL_METHOD(SplObjectStorage, serialize)
782775
INIT_PZVAL(&members);
783776
Z_ARRVAL(members) = zend_std_get_properties(getThis() TSRMLS_CC);
784777
Z_TYPE(members) = IS_ARRAY;
785-
zend_hash_del(Z_ARRVAL(members), "\x00gcdata", sizeof("\x00gcdata"));
778+
786779
pmembers = &members;
787780
php_var_serialize(&buf, &pmembers, &var_hash TSRMLS_CC); /* finishes the string */
788781

ext/spl/tests/bug53071.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,5 +23,5 @@ echo "Done.\n";
2323

2424
?>
2525
--EXPECTF--
26-
int(5)
26+
int(4)
2727
Done.

ext/spl/tests/bug65967.phpt

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
--TEST--
2+
Bug #65967: SplObjectStorage contains corrupt member variables after garbage collection
3+
--INI--
4+
zend.enable_gc=1
5+
--FILE--
6+
<?php
7+
$objstore = new SplObjectStorage();
8+
gc_collect_cycles();
9+
10+
var_export($objstore);
11+
?>
12+
--EXPECT--
13+
SplObjectStorage::__set_state(array(
14+
))

0 commit comments

Comments
 (0)