]> granicus.if.org Git - php/commitdiff
Fix bug #77866: Port Serializable SPL classes to use __unserialize()
authorNikita Popov <nikita.ppv@gmail.com>
Tue, 9 Apr 2019 12:57:06 +0000 (14:57 +0200)
committerNikita Popov <nikita.ppv@gmail.com>
Wed, 10 Apr 2019 07:36:39 +0000 (09:36 +0200)
Payloads created using Serializable are still supported.

13 files changed:
UPGRADING
ext/spl/spl_array.c
ext/spl/spl_dllist.c
ext/spl/spl_observer.c
ext/spl/tests/SplDoublyLinkedList_serialization.phpt
ext/spl/tests/SplObjectStorage_unserialize_nested.phpt
ext/spl/tests/array_025.phpt
ext/spl/tests/bug45826.phpt
ext/spl/tests/bug49263.phpt
ext/spl/tests/bug74669.phpt
ext/spl/tests/unserialize_errors.phpt [new file with mode: 0644]
ext/standard/tests/serialize/bug45706.phpt
ext/standard/var_unserializer.re

index 7b460da4a0202565350a6630d6586dae763549c1..33704bdb0212960d397df0cfc99e26c096d2d8a2 100644 (file)
--- a/UPGRADING
+++ b/UPGRADING
@@ -87,6 +87,11 @@ PHP 7.4 UPGRADE NOTES
   . SplPriorityQueue::setExtractFlags() will throw an exception if zero is
     passed. Previously this would generate a recoverable fatal error on the
     next extraction operation.
+  . ArrayObject, ArrayIterator, SplDoublyLinkedList and SplObjectStorage now
+    support the __serialize() + __unserialize() mechanism in addition to the
+    Serializable interface. This means that serialization payloads created on
+    older PHP versions can still be unserialized, but new payloads created by
+    PHP 7.4 will not be understood by older versions.
 
 - Standard:
   . The "o" serialization format has been removed. As it is never produced by
index ab488726df37ae6338adc092be9707cce406241e..2806f93281f4cf2b8f8d239d7b82a13f6a5fb929 100644 (file)
@@ -1812,6 +1812,80 @@ outexcept:
 
 } /* }}} */
 
+/* {{{ proto array ArrayObject::__serialize() */
+SPL_METHOD(Array, __serialize)
+{
+       spl_array_object *intern = Z_SPLARRAY_P(ZEND_THIS);
+       zval tmp;
+
+       if (zend_parse_parameters_none_throw() == FAILURE) {
+               return;
+       }
+
+       array_init(return_value);
+
+       /* flags */
+       ZVAL_LONG(&tmp, (intern->ar_flags & SPL_ARRAY_CLONE_MASK));
+       zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &tmp);
+
+       /* storage */
+       if (intern->ar_flags & SPL_ARRAY_IS_SELF) {
+               ZVAL_NULL(&tmp);
+       } else {
+               ZVAL_COPY(&tmp, &intern->array);
+       }
+       zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &tmp);
+
+       /* members */
+       ZVAL_ARR(&tmp, zend_std_get_properties(ZEND_THIS));
+       Z_TRY_ADDREF(tmp);
+       zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &tmp);
+}
+/* }}} */
+
+
+/* {{{ proto void ArrayObject::__unserialize(array data) */
+SPL_METHOD(Array, __unserialize)
+{
+       spl_array_object *intern = Z_SPLARRAY_P(ZEND_THIS);
+       HashTable *data;
+       zval *flags_zv, *storage_zv, *members_zv;
+       zend_long flags;
+
+       if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "h", &data) == FAILURE) {
+               return;
+       }
+
+       flags_zv = zend_hash_index_find(data, 0);
+       storage_zv = zend_hash_index_find(data, 1);
+       members_zv = zend_hash_index_find(data, 2);
+       if (!flags_zv || !storage_zv || !members_zv ||
+                       Z_TYPE_P(flags_zv) != IS_LONG || Z_TYPE_P(members_zv) != IS_ARRAY) {
+               zend_throw_exception(spl_ce_UnexpectedValueException,
+                       "Incomplete or ill-typed serialization data", 0);
+               return;
+       }
+
+       flags = Z_LVAL_P(flags_zv);
+       intern->ar_flags &= ~SPL_ARRAY_CLONE_MASK;
+       intern->ar_flags |= flags & SPL_ARRAY_CLONE_MASK;
+
+       if (flags & SPL_ARRAY_IS_SELF) {
+               zval_ptr_dtor(&intern->array);
+               ZVAL_UNDEF(&intern->array);
+       } else if (Z_TYPE_P(storage_zv) == IS_ARRAY) {
+               zval_ptr_dtor(&intern->array);
+               ZVAL_COPY_VALUE(&intern->array, storage_zv);
+               ZVAL_NULL(storage_zv);
+               SEPARATE_ARRAY(&intern->array);
+       } else {
+               spl_array_set_array(ZEND_THIS, intern, storage_zv, 0L, 1);
+       }
+
+       object_properties_load(&intern->std, Z_ARRVAL_P(members_zv));
+}
+/* }}} */
+
 /* {{{ arginfo and function table */
 ZEND_BEGIN_ARG_INFO_EX(arginfo_array___construct, 0, 0, 0)
        ZEND_ARG_INFO(0, input)
