Skip to content

Commit ab99a29

Browse files
committed
Zend: reset typed property default on every unserialize failure path.
phpGH-22263 follow-up Close phpGH-22481
1 parent 6c988e0 commit ab99a29

3 files changed

Lines changed: 40 additions & 5 deletions

File tree

NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ PHP NEWS
44

55
- Core:
66
. Implemented partial function application RFC. (Arnaud)
7+
. Fixed bug GH-22263 (reset typed property default on every unserialize
8+
failure path). (David Carlier)
79

810
- DOM:
911
. Fixed bug GH-22825 (DOMElement::setAttribute() fails silently when the DTD
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
--TEST--
2+
unserialize() resets a typed property to its default on every failure path
3+
--FILE--
4+
<?php
5+
/* A typed property whose value fails to unserialize is reset to its default, on
6+
* every failure path, so a partially built object can never expose a value that
7+
* violates the declared type. */
8+
9+
/* Failure while building the typed "array $trace", exposed through SplHeap's
10+
* delayed __unserialize(): the slot is reset, so getTraceAsString() no longer
11+
* reinterprets the object as a HashTable. */
12+
$n = "\x00";
13+
try {
14+
unserialize(
15+
'O:9:"Exception":1:{s:16:"' . $n . 'Exception' . $n . 'trace";' .
16+
'O:8:"stdClass":2:{s:1:"0";O:10:"SplMaxHeap":2:{i:0;a:0:{}i:1;a:2:{' .
17+
's:5:"flags";i:0;s:13:"heap_elements";a:2:{i:0;s:0:"";i:1;R:1;}}}z}}'
18+
);
19+
} catch (\Throwable $e) {
20+
for (; $e; $e = $e->getPrevious()) {
21+
printf("%s: %s\n", $e::class, $e->getMessage());
22+
}
23+
}
24+
25+
/* By-ref type violation: the slot is reset to its default. */
26+
class C { public array $a; }
27+
try {
28+
var_dump(unserialize('O:1:"C":1:{s:1:"a";R:1;}'));
29+
} catch (\Throwable $e) {
30+
printf("%s: %s\n", $e::class, $e->getMessage());
31+
}
32+
echo "OK\n";
33+
?>
34+
--EXPECTF--
35+
Warning: unserialize(): Error at offset %d of %d bytes in %s on line %d
36+
TypeError: %s
37+
OK

ext/standard/var_unserializer.re

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -689,11 +689,7 @@ second_try:
689689

690690
if (!php_var_unserialize_internal(data, p, max, var_hash)) {
691691
if (info) {
692-
if (Z_ISREF_P(data)) {
693-
ZEND_REF_ADD_TYPE_SOURCE(Z_REF_P(data), info);
694-
} else {
695-
var_restore_prop_default(var_hash, obj, info, data);
696-
}
692+
var_restore_prop_default(var_hash, obj, info, data);
697693
}
698694
goto failure;
699695
}

0 commit comments

Comments
 (0)