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