1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
|
--TEST--
Bug #78549: Stack overflow due to nested serialized input
--SKIPIF--
<?php
if (getenv('SKIP_PRELOAD')) die('skip Different order of deprecation messages');
?>
--FILE--
<?php
function create_nested_data($depth, $prefix, $suffix, $inner = 'i:0;') {
return str_repeat($prefix, $depth) . $inner . str_repeat($suffix, $depth);
}
echo "Invalid max_depth:\n";
try {
unserialize('i:0;', ['max_depth' => 'foo']);
} catch (TypeError $exception) {
echo $exception->getMessage() . "\n";
}
try {
unserialize('i:0;', ['max_depth' => -1]);
} catch (ValueError $exception) {
echo $exception->getMessage() . "\n";
}
echo "Array:\n";
var_dump(unserialize(
create_nested_data(128, 'a:1:{i:0;', '}'),
['max_depth' => 128]
) !== false);
var_dump(unserialize(
create_nested_data(129, 'a:1:{i:0;', '}'),
['max_depth' => 128]
));
echo "Object:\n";
var_dump(unserialize(
create_nested_data(128, 'O:8:"stdClass":1:{i:0;', '}'),
['max_depth' => 128]
) !== false);
var_dump(unserialize(
create_nested_data(129, 'O:8:"stdClass":1:{i:0;', '}'),
['max_depth' => 128]
));
// Depth can also be adjusted using ini setting
echo "Ini setting:\n";
ini_set("unserialize_max_depth", 128);
var_dump(unserialize(create_nested_data(128, 'a:1:{i:0;', '}')) !== false);
var_dump(unserialize(create_nested_data(129, 'a:1:{i:0;', '}')));
// But an explicitly specified depth still takes precedence
echo "Ini setting overridden:\n";
var_dump(unserialize(
create_nested_data(256, 'a:1:{i:0;', '}'),
['max_depth' => 256]
) !== false);
var_dump(unserialize(
create_nested_data(257, 'a:1:{i:0;', '}'),
['max_depth' => 256]
));
// Reset ini setting to a large value,
// so it's clear that it won't be used in the following.
ini_set("unserialize_max_depth", 4096);
class Test implements Serializable {
public function serialize() {
return '';
}
public function unserialize($str) {
// Should fail, due to combined nesting level
var_dump(unserialize(create_nested_data(129, 'a:1:{i:0;', '}')));
// Should succeed, below combined nesting level
var_dump(unserialize(create_nested_data(128, 'a:1:{i:0;', '}')) !== false);
}
}
echo "Nested unserialize combined depth limit:\n";
var_dump(is_array(unserialize(
create_nested_data(128, 'a:1:{i:0;', '}', 'C:4:"Test":0:{}'),
['max_depth' => 256]
)));
class Test2 implements Serializable {
public function serialize() {
return '';
}
public function unserialize($str) {
// If depth limit is overridden, the depth should be counted
// from zero again.
var_dump(unserialize(
create_nested_data(257, 'a:1:{i:0;', '}'),
['max_depth' => 256]
));
var_dump(unserialize(
create_nested_data(256, 'a:1:{i:0;', '}'),
['max_depth' => 256]
) !== false);
}
}
echo "Nested unserialize overridden depth limit:\n";
var_dump(is_array(unserialize(
create_nested_data(64, 'a:1:{i:0;', '}', 'C:5:"Test2":0:{}'),
['max_depth' => 128]
)));
?>
--EXPECTF--
Invalid max_depth:
unserialize(): Option "max_depth" must be of type int, string given
unserialize(): Option "max_depth" must be greater than or equal to 0
Array:
bool(true)
Warning: unserialize(): Maximum depth of 128 exceeded. The depth limit can be changed using the max_depth unserialize() option or the unserialize_max_depth ini setting in %s on line %d
Warning: unserialize(): Error at offset 1157 of 1294 bytes in %s on line %d
bool(false)
Object:
bool(true)
Warning: unserialize(): Maximum depth of 128 exceeded. The depth limit can be changed using the max_depth unserialize() option or the unserialize_max_depth ini setting in %s on line %d
Warning: unserialize(): Error at offset 2834 of 2971 bytes in %s on line %d
bool(false)
Ini setting:
bool(true)
Warning: unserialize(): Maximum depth of 128 exceeded. The depth limit can be changed using the max_depth unserialize() option or the unserialize_max_depth ini setting in %s on line %d
Warning: unserialize(): Error at offset 1157 of 1294 bytes in %s on line %d
bool(false)
Ini setting overridden:
bool(true)
Warning: unserialize(): Maximum depth of 256 exceeded. The depth limit can be changed using the max_depth unserialize() option or the unserialize_max_depth ini setting in %s on line %d
Warning: unserialize(): Error at offset 2309 of 2574 bytes in %s on line %d
bool(false)
Deprecated: %s 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
Nested unserialize combined depth limit:
Warning: unserialize(): Maximum depth of 256 exceeded. The depth limit can be changed using the max_depth unserialize() option or the unserialize_max_depth ini setting in %s on line %d
Warning: unserialize(): Error at offset 1157 of 1294 bytes in %s on line %d
bool(false)
bool(true)
bool(true)
Deprecated: %s 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
Nested unserialize overridden depth limit:
Warning: unserialize(): Maximum depth of 256 exceeded. The depth limit can be changed using the max_depth unserialize() option or the unserialize_max_depth ini setting in %s on line %d
Warning: unserialize(): Error at offset 2309 of 2574 bytes in %s on line %d
bool(false)
bool(true)
bool(true)
|