mirror of
https://github.com/php/php-src.git
synced 2024-12-17 22:09:12 +08:00
Merge branch 'PHP-7.4'
* PHP-7.4: Fix bug #67369 ArrayObject serializatino drops the iterator class
This commit is contained in:
commit
3d5db42ca5
@ -1850,6 +1850,14 @@ SPL_METHOD(Array, __serialize)
|
||||
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,18 +1867,22 @@ 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(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_THROWS();
|
||||
@ -1888,6 +1900,26 @@ SPL_METHOD(Array, __unserialize)
|
||||
}
|
||||
|
||||
object_properties_load(&intern->std, Z_ARRVAL_P(members_zv));
|
||||
|
||||
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_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;
|
||||
}
|
||||
}
|
||||
/* }}} */
|
||||
|
||||
|
@ -0,0 +1,15 @@
|
||||
--TEST--
|
||||
ArrayObject::__serialize saves any iterator class set by ::setIteratorClass
|
||||
--FILE--
|
||||
<?php
|
||||
|
||||
class MyArrayIterator extends ArrayIterator {}
|
||||
$arrayObject = new ArrayObject(array(1, 2, 3));
|
||||
$arrayObject->setIteratorClass("MyArrayIterator");
|
||||
$serialized = serialize($arrayObject);
|
||||
$backAgain = unserialize($serialized);
|
||||
echo $backAgain->getIteratorClass(), "\n";
|
||||
|
||||
?>
|
||||
--EXPECT--
|
||||
MyArrayIterator
|
@ -24,7 +24,7 @@ ArrayObject Object
|
||||
)
|
||||
|
||||
)
|
||||
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:{}}
|
||||
O:11:"ArrayObject":4:{i:0;i:0;i:1;O:11:"ArrayObject":4:{i:0;i:0;i:1;a:2:{i:0;i:1;i:1;i:2;}i:2;a:0:{}i:3;N;}i:2;a:0:{}i:3;N;}
|
||||
ArrayObject Object
|
||||
(
|
||||
[storage:ArrayObject:private] => ArrayObject Object
|
||||
|
@ -16,7 +16,7 @@ $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);
|
||||
@ -69,8 +69,8 @@ var_dump($o2[2][2] === $o2[2]);
|
||||
--EXPECT--
|
||||
bool(true)
|
||||
bool(true)
|
||||
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:{}"
|
||||
string(96) "O:11:"ArrayObject":4:{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:{}i:3;N;}"
|
||||
string(137) "x:i:0;a:3:{i:0;O:8:"stdClass":0:{}i:1;r:3;i:2;O:11:"ArrayObject":4:{i:0;i:0;i:1;a:3:{i:0;r:3;i:1;r:3;i:2;r:5;}i:2;a:0:{}i:3;N;}};m:a:0:{}"
|
||||
bool(true)
|
||||
bool(true)
|
||||
bool(true)
|
||||
@ -79,8 +79,8 @@ bool(true)
|
||||
#### Extending ArrayObject
|
||||
bool(true)
|
||||
bool(true)
|
||||
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) {
|
||||
string(97) "O:12:"ArrayObject2":4:{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:{}i:3;N;}"
|
||||
array(4) {
|
||||
[0]=>
|
||||
int(0)
|
||||
[1]=>
|
||||
@ -100,6 +100,8 @@ array(3) {
|
||||
[2]=>
|
||||
array(0) {
|
||||
}
|
||||
[3]=>
|
||||
NULL
|
||||
}
|
||||
bool(true)
|
||||
bool(true)
|
||||
|
@ -104,7 +104,7 @@ object(SelfArray)#9 (1) {
|
||||
["foo"]=>
|
||||
string(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";}}"
|
||||
string(77) "O:9:"SelfArray":4:{i:0;i:16777216;i:1;N;i:2;a:1:{s:3:"foo";s:3:"bar";}i:3;N;}"
|
||||
object(SelfArray)#9 (1) {
|
||||
["foo"]=>
|
||||
string(3) "bar"
|
||||
|
@ -6,6 +6,7 @@ Errors from __unserialize() with invalid data
|
||||
echo "ArrayObject:\n";
|
||||
|
||||
try {
|
||||
// empty array
|
||||
unserialize('O:11:"ArrayObject":0:{}');
|
||||
} catch (Exception $e) {
|
||||
echo $e->getMessage(), "\n";
|
||||
@ -29,6 +30,27 @@ try {
|
||||
echo $e->getMessage(), "\n";
|
||||
}
|
||||
|
||||
try {
|
||||
// iterator class name is not a string
|
||||
unserialize('O:11:"ArrayObject":4:{i:0;i:0;i:1;i:0;i:2;a:0:{}i:3;i:0;}');
|
||||
} catch (Exception $e) {
|
||||
echo $e->getMessage(), "\n";
|
||||
}
|
||||
|
||||
try {
|
||||
unserialize('O:11:"ArrayObject":4:{i:0;i:0;i:1;a:2:{i:0;i:1;i:1;i:2;}i:2;a:0:{}i:3;s:11:"NonExistent";}');
|
||||
} catch (Exception $e) {
|
||||
echo $e->getMessage(), "\n";
|
||||
}
|
||||
|
||||
class Existent {}
|
||||
|
||||
try {
|
||||
unserialize('O:11:"ArrayObject":4:{i:0;i:0;i:1;a:2:{i:0;i:1;i:1;i:2;}i:2;a:0:{}i:3;s:8:"Existent";}');
|
||||
} catch (Exception $e) {
|
||||
echo $e->getMessage(), "\n";
|
||||
}
|
||||
|
||||
echo "ArrayIterator:\n";
|
||||
|
||||
try {
|
||||
@ -114,12 +136,15 @@ try {
|
||||
}
|
||||
|
||||
?>
|
||||
--EXPECTF--
|
||||
--EXPECT--
|
||||
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
|
||||
Incomplete or ill-typed serialization data
|
||||
Cannot deserialize ArrayObject with iterator class 'NonExistent'; no such class exists
|
||||
Cannot deserialize ArrayObject with iterator class 'Existent'; this class does not implement the Iterator interface
|
||||
ArrayIterator:
|
||||
Incomplete or ill-typed serialization data
|
||||
Incomplete or ill-typed serialization data
|
||||
|
@ -15,7 +15,7 @@ var_dump($y);
|
||||
--EXPECTF--
|
||||
array(2) {
|
||||
[0]=>
|
||||
object(__PHP_Incomplete_Class)#3 (4) {
|
||||
object(__PHP_Incomplete_Class)#3 (5) {
|
||||
["__PHP_Incomplete_Class_Name"]=>
|
||||
string(4) "Bar1"
|
||||
["0"]=>
|
||||
@ -26,6 +26,8 @@ array(2) {
|
||||
["2"]=>
|
||||
array(0) {
|
||||
}
|
||||
["3"]=>
|
||||
NULL
|
||||
}
|
||||
[1]=>
|
||||
object(__PHP_Incomplete_Class)#4 (1) {
|
||||
|
Loading…
Reference in New Issue
Block a user