]> granicus.if.org Git - php/commitdiff
Merge branch 'PHP-7.4'
authorNikita Popov <nikita.ppv@gmail.com>
Mon, 20 Apr 2020 09:55:56 +0000 (11:55 +0200)
committerNikita Popov <nikita.ppv@gmail.com>
Mon, 20 Apr 2020 09:56:35 +0000 (11:56 +0200)
* PHP-7.4:
  Fix bug #67369 ArrayObject serializatino drops the iterator class

1  2 
ext/spl/spl_array.c

index cbc40eafe883493b794d97fa60677a89b8193a4c,5f70bfe7a03b760dd8fe33e2e3df7e85d2a70e17..40d74d9671a6b676daec092fd4cf0906c6c57375
@@@ -1847,9 -1837,17 +1847,17 @@@ SPL_METHOD(Array, __serialize
        zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &tmp);
  
        /* members */
 -      ZVAL_ARR(&tmp, zend_std_get_properties(ZEND_THIS));
 +      ZVAL_ARR(&tmp, zend_std_get_properties(&intern->std));
        Z_TRY_ADDREF(tmp);
        zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &tmp);
+       /* iterator class */
+       if (intern->ce_get_iterator == spl_ce_ArrayIterator) {
+               ZVAL_NULL(&tmp);
+       } else {
+               ZVAL_STR_COPY(&tmp, intern->ce_get_iterator->name);
+       }
+       zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &tmp);
  }
  /* }}} */
  
@@@ -1859,21 -1857,25 +1867,25 @@@ SPL_METHOD(Array, __unserialize
  {
        spl_array_object *intern = Z_SPLARRAY_P(ZEND_THIS);
        HashTable *data;
-       zval *flags_zv, *storage_zv, *members_zv;
+       zval *flags_zv, *storage_zv, *members_zv, *iterator_class_zv;
        zend_long flags;
  
 -      if (zend_parse_parameters_throw(ZEND_NUM_ARGS(), "h", &data) == FAILURE) {
 -              return;
 +      if (zend_parse_parameters(ZEND_NUM_ARGS(), "h", &data) == FAILURE) {
 +              RETURN_THROWS();
        }
  
-       flags_zv = zend_hash_index_find(data, 0);
-       storage_zv = zend_hash_index_find(data, 1);
-       members_zv = zend_hash_index_find(data, 2);
+       flags_zv          = zend_hash_index_find(data, 0);
+       storage_zv        = zend_hash_index_find(data, 1);
+       members_zv        = zend_hash_index_find(data, 2);
+       iterator_class_zv = zend_hash_index_find(data, 3);
        if (!flags_zv || !storage_zv || !members_zv ||
-                       Z_TYPE_P(flags_zv) != IS_LONG || Z_TYPE_P(members_zv) != IS_ARRAY) {
+                       Z_TYPE_P(flags_zv) != IS_LONG || Z_TYPE_P(members_zv) != IS_ARRAY ||
+                       (iterator_class_zv && (Z_TYPE_P(iterator_class_zv) != IS_NULL &&
+                               Z_TYPE_P(iterator_class_zv) != IS_STRING))) {
                zend_throw_exception(spl_ce_UnexpectedValueException,
                        "Incomplete or ill-typed serialization data", 0);
 -              return;
 +              RETURN_THROWS();
        }
  
        flags = Z_LVAL_P(flags_zv);
        }
  
        object_properties_load(&intern->std, Z_ARRVAL_P(members_zv));
 -                      return;
 -              } else if (!instanceof_function(ce, spl_ce_Iterator)) {
+       if (iterator_class_zv && Z_TYPE_P(iterator_class_zv) == IS_STRING) {
+               zend_class_entry *ce = zend_lookup_class(Z_STR_P(iterator_class_zv));
+               if (!ce) {
+                       zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
+                               "Cannot deserialize ArrayObject with iterator class '%s'; no such class exists",
+                               ZSTR_VAL(Z_STR_P(iterator_class_zv)));
 -                      return;
 -              } else {
 -                      intern->ce_get_iterator = ce;
++                      RETURN_THROWS();
++              }
++
++              if (!instanceof_function(ce, spl_ce_Iterator)) {
+                       zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0,
+                               "Cannot deserialize ArrayObject with iterator class '%s'; this class does not implement the Iterator interface",
+                               ZSTR_VAL(Z_STR_P(iterator_class_zv)));
++                      RETURN_THROWS();
+               }
++
++              intern->ce_get_iterator = ce;
+       }
  }
  /* }}} */