]> granicus.if.org Git - php/commitdiff
Add tests for delayed __wakeup()
authorNikita Popov <nikic@php.net>
Wed, 4 Jan 2017 23:20:56 +0000 (00:20 +0100)
committerNikita Popov <nikic@php.net>
Wed, 4 Jan 2017 23:21:48 +0000 (00:21 +0100)
ext/standard/tests/serialize/bug72610.phpt [new file with mode: 0644]
ext/standard/tests/serialize/bug72610_2.phpt [new file with mode: 0644]
ext/standard/tests/serialize/bug72610_3.phpt [new file with mode: 0644]
ext/standard/tests/serialize/bug73092.phpt [new file with mode: 0644]
ext/standard/tests/serialize/bug73092_2.phpt [new file with mode: 0644]
ext/standard/tests/serialize/bug73367.phpt [new file with mode: 0644]
ext/standard/tests/serialize/bug73367_2.phpt [new file with mode: 0644]

diff --git a/ext/standard/tests/serialize/bug72610.phpt b/ext/standard/tests/serialize/bug72610.phpt
new file mode 100644 (file)
index 0000000..f2c8bf7
--- /dev/null
@@ -0,0 +1,64 @@
+--TEST--
+__wakeup should be able to add dynamic properties without affecting other dynamic properties
+--FILE--
+<?php
+
+class Obj {
+       // Testing $this->a being a dynamic property.
+
+       function __construct($a) {
+               $this->a = $a;
+       }
+
+       public function __wakeup() {
+               echo "Calling __wakeup\n";
+               for ($i = 0; $i < 10000; $i++) {
+                       $this->{'b' . $i} = 42;
+               }
+       }
+}
+
+function main() {
+       $obj = new stdClass();
+       $obj->test = 'foo';
+       $variable = [new Obj($obj), new Obj($obj)];
+       $serialized = serialize($variable);
+       printf("%s\n", $serialized);
+       $unserialized = unserialize($serialized);
+       for ($i = 0; $i < 10000; $i++) {
+               if ($unserialized[0]->{'b' . $i} !== 42) {
+                       echo "Fail 0 b$i\n";
+                       return;
+               }
+               if ($unserialized[1]->{'b' . $i} !== 42) {
+                       echo "Fail 1 b$i\n";
+                       return;
+               }
+               unset($unserialized[0]->{'b' . $i});
+               unset($unserialized[1]->{'b' . $i});
+       }
+       var_dump($unserialized);
+}
+main();
+--EXPECTF--
+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;}}
+Calling __wakeup
+Calling __wakeup
+array(2) {
+  [0]=>
+  object(Obj)#%d (1) {
+    ["a"]=>
+    object(stdClass)#%d (1) {
+      ["test"]=>
+      string(3) "foo"
+    }
+  }
+  [1]=>
+  object(Obj)#%d (1) {
+    ["a"]=>
+    object(stdClass)#%d (1) {
+      ["test"]=>
+      string(3) "foo"
+    }
+  }
+}
diff --git a/ext/standard/tests/serialize/bug72610_2.phpt b/ext/standard/tests/serialize/bug72610_2.phpt
new file mode 100644 (file)
index 0000000..bb06342
--- /dev/null
@@ -0,0 +1,32 @@
+--TEST--
+__wakeup can replace a copy of the object referring to the root node.
+--FILE--
+<?php
+/* This bug never happened, but adding this test to make sure that further changes to unserialize don't allow freeing the root in __wakeup. */
+class Obj {
+       function __construct($a) {
+               $this->a = $a;
+       }
+
+       public function __wakeup() {
+               echo "Calling __wakeup\n";
+               $this->a = "replaced";
+       }
+}
+
+$a = new stdClass();
+$a->obj = new Obj($a);;
+$serialized = serialize($a);
+printf("%s\n", $serialized);
+$unserialized = unserialize($serialized);
+var_dump($unserialized);
+--EXPECTF--
+O:8:"stdClass":1:{s:3:"obj";O:3:"Obj":1:{s:1:"a";r:1;}}
+Calling __wakeup
+object(stdClass)#%d (1) {
+  ["obj"]=>
+  object(Obj)#%d (1) {
+    ["a"]=>
+    string(8) "replaced"
+  }
+}
diff --git a/ext/standard/tests/serialize/bug72610_3.phpt b/ext/standard/tests/serialize/bug72610_3.phpt
new file mode 100644 (file)
index 0000000..4e69087
--- /dev/null
@@ -0,0 +1,49 @@
+--TEST--
+__wakeup should be able to modify dynamic properties without affecting copies of those properties
+--FILE--
+<?php
+
+class Obj {
+       // Testing $this->a being a dynamic property.
+
+       function __construct($a) {
+               $this->a = $a;
+       }
+
+       public function __wakeup() {
+               echo "Calling __wakeup " . json_encode($this->a) . "\n";
+               $this->a = "roh";
+       }
+}
+
+function main() {
+       $obj = new stdClass();
+       $obj->c = null;
+    $variable = [new Obj($obj), new Obj($obj), $obj];
+       $serialized = serialize($variable);
+       printf("%s\n", $serialized);
+       $unserialized = unserialize($serialized);
+       var_dump($unserialized);
+}
+main();
+--EXPECTF--
+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;}
+Calling __wakeup {"c":null}
+Calling __wakeup {"c":null}
+array(3) {
+  [0]=>
+  object(Obj)#%d (1) {
+    ["a"]=>
+    string(3) "roh"
+  }
+  [1]=>
+  object(Obj)#%d (1) {
+    ["a"]=>
+    string(3) "roh"
+  }
+  [2]=>
+  object(stdClass)#%d (1) {
+    ["c"]=>
+    NULL
+  }
+}
diff --git a/ext/standard/tests/serialize/bug73092.phpt b/ext/standard/tests/serialize/bug73092.phpt
new file mode 100644 (file)
index 0000000..451c532
--- /dev/null
@@ -0,0 +1,17 @@
+--TEST--
+Bug #73092: Unserialize use-after-free when resizing object's properties hash table
+--FILE--
+<?php
+
+class foo {
+    function __wakeup() {
+        $this->{'x'} = 1;
+    }
+}
+
+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;}');
+
+?>
+===DONE===
+--EXPECT--
+===DONE===
diff --git a/ext/standard/tests/serialize/bug73092_2.phpt b/ext/standard/tests/serialize/bug73092_2.phpt
new file mode 100644 (file)
index 0000000..6bc718b
--- /dev/null
@@ -0,0 +1,49 @@
+--TEST--
+Bug #73092: Unserialize use-after-free when resizing object's properties hash table (2)
+--FILE--
+<?php
+class foo {
+    public $x;
+    function __wakeup() {
+        var_dump($this->x);
+    }
+}
+
+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;}}');
+
+?>
+--EXPECTF--
+object(DateInterval)#%d (16) {
+  ["0"]=>
+  int(0)
+  ["y"]=>
+  int(-1)
+  ["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)
+}
diff --git a/ext/standard/tests/serialize/bug73367.phpt b/ext/standard/tests/serialize/bug73367.phpt
new file mode 100644 (file)
index 0000000..c0c19d2
--- /dev/null
@@ -0,0 +1,31 @@
+--TEST--
+Bug #73367: Create an Unexpected Object and Don't Invoke __wakeup() in Deserialization
+--FILE--
+<?php
+
+class obj {
+       var $ryat;
+       function __wakeup() {
+               $this->ryat = null;
+        echo "wakeup\n";
+               throw new Exception("Not a serializable object");
+       }
+       function __destruct() {
+        echo "dtor\n";
+               if ($this->ryat == 1) {
+            echo "dtor ryat==1\n";
+               }
+       }
+}
+
+$poc = 'O:3:"obj":2:{s:4:"ryat";i:1;i:0;O:3:"obj":1:{s:4:"ryat";R:1;}}';
+try {
+    unserialize($poc);
+} catch (Exception $e) {
+    echo $e->getMessage(), "\n";
+}
+
+?>
+--EXPECT--
+wakeup
+Not a serializable object
diff --git a/ext/standard/tests/serialize/bug73367_2.phpt b/ext/standard/tests/serialize/bug73367_2.phpt
new file mode 100644 (file)
index 0000000..59b09da
--- /dev/null
@@ -0,0 +1,21 @@
+--TEST--
+Bug #73367: Create an Unexpected Object and Don't Invoke __wakeup() in Deserialization (2)
+--FILE--
+<?php
+
+class obj {
+    var $ryat;
+    function __wakeup() {
+        $this->ryat = null;
+        $this->foo = 'bar'; // $this should still be live here
+        echo "wakeup\n";
+    }
+}
+
+$poc = 'O:3:"obj":2:{s:4:"ryat";i:1;i:0;O:3:"obj":1:{s:4:"ryat";R:1;}}';
+unserialize($poc);
+
+?>
+--EXPECT--
+wakeup
+wakeup