@@ -1884,6 +1958,8 @@ static const zend_function_entry spl_funcs_ArrayObject[] = {
        SPL_ME(Array, natcasesort,      arginfo_array_void,             ZEND_ACC_PUBLIC)
        SPL_ME(Array, unserialize,      arginfo_array_unserialize,      ZEND_ACC_PUBLIC)
        SPL_ME(Array, serialize,        arginfo_array_void,             ZEND_ACC_PUBLIC)
+       SPL_ME(Array, __unserialize,    arginfo_array_unserialize,      ZEND_ACC_PUBLIC)
+       SPL_ME(Array, __serialize,      arginfo_array_void,             ZEND_ACC_PUBLIC)
        /* ArrayObject specific */
        SPL_ME(Array, getIterator,      arginfo_array_void,             ZEND_ACC_PUBLIC)
        SPL_ME(Array, exchangeArray,    arginfo_array_exchangeArray,    ZEND_ACC_PUBLIC)
@@ -1911,6 +1987,8 @@ static const zend_function_entry spl_funcs_ArrayIterator[] = {
        SPL_ME(Array, natcasesort,      arginfo_array_void,             ZEND_ACC_PUBLIC)
        SPL_ME(Array, unserialize,      arginfo_array_unserialize,      ZEND_ACC_PUBLIC)
        SPL_ME(Array, serialize,        arginfo_array_void,             ZEND_ACC_PUBLIC)
+       SPL_ME(Array, __unserialize,    arginfo_array_unserialize,      ZEND_ACC_PUBLIC)
+       SPL_ME(Array, __serialize,      arginfo_array_void,             ZEND_ACC_PUBLIC)
        /* ArrayIterator specific */
        SPL_ME(Array, rewind,           arginfo_array_void,             ZEND_ACC_PUBLIC)
        SPL_ME(Array, current,          arginfo_array_void,             ZEND_ACC_PUBLIC)
index 2a274595f3cda3f07e1ccc3c5d6cdeb76bc7dbb7..299cf70174e0c40f93d098a8eac403cfa88a074d 100644 (file)
@@ -1220,6 +1220,67 @@ error:
 
 } /* }}} */
 
+/* {{{ proto array SplDoublyLinkedList::__serialize() */
+SPL_METHOD(SplDoublyLinkedList, __serialize)
+{
+       spl_dllist_object *intern = Z_SPLDLLIST_P(ZEND_THIS);
+       spl_ptr_llist_element *current = intern->llist->head;
+       zval tmp;
+
+       if (zend_parse_parameters_none_throw() == FAILURE) {
+               return;
+       }
+
+       array_init(return_value);
+
+       /* flags */
+       ZVAL_LONG(&tmp, intern->flags);
+       zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &tmp);
+
+       /* elements */
+       array_init_size(&tmp, intern->llist->count);
+       while (current) {
+               zend_hash_next_index_insert(Z_ARRVAL(tmp), &current->data);
+               current = current->next;
+       }
+       zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &tmp);
+
+       /* members */
+       ZVAL_ARR(&tmp, zend_std_get_properties(ZEND_THIS));
+       Z_TRY_ADDREF(tmp);
+       zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &tmp);
+} /* }}} */
+
+/* {{{ proto void SplDoublyLinkedList::__unserialize(array serialized) */
+SPL_METHOD(SplDoublyLinkedList, __unserialize) {
+       spl_dllist_object *intern = Z_SPLDLLIST_P(ZEND_THIS);
+       HashTable *data;
+       zval *flags_zv, *storage_zv, *members_zv, *elem;
+
+       if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "h", &data) == FAILURE) {
+               return;
+       }
+
+       flags_zv = zend_hash_index_find(data, 0);
+       storage_zv = zend_hash_index_find(data, 1);
+       members_zv = zend_hash_index_find(data, 2);
+       if (!flags_zv || !storage_zv || !members_zv ||
+                       Z_TYPE_P(flags_zv) != IS_LONG || Z_TYPE_P(storage_zv) != IS_ARRAY ||
+                       Z_TYPE_P(members_zv) != IS_ARRAY) {
+               zend_throw_exception(spl_ce_UnexpectedValueException,
+                       "Incomplete or ill-typed serialization data", 0);
+               return;
+       }
+
+       intern->flags = (int) Z_LVAL_P(flags_zv);
+
+       ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(storage_zv), elem) {
+               spl_ptr_llist_push(intern->llist, elem);
+       } ZEND_HASH_FOREACH_END();
+
+       object_properties_load(&intern->std, Z_ARRVAL_P(members_zv));
+} /* }}} */
+
 /* {{{ proto void SplDoublyLinkedList::add(mixed index, mixed newval)
  Inserts a new entry before the specified $index consisting of $newval. */
 SPL_METHOD(SplDoublyLinkedList, add)
