1--TEST-- 2Exceptions thrown in operand cleaning must cause leak of return value 3--FILE-- 4<?php 5 6try { 7 var_dump(new class { 8 function __toString() { return "a"; } 9 function __destruct() { throw new Exception; } 10 } . "foo"); 11} catch (Exception $e) { print "caught Exception 1\n"; } 12 13try { 14 var_dump([0] + [new class { 15 function __destruct() { throw new Exception; } 16 }]); 17} catch (Exception $e) { print "caught Exception 2\n"; } 18 19try { 20 $foo = [0]; 21 var_dump($foo += [new class { 22 function __destruct() { throw new Exception; } 23 }]); 24} catch (Exception $e) { print "caught Exception 3\n"; } 25 26try { 27 $foo = (object)["foo" => [0]]; 28 var_dump($foo->foo += [new class { 29 function __destruct() { throw new Exception; } 30 }]); 31} catch (Exception $e) { print "caught Exception 4\n"; } 32 33try { 34 $foo = new class { 35 function __get($x) { return [0]; } 36 function __set($x, $y) {} 37 }; 38 var_dump($foo->foo += [new class { 39 function __destruct() { throw new Exception; } 40 }]); 41} catch (Exception $e) { print "caught Exception 5\n"; } 42 43try { 44 $foo = new class { 45 public $bar = [0]; 46 function &__get($x) { return $this->bar; } 47 }; 48 var_dump($foo->foo += [new class { 49 function __destruct() { throw new Exception; } 50 }]); 51} catch (Exception $e) { print "caught Exception 6\n"; } 52 53try { 54 $foo = new class implements ArrayAccess { 55 function offsetGet($x): mixed { return [0]; } 56 function offsetSet($x, $y): void {} 57 function offsetExists($x): bool { return true; } 58 function offsetUnset($x): void {} 59 }; 60 var_dump($foo[0] += [new class { 61 function __destruct() { throw new Exception; } 62 }]); 63} catch (Exception $e) { print "caught Exception 7\n"; } 64 65try { 66 $foo = new class implements ArrayAccess { 67 public $foo = [0]; 68 function &offsetGet($x): bool { return $this->foo; } 69 function offsetSet($x, $y): void {} 70 function offsetExists($x): bool { return true; } 71 function offsetUnset($x): void {} 72 }; 73 var_dump($foo[0] += [new class { 74 function __destruct() { throw new Exception; } 75 }]); 76} catch (Exception $e) { print "caught Exception 8\n"; } 77 78try { 79 var_dump((function() { return new class { 80 public $foo; 81 function __construct() { $this->foo = new stdClass; } 82 function __destruct() { throw new Exception; } 83 }; })()->foo++); 84} catch (Exception $e) { print "caught Exception 9\n"; } 85 86try { 87 var_dump((function() { return new class { 88 function __get($x) { return new stdClass; } 89 function __set($x, $y) {} 90 function __destruct() { throw new Exception; } 91 }; })()->foo++); 92} catch (Exception $e) { print "caught Exception 10\n"; } 93 94try { 95 var_dump((function() { return new class { 96 public $bar; 97 function __construct() { $this->bar = new stdClass; } 98 function &__get($x) { return $this->bar; } 99 function __destruct() { throw new Exception; } 100 }; })()->foo++); 101} catch (Exception $e) { print "caught Exception 11\n"; } 102 103try { 104 var_dump(++(function() { return new class { 105 function __construct() { $this->foo = new stdClass; } 106 function __destruct() { throw new Exception; } 107 }; })()->foo); 108} catch (Exception $e) { print "caught Exception 12\n"; } 109 110try { 111 var_dump(++(function() { return new class { 112 function __get($x) { return new stdClass; } 113 function __set($x, $y) {} 114 function __destruct() { throw new Exception; } 115 }; })()->foo); 116} catch (Exception $e) { print "caught Exception 13\n"; } 117 118try { 119 var_dump(++(function() { return new class { 120 public $bar; 121 function __construct() { $this->bar = new stdClass; } 122 function &__get($x) { return $this->bar; } 123 function __destruct() { throw new Exception; } 124 }; })()->foo); 125} catch (Exception $e) { print "caught Exception 14\n"; } 126 127try { 128 var_dump((function() { return new class implements ArrayAccess { 129 function offsetGet($x): mixed { return [new stdClass]; } 130 function offsetSet($x, $y): void {} 131 function offsetExists($x): bool { return true; } 132 function offsetUnset($x): void {} 133 function __destruct() { throw new Exception; } 134 }; })()[0]++); 135} catch (Exception $e) { print "caught Exception 15\n"; } 136 137try { 138 var_dump(++(function() { return new class implements ArrayAccess { 139 function offsetGet($x): mixed { return [new stdClass]; } 140 function offsetSet($x, $y): void {} 141 function offsetExists($x): bool { return true; } 142 function offsetUnset($x): void {} 143 function __destruct() { throw new Exception; } 144 }; })()[0]); 145} catch (Exception $e) { print "caught Exception 16\n"; } 146 147try { 148 var_dump((new class { 149 public $foo; 150 function __construct() { $this->foo = new stdClass; } 151 function __destruct() { throw new Exception; } 152 })->foo); 153} catch (Exception $e) { print "caught Exception 17\n"; } 154 155try { 156 var_dump((new class { 157 function __get($x) { return new stdClass; } 158 function __set($x, $y) {} 159 function __destruct() { throw new Exception; } 160 })->foo); 161} catch (Exception $e) { print "caught Exception 18\n"; } 162 163try { 164 var_dump((new class implements ArrayAccess { 165 function offsetGet($x): mixed { return [new stdClass]; } 166 function offsetSet($x, $y): void {} 167 function offsetExists($x): bool { return true; } 168 function offsetUnset($x): void {} 169 function __destruct() { throw new Exception; } 170 })[0]); 171} catch (Exception $e) { print "caught Exception 19\n"; } 172 173try { 174 var_dump(isset((new class { 175 public $foo; 176 function __construct() { $this->foo = new stdClass; } 177 function __destruct() { throw new Exception; } 178 })->foo->bar)); 179} catch (Exception $e) { print "caught Exception 20\n"; } 180 181try { 182 var_dump(isset((new class { 183 function __get($x) { return new stdClass; } 184 function __set($x, $y) {} 185 function __destruct() { throw new Exception; } 186 })->foo->bar)); 187} catch (Exception $e) { print "caught Exception 21\n"; } 188 189try { 190 var_dump(isset((new class implements ArrayAccess { 191 function offsetGet($x): mixed { return [new stdClass]; } 192 function offsetSet($x, $y): void {} 193 function offsetExists($x): bool { return true; } 194 function offsetUnset($x): void {} 195 function __destruct() { throw new Exception; } 196 })[0]->bar)); 197} catch (Exception $e) { print "caught Exception 22\n"; } 198 199try { 200 $foo = new class { 201 function __destruct() { throw new Exception; } 202 }; 203 var_dump($foo = new stdClass); 204} catch (Exception $e) { print "caught Exception 23\n"; } 205 206try { 207 $foo = [new class { 208 function __destruct() { throw new Exception; } 209 }]; 210 var_dump($foo[0] = new stdClass); 211} catch (Exception $e) { print "caught Exception 24\n"; } 212 213try { 214 $foo = (object) ["foo" => new class { 215 function __destruct() { throw new Exception; } 216 }]; 217 var_dump($foo->foo = new stdClass); 218} catch (Exception $e) { print "caught Exception 25\n"; } 219 220try { 221 $foo = new class { 222 function __get($x) {} 223 function __set($x, $y) { throw new Exception; } 224 }; 225 var_dump($foo->foo = new stdClass); 226} catch (Exception $e) { print "caught Exception 26\n"; } 227 228try { 229 $foo = new class implements ArrayAccess { 230 function offsetGet($x): mixed {} 231 function offsetSet($x, $y): void { throw new Exception; } 232 function offsetExists($x): bool { return true; } 233 function offsetUnset($x): void {} 234 }; 235 var_dump($foo[0] = new stdClass); 236} catch (Exception $e) { print "caught Exception 27\n"; } 237 238try { 239 $foo = new class { 240 function __destruct() { throw new Exception; } 241 }; 242 $bar = new stdClass; 243 var_dump($foo = &$bar); 244} catch (Exception $e) { print "caught Exception 28\n"; } 245 246try { 247 $f = function() { 248 return new class { 249 function __toString() { return "a"; } 250 function __destruct() { throw new Exception; } 251 }; 252 }; 253 var_dump("{$f()}foo"); 254} catch (Exception $e) { print "caught Exception 29\n"; } 255 256try { 257 $f = function() { 258 return new class { 259 function __toString() { return "a"; } 260 function __destruct() { throw new Exception; } 261 }; 262 }; 263 var_dump("bar{$f()}foo"); 264} catch (Exception $e) { print "caught Exception 30\n"; } 265 266try { 267 var_dump((string) new class { 268 function __toString() { $x = "Z"; return ++$x; } 269 function __destruct() { throw new Exception; } 270 }); 271} catch (Exception $e) { print "caught Exception 31\n"; } 272 273try { 274 var_dump(clone (new class { 275 function __clone() { throw new Exception; } 276 })); 277} catch (Exception $e) { print "caught Exception 32\n"; } 278 279?> 280--EXPECTF-- 281caught Exception 1 282caught Exception 2 283caught Exception 3 284caught Exception 4 285caught Exception 5 286 287Deprecated: Creation of dynamic property class@anonymous::$foo is deprecated in %s on line %d 288caught Exception 6 289caught Exception 7 290caught Exception 8 291caught Exception 9 292caught Exception 10 293 294Deprecated: Creation of dynamic property class@anonymous::$foo is deprecated in %s on line %d 295caught Exception 11 296 297Deprecated: Creation of dynamic property class@anonymous::$foo is deprecated in %s on line %d 298caught Exception 12 299caught Exception 13 300 301Deprecated: Creation of dynamic property class@anonymous::$foo is deprecated in %s on line %d 302caught Exception 14 303 304Notice: Indirect modification of overloaded element of ArrayAccess@anonymous has no effect in %s on line %d 305caught Exception 15 306 307Notice: Indirect modification of overloaded element of ArrayAccess@anonymous has no effect in %s on line %d 308caught Exception 16 309caught Exception 17 310caught Exception 18 311caught Exception 19 312caught Exception 20 313caught Exception 21 314caught Exception 22 315caught Exception 23 316caught Exception 24 317caught Exception 25 318caught Exception 26 319caught Exception 27 320caught Exception 28 321caught Exception 29 322caught Exception 30 323caught Exception 31 324caught Exception 32 325