Skip to content

Commit 396bc00

Browse files
committed
Merge branch 'PHP-5.5' into PHP-5.6
2 parents 4b930e1 + ed59370 commit 396bc00

File tree

4 files changed

+47
-30
lines changed

4 files changed

+47
-30
lines changed

ext/spl/spl_observer.c

Lines changed: 18 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,8 @@ typedef struct _spl_SplObjectStorage { /* {{{ */
8787
long flags;
8888
zend_function *fptr_get_hash;
8989
HashTable *debug_info;
90+
zval **gcdata;
91+
long gcdata_num;
9092
} spl_SplObjectStorage; /* }}} */
9193

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

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

@@ -325,7 +331,6 @@ static HashTable* spl_object_storage_debug_info(zval *obj, int *is_temp TSRMLS_D
325331
*is_temp = 0;
326332

327333
props = Z_OBJPROP_P(obj);
328-
zend_hash_del(props, "\x00gcdata", sizeof("\x00gcdata"));
329334

330335
if (intern->debug_info == NULL) {
331336
ALLOC_HASHTABLE(intern->debug_info);
@@ -361,46 +366,30 @@ static HashTable* spl_object_storage_debug_info(zval *obj, int *is_temp TSRMLS_D
361366
}
362367
/* }}} */
363368

364-
/* overriden for garbage collection
365-
* This is very hacky */
369+
/* overriden for garbage collection */
366370
static HashTable *spl_object_storage_get_gc(zval *obj, zval ***table, int *n TSRMLS_DC) /* {{{ */
367371
{
372+
long i = 0;
368373
spl_SplObjectStorage *intern = (spl_SplObjectStorage*)zend_object_store_get_object(obj TSRMLS_CC);
369374
spl_SplObjectStorageElement *element;
370-
HashTable *props;
371375
HashPosition pos;
372-
zval *gcdata_arr = NULL,
373-
**gcdata_arr_pp;
374-
375-
props = std_object_handlers.get_properties(obj TSRMLS_CC);
376-
377-
*table = NULL;
378-
*n = 0;
379376

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

396382
zend_hash_internal_pointer_reset_ex(&intern->storage, &pos);
397383
while (zend_hash_get_current_data_ex(&intern->storage, (void **)&element, &pos) == SUCCESS) {
398-
add_next_index_zval(gcdata_arr, element->obj);
399-
add_next_index_zval(gcdata_arr, element->inf);
384+
intern->gcdata[i++] = element->obj;
385+
intern->gcdata[i++] = element->inf;
400386
zend_hash_move_forward_ex(&intern->storage, &pos);
401387
}
402388

403-
return props;
389+
*table = intern->gcdata;
390+
*n = i;
391+
392+
return std_object_handlers.get_properties(obj TSRMLS_CC);
404393
}
405394
/* }}} */
406395

@@ -799,7 +788,7 @@ SPL_METHOD(SplObjectStorage, serialize)
799788
INIT_PZVAL(&members);
800789
Z_ARRVAL(members) = zend_std_get_properties(getThis() TSRMLS_CC);
801790
Z_TYPE(members) = IS_ARRAY;
802-
zend_hash_del(Z_ARRVAL(members), "\x00gcdata", sizeof("\x00gcdata"));
791+
803792
pmembers = &members;
804793
php_var_serialize(&buf, &pmembers, &var_hash TSRMLS_CC); /* finishes the string */
805794

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+
))

ext/spl/tests/bug69227.phpt

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
--TEST--
2+
Bug #69227 (Use after free in zval_scan caused by spl_object_storage_get_gc)
3+
--INI--
4+
zend.enable_gc=1
5+
--FILE--
6+
<?php
7+
8+
$s = new SplObjectStorage();
9+
$s->attach($s);
10+
gc_collect_cycles();
11+
echo "ok";
12+
?>
13+
--EXPECT--
14+
ok

0 commit comments

Comments
 (0)