153 lines
4.9 KiB
PHP
153 lines
4.9 KiB
PHP
--TEST--
|
|
Bug #78549: Stack overflow due to nested serialized input
|
|
--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
|
|
|
|
Notice: 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
|
|
|
|
Notice: 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
|
|
|
|
Notice: 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
|
|
|
|
Notice: unserialize(): Error at offset 2309 of 2574 bytes in %s on line %d
|
|
bool(false)
|
|
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
|
|
|
|
Notice: unserialize(): Error at offset 1157 of 1294 bytes in %s on line %d
|
|
bool(false)
|
|
bool(true)
|
|
bool(true)
|
|
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
|
|
|
|
Notice: unserialize(): Error at offset 2309 of 2574 bytes in %s on line %d
|
|
bool(false)
|
|
bool(true)
|
|
bool(true)
|