@@ -1374,6 +1435,8 @@ static const zend_function_entry spl_funcs_SplDoublyLinkedList[] = {
        /* Serializable */
        SPL_ME(SplDoublyLinkedList,  unserialize,    arginfo_dllist_serialized,      ZEND_ACC_PUBLIC)
        SPL_ME(SplDoublyLinkedList,  serialize,      arginfo_dllist_void,            ZEND_ACC_PUBLIC)
+       SPL_ME(SplDoublyLinkedList,  __unserialize,    arginfo_dllist_serialized,    ZEND_ACC_PUBLIC)
+       SPL_ME(SplDoublyLinkedList,  __serialize,      arginfo_dllist_void,          ZEND_ACC_PUBLIC)
        PHP_FE_END
 };
 /* }}} */
index 8b170afaee69c5812d143c237dcbc196d3bc815b..381019519369d194bbfd74f5926baa150c2ebb7b 100644 (file)
@@ -868,6 +868,78 @@ outexcept:
 
 } /* }}} */
 
+/* {{{ proto auto SplObjectStorage::__serialize() */
+SPL_METHOD(SplObjectStorage, __serialize)
+{
+       spl_SplObjectStorage *intern = Z_SPLOBJSTORAGE_P(ZEND_THIS);
+       spl_SplObjectStorageElement *elem;
+       zval tmp;
+
+       if (zend_parse_parameters_none_throw() == FAILURE) {
+               return;
+       }
+
+       array_init(return_value);
+
+       /* storage */
+       array_init_size(&tmp, 2 * zend_hash_num_elements(&intern->storage));
+       ZEND_HASH_FOREACH_PTR(&intern->storage, elem) {
+               Z_TRY_ADDREF(elem->obj);
+               zend_hash_next_index_insert(Z_ARRVAL(tmp), &elem->obj);
+               Z_TRY_ADDREF(elem->inf);
+               zend_hash_next_index_insert(Z_ARRVAL(tmp), &elem->inf);
+       } ZEND_HASH_FOREACH_END();
+       zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &tmp);
+
+       /* members */
+       ZVAL_ARR(&tmp, zend_std_get_properties(ZEND_THIS));
+       Z_TRY_ADDREF(tmp);
+       zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &tmp);
+} /* }}} */
+
+/* {{{ proto void SplObjectStorage::__unserialize(array serialized) */
+SPL_METHOD(SplObjectStorage, __unserialize)
+{
+       spl_SplObjectStorage *intern = Z_SPLOBJSTORAGE_P(ZEND_THIS);
+       HashTable *data;
+       zval *storage_zv, *members_zv, *key, *val;
+
+       if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "h", &data) == FAILURE) {
+               return;
+       }
+
+       storage_zv = zend_hash_index_find(data, 0);
+       members_zv = zend_hash_index_find(data, 1);
+       if (!storage_zv || !members_zv ||
+                       Z_TYPE_P(storage_zv) != IS_ARRAY || Z_TYPE_P(members_zv) != IS_ARRAY) {
+               zend_throw_exception(spl_ce_UnexpectedValueException,
+                       "Incomplete or ill-typed serialization data", 0);
+               return;
+       }
+
+       if (zend_hash_num_elements(Z_ARRVAL_P(storage_zv)) % 2 != 0) {
+               zend_throw_exception(spl_ce_UnexpectedValueException, "Odd number of elements", 0);
+               return;
+       }
+
+       key = NULL;
+       ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(storage_zv), val) {
+               if (key) {
+                       if (Z_TYPE_P(key) != IS_OBJECT) {
+                               zend_throw_exception(spl_ce_UnexpectedValueException, "Non-object key", 0);
+                               return;
+                       }
+
+                       spl_object_storage_attach(intern, ZEND_THIS, key, val);
+                       key = NULL;
+               } else {
+                       key = val;
+               }
+       } ZEND_HASH_FOREACH_END();
+
+       object_properties_load(&intern->std, Z_ARRVAL_P(members_zv));
+}
+
 ZEND_BEGIN_ARG_INFO(arginfo_Object, 0)
        ZEND_ARG_INFO(0, object)
 ZEND_END_ARG_INFO();
