summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXinchen Hui <laruence@php.net>2015-03-14 01:01:02 +0800
committerXinchen Hui <laruence@php.net>2015-03-14 01:01:02 +0800
commite827d1a424adf7238dbd43154f9ff938592bdce7 (patch)
treeeab8521235d444c6d3a825f7c0dd9692908cbaa2
parentf97b000430932c8e963f4423785019c5fbb70b0c (diff)
parent669c7104c3dbac643697382bdb924f26ee99ecd4 (diff)
downloadphp-git-e827d1a424adf7238dbd43154f9ff938592bdce7.tar.gz
Merge branch 'PHP-5.6'
Conflicts: ext/spl/spl_observer.c
-rw-r--r--ext/spl/spl_observer.c46
-rw-r--r--ext/spl/tests/bug53071.phpt2
-rw-r--r--ext/spl/tests/bug65967.phpt14
-rw-r--r--ext/spl/tests/bug69227.phpt14
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