Skip to content

Commit f697874

Browse files
committed
Add tests for delayed __wakeup()
1 parent 0426b91 commit f697874

File tree

7 files changed

+263
-0
lines changed

7 files changed

+263
-0
lines changed
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
--TEST--
2+
__wakeup should be able to add dynamic properties without affecting other dynamic properties
3+
--FILE--
4+
<?php
5+
6+
class Obj {
7+
// Testing $this->a being a dynamic property.
8+
9+
function __construct($a) {
10+
$this->a = $a;
11+
}
12+
13+
public function __wakeup() {
14+
echo "Calling __wakeup\n";
15+
for ($i = 0; $i < 10000; $i++) {
16+
$this->{'b' . $i} = 42;
17+
}
18+
}
19+
}
20+
21+
function main() {
22+
$obj = new stdClass();
23+
$obj->test = 'foo';
24+
$variable = [new Obj($obj), new Obj($obj)];
25+
$serialized = serialize($variable);
26+
printf("%s\n", $serialized);
27+
$unserialized = unserialize($serialized);
28+
for ($i = 0; $i < 10000; $i++) {
29+
if ($unserialized[0]->{'b' . $i} !== 42) {
30+
echo "Fail 0 b$i\n";
31+
return;
32+
}
33+
if ($unserialized[1]->{'b' . $i} !== 42) {
34+
echo "Fail 1 b$i\n";
35+
return;
36+
}
37+
unset($unserialized[0]->{'b' . $i});
38+
unset($unserialized[1]->{'b' . $i});
39+
}
40+
var_dump($unserialized);
41+
}
42+
main();
43+
--EXPECTF--
44+
a:2:{i:0;O:3:"Obj":1:{s:1:"a";O:8:"stdClass":1:{s:4:"test";s:3:"foo";}}i:1;O:3:"Obj":1:{s:1:"a";r:3;}}
45+
Calling __wakeup
46+
Calling __wakeup
47+
array(2) {
48+
[0]=>
49+
object(Obj)#%d (1) {
50+
["a"]=>
51+
object(stdClass)#%d (1) {
52+
["test"]=>
53+
string(3) "foo"
54+
}
55+
}
56+
[1]=>
57+
object(Obj)#%d (1) {
58+
["a"]=>
59+
object(stdClass)#%d (1) {
60+
["test"]=>
61+
string(3) "foo"
62+
}
63+
}
64+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
--TEST--
2+
__wakeup can replace a copy of the object referring to the root node.
3+
--FILE--
4+
<?php
5+
/* This bug never happened, but adding this test to make sure that further changes to unserialize don't allow freeing the root in __wakeup. */
6+
class Obj {
7+
function __construct($a) {
8+
$this->a = $a;
9+
}
10+
11+
public function __wakeup() {
12+
echo "Calling __wakeup\n";
13+
$this->a = "replaced";
14+
}
15+
}
16+
17+
$a = new stdClass();
18+
$a->obj = new Obj($a);;
19+
$serialized = serialize($a);
20+
printf("%s\n", $serialized);
21+
$unserialized = unserialize($serialized);
22+
var_dump($unserialized);
23+
--EXPECTF--
24+
O:8:"stdClass":1:{s:3:"obj";O:3:"Obj":1:{s:1:"a";r:1;}}
25+
Calling __wakeup
26+
object(stdClass)#%d (1) {
27+
["obj"]=>
28+
object(Obj)#%d (1) {
29+
["a"]=>
30+
string(8) "replaced"
31+
}
32+
}
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
--TEST--
2+
__wakeup should be able to modify dynamic properties without affecting copies of those properties
3+
--FILE--
4+
<?php
5+
6+
class Obj {
7+
// Testing $this->a being a dynamic property.
8+
9+
function __construct($a) {
10+
$this->a = $a;
11+
}
12+
13+
public function __wakeup() {
14+
echo "Calling __wakeup " . json_encode($this->a) . "\n";
15+
$this->a = "roh";
16+
}
17+
}
18+
19+
function main() {
20+
$obj = new stdClass();
21+
$obj->c = null;
22+
$variable = [new Obj($obj), new Obj($obj), $obj];
23+
$serialized = serialize($variable);
24+
printf("%s\n", $serialized);
25+
$unserialized = unserialize($serialized);
26+
var_dump($unserialized);
27+
}
28+
main();
29+
--EXPECTF--
30+
a:3:{i:0;O:3:"Obj":1:{s:1:"a";O:8:"stdClass":1:{s:1:"c";N;}}i:1;O:3:"Obj":1:{s:1:"a";r:3;}i:2;r:3;}
31+
Calling __wakeup {"c":null}
32+
Calling __wakeup {"c":null}
33+
array(3) {
34+
[0]=>
35+
object(Obj)#%d (1) {
36+
["a"]=>
37+
string(3) "roh"
38+
}
39+
[1]=>
40+
object(Obj)#%d (1) {
41+
["a"]=>
42+
string(3) "roh"
43+
}
44+
[2]=>
45+
object(stdClass)#%d (1) {
46+
["c"]=>
47+
NULL
48+
}
49+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
--TEST--
2+
Bug #73092: Unserialize use-after-free when resizing object's properties hash table
3+
--FILE--
4+
<?php
5+
6+
class foo {
7+
function __wakeup() {
8+
$this->{'x'} = 1;
9+
}
10+
}
11+
12+
unserialize('a:3:{i:0;O:3:"foo":8:{i:0;i:0;i:1;i:1;i:2;i:2;i:3;i:3;i:4;i:4;i:5;i:5;i:6;i:6;i:7;i:7;}i:1;s:263:"'.str_repeat("\06", 263).'";i:2;r:3;}');
13+
14+
?>
15+
===DONE===
16+
--EXPECT--
17+
===DONE===
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
--TEST--
2+
Bug #73092: Unserialize use-after-free when resizing object's properties hash table (2)
3+
--FILE--
4+
<?php
5+
class foo {
6+
public $x;
7+
function __wakeup() {
8+
var_dump($this->x);
9+
}
10+
}
11+
12+
unserialize('a:3:{i:0;O:3:"foo":1:{s:1:"x";O:12:"DateInterval":1:{i:0;i:0;}}i:1;s:263:"'.str_repeat("\06", 263).'";i:2;r:4;}}');
13+
14+
?>
15+
--EXPECTF--
16+
object(DateInterval)#%d (16) {
17+
["0"]=>
18+
int(0)
19+
["y"]=>
20+
int(-1)
21+
["m"]=>
22+
int(-1)
23+
["d"]=>
24+
int(-1)
25+
["h"]=>
26+
int(-1)
27+
["i"]=>
28+
int(-1)
29+
["s"]=>
30+
int(-1)
31+
["weekday"]=>
32+
int(-1)
33+
["weekday_behavior"]=>
34+
int(-1)
35+
["first_last_day_of"]=>
36+
int(-1)
37+
["invert"]=>
38+
int(0)
39+
["days"]=>
40+
int(-1)
41+
["special_type"]=>
42+
int(0)
43+
["special_amount"]=>
44+
int(-1)
45+
["have_weekday_relative"]=>
46+
int(0)
47+
["have_special_relative"]=>
48+
int(0)
49+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
--TEST--
2+
Bug #73367: Create an Unexpected Object and Don't Invoke __wakeup() in Deserialization
3+
--FILE--
4+
<?php
5+
6+
class obj {
7+
var $ryat;
8+
function __wakeup() {
9+
$this->ryat = null;
10+
echo "wakeup\n";
11+
throw new Exception("Not a serializable object");
12+
}
13+
function __destruct() {
14+
echo "dtor\n";
15+
if ($this->ryat == 1) {
16+
echo "dtor ryat==1\n";
17+
}
18+
}
19+
}
20+
21+
$poc = 'O:3:"obj":2:{s:4:"ryat";i:1;i:0;O:3:"obj":1:{s:4:"ryat";R:1;}}';
22+
try {
23+
unserialize($poc);
24+
} catch (Exception $e) {
25+
echo $e->getMessage(), "\n";
26+
}
27+
28+
?>
29+
--EXPECT--
30+
wakeup
31+
Not a serializable object
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
--TEST--
2+
Bug #73367: Create an Unexpected Object and Don't Invoke __wakeup() in Deserialization (2)
3+
--FILE--
4+
<?php
5+
6+
class obj {
7+
var $ryat;
8+
function __wakeup() {
9+
$this->ryat = null;
10+
$this->foo = 'bar'; // $this should still be live here
11+
echo "wakeup\n";
12+
}
13+
}
14+
15+
$poc = 'O:3:"obj":2:{s:4:"ryat";i:1;i:0;O:3:"obj":1:{s:4:"ryat";R:1;}}';
16+
unserialize($poc);
17+
18+
?>
19+
--EXPECT--
20+
wakeup
21+
wakeup

0 commit comments

Comments
 (0)