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