summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXinchen Hui <laruence@gmail.com>2015-10-17 05:28:49 -0700
committerAnatol Belski <ab@php.net>2015-10-23 11:09:42 +0200
commit8836fdd4ed402c70e55b4646c605e6da4dc3b344 (patch)
treedc1b2a8ac0c67070200635ecfca0a5db2b7fd5a2
parentb01a607d7381e5cc84103956cf036d8c97776388 (diff)
downloadphp-git-8836fdd4ed402c70e55b4646c605e6da4dc3b344.tar.gz
Fixed bug #70730 (Incorrect ArrayObject serialization if unset is called in serialize())
It's possible to fixed this in SPL side, but it will be ugly, and we should make serialize more robust, so I prefer fix it in serialize side.
-rw-r--r--ext/spl/tests/bug70730.phpt44
-rw-r--r--ext/standard/var.c30
2 files changed, 59 insertions, 15 deletions
diff --git a/ext/spl/tests/bug70730.phpt b/ext/spl/tests/bug70730.phpt
new file mode 100644
index 0000000000..5710c9586d
--- /dev/null
+++ b/ext/spl/tests/bug70730.phpt
@@ -0,0 +1,44 @@
+--TEST--
+Bug #70730 (Incorrect ArrayObject serialization if unset is called in serialize())
+--FILE--
+<?php
+class A extends \ArrayObject
+{
+ protected $foo;
+
+ public function __construct()
+ {
+ $this->foo = 'bar';
+ }
+
+ public function serialize()
+ {
+ unset($this->foo);
+ $result = parent::serialize();
+ $this->foo = 'bar';
+ return $result;
+ }
+}
+
+$a = new A();
+$a->append('item1');
+$a->append('item2');
+$a->append('item3');
+$b = new A();
+$b->unserialize($a->serialize());
+var_dump($b);
+?>
+--EXPECTF--
+object(A)#%d (2) {
+ ["foo":protected]=>
+ string(3) "bar"
+ ["storage":"ArrayObject":private]=>
+ array(3) {
+ [0]=>
+ string(5) "item1"
+ [1]=>
+ string(5) "item2"
+ [2]=>
+ string(5) "item3"
+ }
+}
diff --git a/ext/standard/var.c b/ext/standard/var.c
index 5de32f9c3e..72b2dd5ed5 100644
--- a/ext/standard/var.c
+++ b/ext/standard/var.c
@@ -35,7 +35,7 @@
#define COMMON (is_ref ? "&" : "")
/* }}} */
-static uint32_t zend_hash_recalc_elements(HashTable *ht) /* {{{ */
+static uint32_t php_array_recalc_elements(HashTable *ht) /* {{{ */
{
zval *val;
uint32_t num = ht->nNumOfElements;
@@ -52,12 +52,12 @@ static uint32_t zend_hash_recalc_elements(HashTable *ht) /* {{{ */
}
/* }}} */
-static uint32_t zend_obj_num_elements(HashTable *ht) /* {{{ */
+static uint32_t php_array_num_elements(HashTable *ht) /* {{{ */
{
uint32_t num = ht->nNumOfElements;
if (UNEXPECTED(ht->u.v.flags & HASH_FLAG_HAS_EMPTY_IND)) {
- num = zend_hash_recalc_elements(ht);
+ num = php_array_recalc_elements(ht);
if (UNEXPECTED(ht->nNumOfElements == num)) {
ht->u.v.flags &= ~HASH_FLAG_HAS_EMPTY_IND;
}
@@ -151,9 +151,9 @@ again:
return;
}
if (UNEXPECTED(Z_SYMBOLTABLE_P(struc))) {
- count = zend_hash_recalc_elements(myht);
+ count = php_array_recalc_elements(myht);
} else {
- count = zend_hash_num_elements(myht);
+ count = php_array_num_elements(myht);
}
php_printf("%sarray(%d) {\n", COMMON, count);
is_temp = 0;
@@ -182,7 +182,7 @@ again:
myht = Z_OBJDEBUG_P(struc, is_temp);
class_name = Z_OBJ_HANDLER_P(struc, get_class_name)(Z_OBJ_P(struc));
- php_printf("%sobject(%s)#%d (%d) {\n", COMMON, ZSTR_VAL(class_name), Z_OBJ_HANDLE_P(struc), myht ? zend_obj_num_elements(myht) : 0);
+ php_printf("%sobject(%s)#%d (%d) {\n", COMMON, ZSTR_VAL(class_name), Z_OBJ_HANDLE_P(struc), myht ? php_array_num_elements(myht) : 0);
zend_string_release(class_name);
if (myht) {
@@ -325,9 +325,9 @@ again:
return;
}
if (UNEXPECTED(Z_SYMBOLTABLE_P(struc))) {
- count = zend_hash_recalc_elements(myht);
+ count = php_array_recalc_elements(myht);
} else {
- count = zend_hash_num_elements(myht);
+ count = php_array_num_elements(myht);
}
php_printf("%sarray(%d) refcount(%u){\n", COMMON, count, Z_REFCOUNTED_P(struc) ? Z_REFCOUNT_P(struc) : 1);
ZEND_HASH_FOREACH_KEY_VAL_IND(myht, index, key, val) {
@@ -356,7 +356,7 @@ again:
}
}
class_name = Z_OBJ_HANDLER_P(struc, get_class_name)(Z_OBJ_P(struc));
- php_printf("%sobject(%s)#%d (%d) refcount(%u){\n", COMMON, ZSTR_VAL(class_name), Z_OBJ_HANDLE_P(struc), myht ? zend_obj_num_elements(myht) : 0, Z_REFCOUNT_P(struc));
+ php_printf("%sobject(%s)#%d (%d) refcount(%u){\n", COMMON, ZSTR_VAL(class_name), Z_OBJ_HANDLE_P(struc), myht ? php_array_num_elements(myht) : 0, Z_REFCOUNT_P(struc));
zend_string_release(class_name);
if (myht) {
ZEND_HASH_FOREACH_KEY_VAL_IND(myht, index, key, val) {
@@ -708,13 +708,13 @@ static void php_var_serialize_class(smart_str *buf, zval *struc, zval *retval_pt
if (Z_TYPE_P(retval_ptr) == IS_ARRAY) {
ht = Z_ARRVAL_P(retval_ptr);
if (UNEXPECTED(Z_SYMBOLTABLE_P(struc))) {
- count = zend_hash_recalc_elements(ht);
+ count = php_array_recalc_elements(ht);
} else {
- count = zend_hash_num_elements(ht);
+ count = php_array_num_elements(ht);
}
} else if (Z_TYPE_P(retval_ptr) == IS_OBJECT) {
ht = Z_OBJPROP_P(retval_ptr);
- count = zend_obj_num_elements(ht);
+ count = php_array_num_elements(ht);
if (incomplete_class) {
--count;
}
@@ -936,16 +936,16 @@ again:
smart_str_appendl(buf, "a:", 2);
myht = Z_ARRVAL_P(struc);
if (UNEXPECTED(Z_SYMBOLTABLE_P(struc))) {
- i = zend_hash_recalc_elements(myht);
+ i = php_array_recalc_elements(myht);
} else {
- i = zend_hash_num_elements(myht);
+ i = php_array_num_elements(myht);
}
} else {
incomplete_class = php_var_serialize_class_name(buf, struc);
myht = Z_OBJPROP_P(struc);
/* count after serializing name, since php_var_serialize_class_name
* changes the count if the variable is incomplete class */
- i = zend_obj_num_elements(myht);
+ i = php_array_num_elements(myht);
if (i > 0 && incomplete_class) {
--i;
}