@@ -917,6 +989,8 @@ static const zend_function_entry spl_funcs_SplObjectStorage[] = {
        /* Serializable */
        SPL_ME(SplObjectStorage,  unserialize, arginfo_Serialized,    0)
        SPL_ME(SplObjectStorage,  serialize,   arginfo_splobject_void,0)
+       SPL_ME(SplObjectStorage,  __unserialize, arginfo_Serialized,    0)
+       SPL_ME(SplObjectStorage,  __serialize,   arginfo_splobject_void,0)
        /* ArrayAccess */
        SPL_MA(SplObjectStorage, offsetExists, SplObjectStorage, contains, arginfo_offsetGet, 0)
        SPL_MA(SplObjectStorage, offsetSet,    SplObjectStorage, attach,   arginfo_attach, 0)
index 7ab7d78174f7e9ce6974410fe1fcc4bc67bf697f..d04e0cbe72514f5291bbbcfc0bdc1f6232c938d9 100644 (file)
@@ -29,7 +29,7 @@ object(SplQueue)#%d (2) {
     string(1) "b"
   }
 }
-string(42) "C:8:"SplQueue":22:{i:4;:s:1:"a";:s:1:"b";}"
+string(71) "O:8:"SplQueue":3:{i:0;i:4;i:1;a:2:{i:0;s:1:"a";i:1;s:1:"b";}i:2;a:0:{}}"
 object(SplQueue)#%d (2) {
   ["flags":"SplDoublyLinkedList":private]=>
   int(4)
@@ -52,7 +52,7 @@ object(SplStack)#%d (2) {
     string(1) "b"
   }
 }
-string(42) "C:8:"SplStack":22:{i:6;:s:1:"a";:s:1:"b";}"
+string(71) "O:8:"SplStack":3:{i:0;i:6;i:1;a:2:{i:0;s:1:"a";i:1;s:1:"b";}i:2;a:0:{}}"
 object(SplStack)#%d (2) {
   ["flags":"SplDoublyLinkedList":private]=>
   int(6)
index daf415049c91163584463a4abdda2ae5be5bb233..c75662c66ecc92caeb4c0a14d1769fcbebb08f4e 100644 (file)
@@ -18,7 +18,7 @@ echo $s."\n";
 $so1 = unserialize($s);
 var_dump($so1);
 --EXPECTF--
-C:16:"SplObjectStorage":76:{x:i:2;O:8:"stdClass":1:{s:1:"a";O:8:"stdClass":0:{}},i:1;;r:4;,i:2;;m:a:0:{}}
+O:16:"SplObjectStorage":2:{i:0;a:4:{i:0;O:8:"stdClass":1:{s:1:"a";O:8:"stdClass":0:{}}i:1;i:1;i:2;r:4;i:3;i:2;}i:1;a:0:{}}
 object(SplObjectStorage)#4 (1) {
   ["storage":"SplObjectStorage":private]=>
   array(2) {
index 35893ea1eaf5533498a7e9800367218e37471ede..9a95de60eb48d48cd21d85bec8fad85ad1779434 100644 (file)
@@ -24,7 +24,7 @@ ArrayObject Object
         )
 
 )
