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