]> granicus.if.org Git - php/commitdiff
Fixed bug #70730 (Incorrect ArrayObject serialization if unset is called in serialize())
authorXinchen Hui <laruence@gmail.com>
Sat, 17 Oct 2015 12:28:49 +0000 (05:28 -0700)
committerXinchen Hui <laruence@gmail.com>
Sat, 17 Oct 2015 12:28:49 +0000 (05:28 -0700)
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.

NEWS
ext/spl/tests/bug70730.phpt [new file with mode: 0644]
ext/standard/var.c

diff --git a/NEWS b/NEWS
index 29bb0e41df1b672f63e499ab3e2b8b22cc46aacb..6343dc6db5c93f193c2f40482d44b8f4a4a79adb 100644 (file)
--- 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 (file)
index 0000000..5710c95
--- /dev/null
@@ -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"
+  }
+}
index 5de32f9c3e8f9cdbfeda222817cd613617d8f721..72b2dd5ed5dfdd4374d62a8a39c4f90a413c6e4f 100644 (file)
@@ -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;
                                }