diff options
author | Xinchen Hui <laruence@php.net> | 2015-03-14 01:01:02 +0800 |
---|---|---|
committer | Xinchen Hui <laruence@php.net> | 2015-03-14 01:01:02 +0800 |
commit | e827d1a424adf7238dbd43154f9ff938592bdce7 (patch) | |
tree | eab8521235d444c6d3a825f7c0dd9692908cbaa2 | |
parent | f97b000430932c8e963f4423785019c5fbb70b0c (diff) | |
parent | 669c7104c3dbac643697382bdb924f26ee99ecd4 (diff) | |
download | php-git-e827d1a424adf7238dbd43154f9ff938592bdce7.tar.gz |
Merge branch 'PHP-5.6'
Conflicts:
ext/spl/spl_observer.c
-rw-r--r-- | ext/spl/spl_observer.c | 46 | ||||
-rw-r--r-- | ext/spl/tests/bug53071.phpt | 2 | ||||
-rw-r--r-- | ext/spl/tests/bug65967.phpt | 14 | ||||
-rw-r--r-- | ext/spl/tests/bug69227.phpt | 14 |
4 files changed, 48 insertions, 28 deletions
diff --git a/ext/spl/spl_observer.c b/ext/spl/spl_observer.c index ae35f8aec2..e727b9e493 100644 --- a/ext/spl/spl_observer.c +++ b/ext/spl/spl_observer.c @@ -86,6 +86,8 @@ typedef struct _spl_SplObjectStorage { /* {{{ */ zend_long flags; zend_function *fptr_get_hash; HashTable *debug_info; + zval *gcdata; + size_t gcdata_num; zend_object std; } spl_SplObjectStorage; /* }}} */ @@ -114,6 +116,11 @@ void spl_SplObjectStorage_free_storage(zend_object *object) /* {{{ */ zend_hash_destroy(intern->debug_info); efree(intern->debug_info); } + + if (intern->gcdata != NULL) { + efree(intern->gcdata); + } + } /* }}} */ static zend_string *spl_object_storage_get_hash(spl_SplObjectStorage *intern, zval *this, zval *obj) { @@ -317,7 +324,6 @@ static HashTable* spl_object_storage_debug_info(zval *obj, int *is_temp) /* {{{ *is_temp = 0; props = Z_OBJPROP_P(obj); - zend_hash_str_del(props, "\x00gcdata", sizeof("\x00gcdata") - 1); if (intern->debug_info == NULL) { ALLOC_HASHTABLE(intern->debug_info); @@ -350,41 +356,27 @@ static HashTable* spl_object_storage_debug_info(zval *obj, int *is_temp) /* {{{ } /* }}} */ -/* overriden for garbage collection - * This is very hacky */ +/* overriden for garbage collection */ static HashTable *spl_object_storage_get_gc(zval *obj, zval **table, int *n) /* {{{ */ { + int i = 0; spl_SplObjectStorage *intern = Z_SPLOBJSTORAGE_P(obj); spl_SplObjectStorageElement *element; - HashTable *props; - zval *gcdata_arr, tmp; - - props = std_object_handlers.get_properties(obj); - - *table = NULL; - *n = 0; - /* clean \x00gcdata, as it may be out of date */ - if ((gcdata_arr = zend_hash_str_find(props, "\x00gcdata", sizeof("\x00gcdata") - 1)) != NULL) { - zend_hash_clean(Z_ARRVAL_P(gcdata_arr)); - } - - if (gcdata_arr == NULL) { - array_init(&tmp); - /* don't decrease refcount of members when destroying */ - Z_ARRVAL_P(&tmp)->pDestructor = NULL; - - /* name starts with \x00 to make tampering in user-land more difficult */ - zend_hash_str_add(props, "\x00gcdata", sizeof("\x00gcdata") - 1, &tmp); - gcdata_arr = &tmp; + if (intern->storage.nNumOfElements > intern->gcdata_num) { + intern->gcdata_num = intern->storage.nNumOfElements * 2; + intern->gcdata = (zval*)erealloc(intern->gcdata, sizeof(zval) * intern->gcdata_num); } ZEND_HASH_FOREACH_PTR(&intern->storage, element) { - add_next_index_zval(gcdata_arr, &element->obj); - add_next_index_zval(gcdata_arr, &element->inf); + ZVAL_COPY_VALUE(&intern->gcdata[i++], &element->obj); + ZVAL_COPY_VALUE(&intern->gcdata[i++], &element->inf); } ZEND_HASH_FOREACH_END(); - return props; + *table = intern->gcdata; + *n = i; + + return std_object_handlers.get_properties(obj TSRMLS_CC); } /* }}} */ @@ -769,8 +761,8 @@ SPL_METHOD(SplObjectStorage, serialize) /* members */ smart_str_appendl(&buf, "m:", 2); + ZVAL_ARR(&members, zend_array_dup(zend_std_get_properties(getThis()))); - zend_hash_str_del(Z_ARRVAL(members), "\x00gcdata", sizeof("\x00gcdata") - 1); php_var_serialize(&buf, &members, &var_hash); /* finishes the string */ zval_ptr_dtor(&members); diff --git a/ext/spl/tests/bug53071.phpt b/ext/spl/tests/bug53071.phpt index 9d5dac4cd0..a2983ed2b2 100644 --- a/ext/spl/tests/bug53071.phpt +++ b/ext/spl/tests/bug53071.phpt @@ -23,5 +23,5 @@ echo "Done.\n"; ?> --EXPECTF-- -int(5) +int(4) Done. diff --git a/ext/spl/tests/bug65967.phpt b/ext/spl/tests/bug65967.phpt new file mode 100644 index 0000000000..e3bb6471c6 --- /dev/null +++ b/ext/spl/tests/bug65967.phpt @@ -0,0 +1,14 @@ +--TEST-- +Bug #65967: SplObjectStorage contains corrupt member variables after garbage collection +--INI-- +zend.enable_gc=1 +--FILE-- +<?php +$objstore = new SplObjectStorage(); +gc_collect_cycles(); + +var_export($objstore); +?> +--EXPECT-- +SplObjectStorage::__set_state(array( +)) diff --git a/ext/spl/tests/bug69227.phpt b/ext/spl/tests/bug69227.phpt new file mode 100644 index 0000000000..812d8bafd8 --- /dev/null +++ b/ext/spl/tests/bug69227.phpt @@ -0,0 +1,14 @@ +--TEST-- +Bug #69227 (Use after free in zval_scan caused by spl_object_storage_get_gc) +--INI-- +zend.enable_gc=1 +--FILE-- +<?php + +$s = new SplObjectStorage(); +$s->attach($s); +gc_collect_cycles(); +echo "ok"; +?> +--EXPECT-- +ok |