Skip to content

Commit d22e247

Browse files
committed
Fix extra data detection for nested unserialize in Serializable interface
1 parent cb8cb01 commit d22e247

File tree

4 files changed

+97
-10
lines changed

4 files changed

+97
-10
lines changed

ext/standard/tests/serialize/unserialize_extra_data.phpt renamed to ext/standard/tests/serialize/unserialize_extra_data_001.phpt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
--TEST--
2-
Extra data at the end of a valid value
2+
Test unserialize() with extra data at the end of a valid value
33
--FILE--
44
<?php
55

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
--TEST--
2+
Test unserialize() with extra data at the end of a valid value with nested unserialize
3+
--FILE--
4+
<?php
5+
6+
final class Foo {
7+
public $foo;
8+
9+
public function __unserialize(array $foo)
10+
{
11+
$this->foo = unserialize($foo['bar']);
12+
}
13+
14+
public function __serialize(): array
15+
{
16+
return [
17+
'bar' => serialize($this->foo) . 'garbage',
18+
];
19+
}
20+
}
21+
22+
$f = new Foo;
23+
$f->foo = ['a', 'b', 'c'];
24+
25+
var_dump(unserialize(serialize($f) . 'garbage'));
26+
27+
?>
28+
--EXPECTF--
29+
Warning: unserialize(): Extra data starting at offset 81 of 88 bytes in %s on line %d
30+
31+
Warning: unserialize(): Extra data starting at offset 42 of 49 bytes in %s on line %d
32+
object(Foo)#2 (1) {
33+
["foo"]=>
34+
array(3) {
35+
[0]=>
36+
string(1) "a"
37+
[1]=>
38+
string(1) "b"
39+
[2]=>
40+
string(1) "c"
41+
}
42+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
--TEST--
2+
Test unserialize() with extra data at the end of a valid value with Serializable
3+
--FILE--
4+
<?php
5+
6+
final class Foo implements Serializable {
7+
public $foo;
8+
9+
public function unserialize(string $foo)
10+
{
11+
$this->foo = unserialize($foo);
12+
}
13+
14+
public function serialize(): string
15+
{
16+
return serialize($this->foo) . 'garbage';
17+
}
18+
}
19+
20+
$f = new Foo;
21+
$f->foo = ['a', 'b', 'c'];
22+
23+
var_dump(unserialize(serialize($f) . 'garbage'));
24+
25+
?>
26+
--EXPECTF--
27+
Deprecated: Foo implements the Serializable interface, which is deprecated. Implement __serialize() and __unserialize() instead (or in addition, if support for old PHP versions is necessary) in %s on line %d
28+
29+
Warning: unserialize(): Extra data starting at offset 42 of 49 bytes in %s on line %d
30+
31+
Warning: unserialize(): Extra data starting at offset 64 of 71 bytes in %s on line %d
32+
object(Foo)#2 (1) {
33+
["foo"]=>
34+
array(3) {
35+
[0]=>
36+
string(1) "a"
37+
[1]=>
38+
string(1) "b"
39+
[2]=>
40+
string(1) "c"
41+
}
42+
}

ext/standard/var.c

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1407,16 +1407,19 @@ PHPAPI void php_unserialize_with_options(zval *return_value, const char *buf, co
14071407
zval_ptr_dtor(return_value);
14081408
}
14091409
RETVAL_FALSE;
1410-
} else if ((char*)p < buf + buf_len) {
1411-
if (!EG(exception)) {
1412-
php_error_docref(NULL, E_WARNING, "Extra data starting at offset " ZEND_LONG_FMT " of %zd bytes",
1413-
(zend_long)((char*)p - buf), buf_len);
1410+
} else {
1411+
if ((char*)p < buf + buf_len) {
1412+
if (!EG(exception)) {
1413+
php_error_docref(NULL, E_WARNING, "Extra data starting at offset " ZEND_LONG_FMT " of %zd bytes",
1414+
(zend_long)((char*)p - buf), buf_len);
1415+
}
1416+
}
1417+
if (BG(unserialize).level > 1) {
1418+
ZVAL_COPY(return_value, retval);
1419+
} else if (Z_REFCOUNTED_P(return_value)) {
1420+
zend_refcounted *ref = Z_COUNTED_P(return_value);
1421+
gc_check_possible_root(ref);
14141422
}
1415-
} else if (BG(unserialize).level > 1) {
1416-
ZVAL_COPY(return_value, retval);
1417-
} else if (Z_REFCOUNTED_P(return_value)) {
1418-
zend_refcounted *ref = Z_COUNTED_P(return_value);
1419-
gc_check_possible_root(ref);
14201423
}
14211424

14221425
cleanup:

0 commit comments

Comments
 (0)