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