-C:11:"ArrayObject":76:{x:i:0;C:11:"ArrayObject":37:{x:i:0;a:2:{i:0;i:1;i:1;i:2;};m:a:0:{}};m:a:0:{}}
+O:11:"ArrayObject":3:{i:0;i:0;i:1;O:11:"ArrayObject":3:{i:0;i:0;i:1;a:2:{i:0;i:1;i:1;i:2;}i:2;a:0:{}}i:2;a:0:{}}
 ArrayObject Object
 (
     [storage:ArrayObject:private] => ArrayObject Object
index 7993bfaa958753f91eda961f7ad6814074c3d3f6..8187b3a3203aa3f0a967a67fc490aaf4264bb9fa 100644 (file)
@@ -31,12 +31,12 @@ var_dump($o2[2][2] === $o2[2]);
 echo "#### Extending ArrayObject\n";
 unset($o,$x,$s1,$s2,$o1,$o2);
 class ArrayObject2 extends ArrayObject {
-    public function serialize() {
-        return parent::serialize();
+    public function __serialize() {
+        return parent::__serialize();
     }
 
-    public function unserialize($s) {
-        return parent::unserialize($s);
+    public function __unserialize($s) {
+        return parent::__unserialize($s);
     }
 }
 
@@ -50,17 +50,17 @@ var_dump($o[0] === $o[1]);
 var_dump($o[2] === $o);
 
 $s1 = serialize($o);
-$s2 = $o->serialize();
+$s2 = $o->__serialize();
 var_dump($s1);
 var_dump($s2);
 
-$o1 =unserialize($s1);
+$o1 = unserialize($s1);
 
 var_dump($o1[0] === $o1[1]);
 var_dump($o1[2] === $o1);
 
 $o2 = new ArrayObject2();
-$o2->unserialize($s2);
+$o2->__unserialize($s2);
 
 var_dump($o2[0] === $o2[1]);
 var_dump($o2[2] !== $o2);
@@ -69,8 +69,8 @@ var_dump($o2[2][2] === $o2[2]);
 --EXPECT--
 bool(true)
 bool(true)
-string(84) "C:11:"ArrayObject":60:{x:i:0;a:3:{i:0;O:8:"stdClass":0:{}i:1;r:4;i:2;r:1;};m:a:0:{}}"
-string(125) "x:i:0;a:3:{i:0;O:8:"stdClass":0:{}i:1;r:3;i:2;C:11:"ArrayObject":45:{x:i:0;a:3:{i:0;r:3;i:1;r:3;i:2;r:5;};m:a:0:{}}};m:a:0:{}"
+string(90) "O:11:"ArrayObject":3:{i:0;i:0;i:1;a:3:{i:0;O:8:"stdClass":0:{}i:1;r:4;i:2;r:1;}i:2;a:0:{}}"
+string(131) "x:i:0;a:3:{i:0;O:8:"stdClass":0:{}i:1;r:3;i:2;O:11:"ArrayObject":3:{i:0;i:0;i:1;a:3:{i:0;r:3;i:1;r:3;i:2;r:5;}i:2;a:0:{}}};m:a:0:{}"
 bool(true)
 bool(true)
 bool(true)
@@ -79,8 +79,28 @@ bool(true)
 #### Extending ArrayObject
 bool(true)
 bool(true)
-string(85) "C:12:"ArrayObject2":60:{x:i:0;a:3:{i:0;O:8:"stdClass":0:{}i:1;r:4;i:2;r:1;};m:a:0:{}}"
-string(126) "x:i:0;a:3:{i:0;O:8:"stdClass":0:{}i:1;r:3;i:2;C:12:"ArrayObject2":45:{x:i:0;a:3:{i:0;r:3;i:1;r:3;i:2;r:5;};m:a:0:{}}};m:a:0:{}"
+string(91) "O:12:"ArrayObject2":3:{i:0;i:0;i:1;a:3:{i:0;O:8:"stdClass":0:{}i:1;r:4;i:2;r:1;}i:2;a:0:{}}"
+array(3) {
+  [0]=>
+  int(0)
+  [1]=>
+  array(3) {
+    [0]=>
+    object(stdClass)#8 (0) {
+    }
+    [1]=>
+    object(stdClass)#8 (0) {
+    }
+    [2]=>
+    object(ArrayObject2)#5 (1) {
+      ["storage":"ArrayObject":private]=>
+      *RECURSION*
+    }
+  }
+  [2]=>
+  array(0) {
+  }
+}
 bool(true)
 bool(true)
 bool(true)
