This repository has been archived by the owner on Oct 14, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #13 from TysonAndre/fix-php7-serialization-v3
Fix php7 igbinary serialization and unserialization igbinary reference id counts in serialize/unserialize. Make PHP reference unserialization more consistent. Fix segfault in __wakeup for references add tests
- Loading branch information
Showing
12 changed files
with
826 additions
and
133 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,63 @@ | ||
--TEST-- | ||
Check for reference serialization (Original example, not using var_dump) | ||
--SKIPIF-- | ||
<?php | ||
if(!extension_loaded('igbinary')) { | ||
echo "skip no igbinary"; | ||
} | ||
--FILE-- | ||
<?php | ||
error_reporting(E_ALL|E_STRICT); | ||
// Verify that $type[0] is the same zval as $type[0][0][0], but different from $type[0] | ||
function test_cyclic2($type, $variable) { | ||
$serialized = igbinary_serialize($variable); | ||
$unserialized = igbinary_unserialize($serialized); | ||
echo $type, "\n"; | ||
echo substr(bin2hex($serialized), 8), "\n"; | ||
// Can't use === or == on two recursive arrays in some cases | ||
echo array_keys($unserialized) === array_keys($variable) && array_keys($unserialized[0]) === array_keys($variable[0]) ? 'OK' : 'ERROR', "\n"; | ||
ob_start(); | ||
var_dump($variable); | ||
$dump_exp = ob_get_clean(); | ||
ob_start(); | ||
var_dump($unserialized); | ||
$dump_act = ob_get_clean(); | ||
if (preg_replace('/&array/', 'array', $dump_act) !== preg_replace('/&array/', 'array', $dump_exp)) { | ||
echo "But var dump differs:\nActual:\n", $dump_act, "\nExpected\n", $dump_exp, "\n"; | ||
echo "(Was normalized)\n"; | ||
} | ||
|
||
if (!isset($unserialized[0]) || count($unserialized) != 1) { | ||
printf("Unexpected keys: %s\n", array_keys($unserialized)); | ||
return; | ||
} else if (!is_array($unserialized)) { | ||
printf("\$a[0] is not an array, it is %s", gettype($unserialized)); | ||
return; | ||
} | ||
// Set a key, check for the presense of the key 2 levels deeper (Should find it) and 1 level deeper (Should not find it) | ||
$unserialized[0]['test'] = 'foo'; | ||
if ($unserialized[0][0][0]['test'] !== 'foo') { | ||
echo "Expected the unserialized array to be cyclic\n"; | ||
} | ||
if (isset($unserialized[0][0]['test'])) { | ||
echo "Expected the unserialized array to be cyclic AND of cycle depth 2, but cycle depth is 1\n"; | ||
} | ||
} | ||
$a = [null]; | ||
$b = [&$a]; | ||
$a[0] = &$b; | ||
// 1401060025140106002514010600250101 could also be serialized as 14010600251401060014010600250101 if we normalized the references which only occurred once in the serialization | ||
// (Replace middle &array(&$a) with array(&$array), i.e. second 2514 with 14) | ||
test_cyclic2('cyclic $a = array(&array(&$a)) - testing functionality', $a); | ||
unset($a); | ||
$a = null; | ||
$a = [[&$a]]; | ||
test_cyclic2('cyclic $a = array(array(&$a)); $a[0] - testing functionality', $a[0]); | ||
// $a serializes as 140106001401060025140106000101 - This is a bug, probably exists in php5 as well. | ||
--EXPECT-- | ||
cyclic $a = array(&array(&$a)) - testing functionality | ||
1401060025140106002514010600250101 | ||
OK | ||
cyclic $a = array(array(&$a)); $a[0] - testing functionality | ||
14010600251401060014010600250101 | ||
OK |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
--TEST-- | ||
Correctly unserialize multiple object refs. | ||
--SKIPIF-- | ||
--INI-- | ||
igbinary.compact_strings = On | ||
--FILE-- | ||
<?php | ||
$a = array(new stdClass()); | ||
$a[1] = &$a[0]; | ||
$a[2] = &$a[1]; | ||
$a[3] = &$a[2]; | ||
printf("%s\n", serialize($a)); | ||
$ig_ser = igbinary_serialize($a); | ||
printf("%s\n", bin2hex($ig_ser)); | ||
$ig = igbinary_unserialize($ig_ser); | ||
printf("%s\n", serialize($ig)); | ||
$f = &$ig[3]; | ||
$f = 'V'; | ||
var_dump($ig); | ||
--EXPECT-- | ||
a:4:{i:0;O:8:"stdClass":0:{}i:1;R:2;i:2;R:2;i:3;R:2;} | ||
0000000214040600251708737464436c6173731400060125220106022522010603252201 | ||
a:4:{i:0;O:8:"stdClass":0:{}i:1;R:2;i:2;R:2;i:3;R:2;} | ||
array(4) { | ||
[0]=> | ||
&string(1) "V" | ||
[1]=> | ||
&string(1) "V" | ||
[2]=> | ||
&string(1) "V" | ||
[3]=> | ||
&string(1) "V" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
--TEST-- | ||
Correctly unserialize multiple array refs. | ||
--SKIPIF-- | ||
--INI-- | ||
igbinary.compact_strings = On | ||
--FILE-- | ||
<?php | ||
$a = array([]); | ||
$a[1] = &$a[0]; | ||
$a[2] = &$a[1]; | ||
$a[3] = &$a[2]; | ||
printf("%s\n", serialize($a)); | ||
$ig_ser = igbinary_serialize($a); | ||
printf("%s\n", bin2hex($ig_ser)); | ||
$ig = igbinary_unserialize($ig_ser); | ||
printf("%s\n", serialize($ig)); | ||
$f = &$ig[3]; | ||
$f = 'V'; | ||
var_dump($ig); | ||
--EXPECT-- | ||
a:4:{i:0;a:0:{}i:1;R:2;i:2;R:2;i:3;R:2;} | ||
0000000214040600251400060125010106022501010603250101 | ||
a:4:{i:0;a:0:{}i:1;R:2;i:2;R:2;i:3;R:2;} | ||
array(4) { | ||
[0]=> | ||
&string(1) "V" | ||
[1]=> | ||
&string(1) "V" | ||
[2]=> | ||
&string(1) "V" | ||
[3]=> | ||
&string(1) "V" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
--TEST-- | ||
Correctly unserialize multiple object refs and non-refs. | ||
--SKIPIF-- | ||
--INI-- | ||
igbinary.compact_strings = On | ||
--FILE-- | ||
<?php | ||
$a = array(new stdClass()); | ||
$a[1] = $a[0]; | ||
$a[2] = &$a[1]; | ||
$a[3] = $a[0]; | ||
var_dump($a); | ||
printf("%s\n", serialize($a)); | ||
$ig_ser = igbinary_serialize($a); | ||
printf("%s\n", bin2hex($ig_ser)); | ||
$ig = igbinary_unserialize($ig_ser); | ||
printf("%s\n", serialize($ig)); | ||
var_dump($ig); | ||
$f = &$ig[2]; | ||
$f = 'V'; | ||
var_dump($ig); | ||
// Note: While the php7 unserializer consistently makes a distinction between refs to an object and non-refs, | ||
// the php5 serializer does not yet. | ||
--EXPECTF-- | ||
array(4) { | ||
[0]=> | ||
object(stdClass)#%d (0) { | ||
} | ||
[1]=> | ||
&object(stdClass)#%d (0) { | ||
} | ||
[2]=> | ||
&object(stdClass)#%d (0) { | ||
} | ||
[3]=> | ||
object(stdClass)#%d (0) { | ||
} | ||
} | ||
a:4:{i:0;O:8:"stdClass":0:{}i:1;R:2;i:2;R:2;i:3;r:2;} | ||
00000002140406001708737464436c61737314000601252201060225220106032201 | ||
a:4:{i:0;O:8:"stdClass":0:{}i:1;R:2;i:2;R:2;i:3;r:2;} | ||
array(4) { | ||
[0]=> | ||
object(stdClass)#%d (0) { | ||
} | ||
[1]=> | ||
&object(stdClass)#%d (0) { | ||
} | ||
[2]=> | ||
&object(stdClass)#%d (0) { | ||
} | ||
[3]=> | ||
object(stdClass)#%d (0) { | ||
} | ||
} | ||
array(4) { | ||
[0]=> | ||
object(stdClass)#%d (0) { | ||
} | ||
[1]=> | ||
&string(1) "V" | ||
[2]=> | ||
&string(1) "V" | ||
[3]=> | ||
object(stdClass)#%d (0) { | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
--TEST-- | ||
Correctly unserialize multiple references in arrays | ||
--SKIPIF-- | ||
--INI-- | ||
igbinary.compact_strings = On | ||
--FILE-- | ||
<?php | ||
class Foo{} | ||
$a = array("A"); | ||
$a[1] = &$a[0]; | ||
$a[2] = &$a[1]; | ||
$a[3] = &$a[2]; | ||
$a[4] = false; | ||
$a[5] = &$a[4]; | ||
$a[6] = new Foo(); | ||
$a[7] = &$a[6]; | ||
$a[8] = &$a[7]; | ||
$a[9] = [33]; | ||
$a[10] = new stdClass(); | ||
$a[10]->prop = &$a[8]; | ||
$a[11] = &$a[10]; | ||
$a[12] = $a[9]; | ||
$ig_ser = igbinary_serialize($a); | ||
printf("ig_ser=%s\n", bin2hex($ig_ser)); | ||
$ig = igbinary_unserialize($ig_ser); | ||
var_dump($ig); | ||
$f = &$ig[3]; | ||
$f = 'V'; | ||
$g = &$ig[5]; | ||
$g = 'H'; | ||
$h = $ig[10]; | ||
$h->prop = 'S'; | ||
var_dump($ig); | ||
--EXPECTF-- | ||
ig_ser=00000002140d0600251101410601250101060225010106032501010604250406052501020606251703466f6f1400060725220306082522030609140106000621060a251708737464436c6173731401110470726f70252203060b252205060c0104 | ||
array(13) { | ||
[0]=> | ||
&string(1) "A" | ||
[1]=> | ||
&string(1) "A" | ||
[2]=> | ||
&string(1) "A" | ||
[3]=> | ||
&string(1) "A" | ||
[4]=> | ||
&bool(false) | ||
[5]=> | ||
&bool(false) | ||
[6]=> | ||
&object(Foo)#%d (0) { | ||
} | ||
[7]=> | ||
&object(Foo)#%d (0) { | ||
} | ||
[8]=> | ||
&object(Foo)#%d (0) { | ||
} | ||
[9]=> | ||
array(1) { | ||
[0]=> | ||
int(33) | ||
} | ||
[10]=> | ||
&object(stdClass)#%d (1) { | ||
["prop"]=> | ||
&object(Foo)#%d (0) { | ||
} | ||
} | ||
[11]=> | ||
&object(stdClass)#%d (1) { | ||
["prop"]=> | ||
&object(Foo)#%d (0) { | ||
} | ||
} | ||
[12]=> | ||
array(1) { | ||
[0]=> | ||
int(33) | ||
} | ||
} | ||
array(13) { | ||
[0]=> | ||
&string(1) "V" | ||
[1]=> | ||
&string(1) "V" | ||
[2]=> | ||
&string(1) "V" | ||
[3]=> | ||
&string(1) "V" | ||
[4]=> | ||
&string(1) "H" | ||
[5]=> | ||
&string(1) "H" | ||
[6]=> | ||
&string(1) "S" | ||
[7]=> | ||
&string(1) "S" | ||
[8]=> | ||
&string(1) "S" | ||
[9]=> | ||
array(1) { | ||
[0]=> | ||
int(33) | ||
} | ||
[10]=> | ||
&object(stdClass)#%d (1) { | ||
["prop"]=> | ||
&string(1) "S" | ||
} | ||
[11]=> | ||
&object(stdClass)#%d (1) { | ||
["prop"]=> | ||
&string(1) "S" | ||
} | ||
[12]=> | ||
array(1) { | ||
[0]=> | ||
int(33) | ||
} | ||
} |
Oops, something went wrong.