summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorXinchen Hui <laruence@gmail.com>2015-10-17 05:28:49 -0700
committerXinchen Hui <laruence@gmail.com>2015-10-17 05:28:49 -0700
commite2d6090043aed271d18a4d157cbb64138481c9ed (patch)
tree467ed60f559910d979e3e98520adf43f3032fcf5
parentd4df6641c871e23478c3137365f682c38d8d95a3 (diff)
downloadphp-git-e2d6090043aed271d18a4d157cbb64138481c9ed.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--NEWS12
-rw-r--r--ext/spl/tests/bug70730.phpt44
-rw-r--r--ext/standard/var.c30
3 files changed, 67 insertions, 19 deletions
diff --git a/NEWS b/NEWS
index 29bb0e41df..6343dc6db5 100644
--- a/NEWS
+++ b/NEWS
@@ -6,14 +6,18 @@ PHP NEWS
. Fixed bug #70689 (Exception handler does not work as expected). (Laruence)
. Fixed bug #70430 (Stack buffer overflow in zend_language_parser()). (Nikita)
-- SOAP:
- . Fixed bug #70715 (Segmentation fault inside soap client). (Laruence)
- . Fixed bug #70709 (SOAP Client generates Segfault). (Laruence)
-
- Opcache:
. Fixed bug #70724 (Undefined Symbols from opcache.so on Mac OS X 10.10).
(Laruence)
+- SPL:
+ . Fixed bug #70730 (Incorrect ArrayObject serialization if unset is called
+ in serialize()). (Laruence)
+
+- SOAP:
+ . Fixed bug #70715 (Segmentation fault inside soap client). (Laruence)
+ . Fixed bug #70709 (SOAP Client generates Segfault). (Laruence)
+
- XSL:
. Fixed bug #70678 (PHP7 returns true when false is expected). (Felipe)
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;
}