index a2e2e0b3968b0e359368c568be66ee78d12e3580..4d9e8e1d60a59df7048346a6c7f79370d2340591 100644 (file)
@@ -17,7 +17,7 @@ var_dump(unserialize($ss));
 ?>
 ===DONE===
 --EXPECTF--
-C:16:"SplObjectStorage":113:{x:i:2;O:8:"stdClass":0:{},a:2:{s:4:"prev";i:2;s:4:"next";O:8:"stdClass":0:{}};r:6;,a:1:{s:4:"prev";r:3;};m:a:0:{}}
+O:16:"SplObjectStorage":2:{i:0;a:4:{i:0;O:8:"stdClass":0:{}i:1;a:2:{s:4:"prev";i:2;s:4:"next";O:8:"stdClass":0:{}}i:2;r:6;i:3;a:1:{s:4:"prev";r:3;}}i:1;a:0:{}}
 object(SplObjectStorage)#2 (1) {
   ["storage":"SplObjectStorage":private]=>
   array(2) {
index 5e4fcd023b10f0f5007897cc47a1572e6b058fda..264cd3b97a3589c78743404f6941fdcbac81e637 100644 (file)
@@ -104,7 +104,7 @@ object(SelfArray)#9 (1) {
   ["foo"]=>
   string(3) "bar"
 }
-string(62) "C:9:"SelfArray":41:{x:i:16777216;m:a:1:{s:3:"foo";s:3:"bar";}}"
+string(71) "O:9:"SelfArray":3:{i:0;i:16777216;i:1;N;i:2;a:1:{s:3:"foo";s:3:"bar";}}"
 object(SelfArray)#9 (1) {
   ["foo"]=>
   string(3) "bar"
