com php-src: Fixed #74699 - Broken ArrayIterator unserializing: NEWS ext/spl/spl_array.c ext/spl/tests/bug70155.ph pt ext/spl/tests/bug74669.phpt
| From: | Nikita Popov | Date: | Tue, 18 Jul 2017 20:14:11 +0000 |
| Subject: | com php-src: Fixed #74699 - Broken ArrayIterator unserializing: NEWS ext/spl/spl_array.c ext/spl/tests/bug70155.ph pt ext/spl/tests/bug74669.phpt | ||
| Groups: | php.cvs | ||
| Request: | Send a blank email to php-cvs+get-98624@lists.php.net to get a copy of this message | ||
Commit: afc22828ea036814e6a044083dade065b4c858c9
Author: andrewnester <andrew.nester.dev@gmail.com> Tue, 6 Jun 2017 09:37:05 +0300
Committer: Nikita Popov <nikita.ppv@gmail.com> Tue, 18 Jul 2017 22:14:11 +0200
Parents: 51cdd3dc50af88461d83aec0fac1dca83400b58f
Branches: PHP-7.0 PHP-7.1 PHP-7.2 master
Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=afc22828ea036814e6a044083dade065b4c858c9
Log:
Fixed #74699 - Broken ArrayIterator unserializing
Bugs:
https://bugs.php.net/74699
Changed paths:
M NEWS
M ext/spl/spl_array.c
M ext/spl/tests/bug70155.phpt
A ext/spl/tests/bug74669.phpt
Diff:
diff --git a/NEWS b/NEWS
index 26fa2d8..3f092f4 100644
--- a/NEWS
+++ b/NEWS
@@ -2,7 +2,8 @@ PHP NEWS
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
?? ??? 2017 PHP 7.0.23
-
+- SPL:
+ . Fixed bug #74669 (Unserialize ArrayIterator broken). (Andrew Nester)
03 Aug 2017 PHP 7.0.22
diff --git a/ext/spl/spl_array.c b/ext/spl/spl_array.c
index 556878f..b8eddf0 100644
--- a/ext/spl/spl_array.c
+++ b/ext/spl/spl_array.c
@@ -1734,13 +1734,14 @@ SPL_METHOD(Array, serialize)
*/
SPL_METHOD(Array, unserialize)
{
- spl_array_object *intern = Z_SPLARRAY_P(getThis());
+ zval *object = getThis();
+ spl_array_object *intern = Z_SPLARRAY_P(object);
char *buf;
size_t buf_len;
const unsigned char *p, *s;
php_unserialize_data_t var_hash;
- zval *members, *zflags;
+ zval *members, *zflags, *array;
zend_long flags;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &buf, &buf_len) == FAILURE) {
@@ -1782,24 +1783,38 @@ SPL_METHOD(Array, unserialize)
}
++p;
- if (*p!='m') {
+ if (flags & SPL_ARRAY_IS_SELF) {
+ /* If IS_SELF is used, the flags are not followed by an array/object */
+ intern->ar_flags &= ~SPL_ARRAY_CLONE_MASK;
+ intern->ar_flags |= flags & SPL_ARRAY_CLONE_MASK;
+ zval_ptr_dtor(&intern->array);
+ ZVAL_UNDEF(&intern->array);
+ } else {
if (*p!='a' && *p!='O' && *p!='C' &&
*p!='r') {
goto outexcept;
}
+
+ array = var_tmp_var(&var_hash);
+ if (!php_var_unserialize(array, &p, s + buf_len, &var_hash)
+ || (Z_TYPE_P(array) != IS_ARRAY && Z_TYPE_P(array) != IS_OBJECT)) {
+ goto outexcept;
+ }
+
intern->ar_flags &= ~SPL_ARRAY_CLONE_MASK;
intern->ar_flags |= flags & SPL_ARRAY_CLONE_MASK;
- zval_ptr_dtor(&intern->array);
- ZVAL_UNDEF(&intern->array);
- if (!php_var_unserialize(&intern->array, &p, s + buf_len, &var_hash)
- || (Z_TYPE(intern->array) != IS_ARRAY && Z_TYPE(intern->array) != IS_OBJECT)) {
+
+ if (Z_TYPE_P(array) == IS_ARRAY) {
+ zval_ptr_dtor(&intern->array);
+ ZVAL_COPY(&intern->array, array);
+ } else {
+ spl_array_set_array(object, intern, array, 0L, 1);
+ }
+
+ if (*p != ';') {
goto outexcept;
}
- var_push_dtor(&var_hash, &intern->array);
- }
- if (*p != ';') {
- goto outexcept;
+ ++p;
}
- ++p;
/* members */
if (*p!= 'm' || *++p != ':') {
diff --git a/ext/spl/tests/bug70155.phpt b/ext/spl/tests/bug70155.phpt
index 1730a1a..0aa246c 100644
--- a/ext/spl/tests/bug70155.phpt
+++ b/ext/spl/tests/bug70155.phpt
@@ -8,43 +8,10 @@ $data = unserialize($exploit);
var_dump($data);
?>
-===DONE===
--EXPECTF--
-object(ArrayObject)#1 (2) {
- [0]=>
- int(0)
- ["storage":"ArrayObject":private]=>
- object(DateInterval)#2 (15) {
- ["y"]=>
- int(3)
- ["m"]=>
- int(-1)
- ["d"]=>
- int(-1)
- ["h"]=>
- int(-1)
- ["i"]=>
- int(-1)
- ["s"]=>
- int(-1)
- ["weekday"]=>
- int(-1)
- ["weekday_behavior"]=>
- int(-1)
- ["first_last_day_of"]=>
- int(-1)
- ["invert"]=>
- int(0)
- ["days"]=>
- int(-1)
- ["special_type"]=>
- int(0)
- ["special_amount"]=>
- int(-1)
- ["have_weekday_relative"]=>
- int(0)
- ["have_special_relative"]=>
- int(0)
- }
-}
-===DONE===
+Fatal error: Uncaught InvalidArgumentException: Overloaded object of type DateInterval is not
compatible with ArrayObject in %s
+Stack trace:
+%s
+%s
+%s
+%s
diff --git a/ext/spl/tests/bug74669.phpt b/ext/spl/tests/bug74669.phpt
new file mode 100644
index 0000000..97c7807
--- /dev/null
+++ b/ext/spl/tests/bug74669.phpt
@@ -0,0 +1,112 @@
+--TEST--
+Bug #74669: Unserialize ArrayIterator broken
+--FILE--
+<?php
+
+class Container implements Iterator
+{
+ public $container;
+ public $iterator;
+
+ public function __construct()
+ {
+ $this->container = new ArrayObject();
+ $this->iterator = $this->container->getIterator();
+ }
+
+ public function append($element)
+ {
+ $this->container->append($element);
+ }
+
+ public function current()
+ {
+ return $this->iterator->current();
+ }
+
+ public function next()
+ {
+ $this->iterator->next();
+ }
+
+ public function key()
+ {
+ return $this->iterator->key();
+ }
+
+ public function valid()
+ {
+ return $this->iterator->valid();
+ }
+
+ public function rewind()
+ {
+ $this->iterator->rewind();
+ }
+}
+
+class SelfArray extends ArrayObject
+{
+ public function __construct()
+ {
+ parent::__construct($this);
+ }
+}
+
+$container = new Container();
+$container->append('test1');
+$container->append('test2');
+$container->valid();
+$serialized = serialize($container);
+unset($container);
+
+$container = unserialize($serialized);
+
+foreach ($container as $key => $value) {
+ echo $key . ' => ' . $value . PHP_EOL;
+}
+
+$arObj = new ArrayObject(['test1', 'test2']);
+$serialized = serialize($container);
+unset($arObj);
+
+$arObj = unserialize($serialized);
+foreach($arObj as $key => $value) {
+ echo $key . ' => ' . $value . PHP_EOL;
+}
+
+$payload = 'x:i:33554432;O:8:"stdClass":0:{};m:a:0:{}';
+$str = 'C:11:"ArrayObject":' . strlen($payload) . ':{' . $payload .
'}';
+
+$ao = unserialize($str);
+var_dump($ao['foo']);
+
+$selfArray = new SelfArray();
+$selfArray['foo'] = 'bar';
+var_dump($selfArray);
+$serialized = serialize($selfArray);
+var_dump($serialized);
+unset($selfArray);
+$selfArray = unserialize($serialized);
+var_dump($selfArray);
+var_dump($selfArray['foo']);
+
+?>
+--EXPECTF--
+0 => test1
+1 => test2
+0 => test1
+1 => test2
+
+Notice: Undefined index: foo in %s on line %s
+NULL
+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";}}"
+object(SelfArray)#9 (1) {
+ ["foo"]=>
+ string(3) "bar"
+}
+string(3) "bar"