mirror of
https://github.com/php/php-src.git
synced 2026-04-30 03:33:17 +02:00
81d95c4c3c
The default depth is large enough to cause stack overflows in msan builds, though apparently only on old clang versions. Avoiding a stack overflow there requires making the depth *much* smaller, less than 1000. As I don't think that's reasonable for all the other setups where 4k works fine, I'm just dropping this part of the test.
148 lines
4.8 KiB
PHP
148 lines
4.8 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";
|
|
var_dump(unserialize('i:0;', ['max_depth' => 'foo']));
|
|
var_dump(unserialize('i:0;', ['max_depth' => -1]));
|
|
|
|
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 succeeed, 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:
|
|
|
|
Warning: unserialize(): max_depth should be int in %s on line %d
|
|
bool(false)
|
|
|
|
Warning: unserialize(): max_depth cannot be negative in %s on line %d
|
|
bool(false)
|
|
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)
|