diff --git a/ext/spl/tests/unserialize_errors.phpt b/ext/spl/tests/unserialize_errors.phpt
new file mode 100644 (file)
index 0000000..237d067
--- /dev/null
@@ -0,0 +1,138 @@
+--TEST--
+Errors from __unserialize() with invalid data
+--FILE--
+<?php
+
+echo "ArrayObject:\n";
+
+try {
+    unserialize('O:11:"ArrayObject":0:{}');
+} catch (Exception $e) {
+    echo $e->getMessage(), "\n";
+}
+
+try {
+    unserialize('O:11:"ArrayObject":3:{i:0;b:1;i:1;a:0:{}i:2;a:0:{}}');
+} catch (Exception $e) {
+    echo $e->getMessage(), "\n";
+}
+
+try {
+    unserialize('O:11:"ArrayObject":3:{i:0;i:0;i:1;a:0:{}i:2;i:0;}');
+} catch (Exception $e) {
+    echo $e->getMessage(), "\n";
+}
+
+try {
+    unserialize('O:11:"ArrayObject":3:{i:0;i:0;i:1;i:0;i:2;a:0:{}}');
+} catch (Exception $e) {
+    echo $e->getMessage(), "\n";
+}
+
+echo "ArrayIterator:\n";
+
+try {
+    unserialize('O:13:"ArrayIterator":0:{}');
+} catch (Exception $e) {
+    echo $e->getMessage(), "\n";
+}
+
+try {
+    unserialize('O:13:"ArrayIterator":3:{i:0;b:1;i:1;a:0:{}i:2;a:0:{}}');
+} catch (Exception $e) {
+    echo $e->getMessage(), "\n";
+}
+
+try {
+    unserialize('O:13:"ArrayIterator":3:{i:0;i:0;i:1;a:0:{}i:2;i:0;}');
+} catch (Exception $e) {
+    echo $e->getMessage(), "\n";
+}
+
+try {
+    unserialize('O:13:"ArrayIterator":3:{i:0;i:0;i:1;i:0;i:2;a:0:{}}');
+} catch (Exception $e) {
+    echo $e->getMessage(), "\n";
+}
+
+echo "SplDoublyLinkedList:\n";
+
+try {
+    unserialize('O:19:"SplDoublyLinkedList":0:{}');
+} catch (Exception $e) {
+    echo $e->getMessage(), "\n";
+}
+
+try {
+    unserialize('O:19:"SplDoublyLinkedList":3:{i:0;b:1;i:1;a:0:{}i:2;a:0:{}}');
+} catch (Exception $e) {
+    echo $e->getMessage(), "\n";
+}
+
+try {
+    unserialize('O:19:"SplDoublyLinkedList":3:{i:0;i:0;i:1;a:0:{}i:2;i:0;}');
+} catch (Exception $e) {
+    echo $e->getMessage(), "\n";
+}
+
+try {
+    unserialize('O:19:"SplDoublyLinkedList":3:{i:0;i:0;i:1;i:0;i:2;a:0:{}}');
+} catch (Exception $e) {
+    echo $e->getMessage(), "\n";
+}
+
+echo "SplObjectStorage:\n";
+
+try {
+    unserialize('O:16:"SplObjectStorage":0:{}');
+} catch (Exception $e) {
+    echo $e->getMessage(), "\n";
+}
+
+try {
+    unserialize('O:16:"SplObjectStorage":2:{i:0;i:0;i:1;a:0:{}}');
+} catch (Exception $e) {
+    echo $e->getMessage(), "\n";
+}
+
+try {
+    unserialize('O:16:"SplObjectStorage":2:{i:0;a:0:{}i:1;i:1;}');
+} catch (Exception $e) {
+    echo $e->getMessage(), "\n";
+}
+
+try {
+    unserialize('O:16:"SplObjectStorage":2:{i:0;a:1:{i:0;i:0;}i:1;a:0:{}}');
+} catch (Exception $e) {
+    echo $e->getMessage(), "\n";
+}
+
+try {
+    unserialize('O:16:"SplObjectStorage":2:{i:0;a:2:{i:0;i:0;i:1;i:0;}i:1;a:0:{}}');
+} catch (Exception $e) {
+    echo $e->getMessage(), "\n";
+}
+
+?>
+--EXPECTF--
+ArrayObject:
+Incomplete or ill-typed serialization data
+Incomplete or ill-typed serialization data
+Incomplete or ill-typed serialization data
+Passed variable is not an array or object
+ArrayIterator:
+Incomplete or ill-typed serialization data
+Incomplete or ill-typed serialization data
+Incomplete or ill-typed serialization data
+Passed variable is not an array or object
+SplDoublyLinkedList:
+Incomplete or ill-typed serialization data
+Incomplete or ill-typed serialization data
+Incomplete or ill-typed serialization data
+Incomplete or ill-typed serialization data
+SplObjectStorage:
+Incomplete or ill-typed serialization data
+Incomplete or ill-typed serialization data
+Incomplete or ill-typed serialization data
+Odd number of elements
+Non-object key
index 218cdcca2d506a8e2f10e5fb418b400bd9365672..12cadfe0fa87fbf519b22515f04bf9362d2b5536 100644 (file)
@@ -13,15 +13,22 @@ $s = str_replace("Foo", "Bar", $s);
 $y = unserialize($s);
 var_dump($y);
 --EXPECTF--
-Warning: Class __PHP_Incomplete_Class has no unserializer in %sbug45706.php on line %d
 array(2) {
   [0]=>
-  object(__PHP_Incomplete_Class)#%d (1) {
+  object(__PHP_Incomplete_Class)#3 (4) {
     ["__PHP_Incomplete_Class_Name"]=>
     string(4) "Bar1"
+    ["0"]=>
+    int(0)
+    ["1"]=>
+    array(0) {
+    }
+    ["2"]=>
+    array(0) {
+    }
   }
   [1]=>
-  object(__PHP_Incomplete_Class)#%d (1) {
+  object(__PHP_Incomplete_Class)#4 (1) {
     ["__PHP_Incomplete_Class_Name"]=>
     string(4) "Bar2"
   }
index 588aa43d8ba3aee88588532cb98ab59953df53d7..1dadbe5a2914e131351d7a1fc891c5e46ef0241c 100644 (file)
@@ -646,7 +646,7 @@ static inline int object_common(UNSERIALIZE_PARAMETER, zend_long elements, zend_
                if (!process_nested_data(UNSERIALIZE_PASSTHRU, Z_ARRVAL(ary), elements, NULL)) {
                        ZVAL_DEREF(rval);
                        GC_ADD_FLAGS(Z_OBJ_P(rval), IS_OBJ_DESTRUCTOR_CALLED);
-            zval_ptr_dtor(&ary);
+                       zval_ptr_dtor(&ary);
                        return 0;
                }