File tree Expand file tree Collapse file tree 4 files changed +92
-1
lines changed Expand file tree Collapse file tree 4 files changed +92
-1
lines changed Original file line number Diff line number Diff line change 1+ --TEST--
2+ GH-11028 (Heap Buffer Overflow in zval_undefined_cv with generators) - other types variant
3+ --FILE--
4+ <?php
5+ function generator ($ x ) {
6+ try {
7+ yield $ x => 0 ;
8+ } finally {
9+ return [];
10+ }
11+ }
12+
13+ function test ($ msg , $ x ) {
14+ echo "yield $ msg \n" ;
15+ try {
16+ var_dump ([...generator ($ x )]);
17+ } catch (Throwable $ e ) {
18+ echo $ e ->getMessage (), "\n" ;
19+ }
20+ }
21+
22+ test ("null " , null );
23+ test ("false " , false );
24+ test ("true " , true );
25+ test ("object " , new stdClass );
26+ ?>
27+ --EXPECT--
28+ yield null
29+ Keys must be of type int|string during array unpacking
30+ yield false
31+ Keys must be of type int|string during array unpacking
32+ yield true
33+ Keys must be of type int|string during array unpacking
34+ yield object
35+ Keys must be of type int|string during array unpacking
Original file line number Diff line number Diff line change 1+ --TEST--
2+ GH-11028 (Heap Buffer Overflow in zval_undefined_cv with generators) - original variant
3+ --FILE--
4+ <?php
5+ $ c = (function () {
6+ [
7+ ...($ r = (function () {
8+ try {
9+ yield $ a => 0 ;
10+ } finally {
11+ return [];
12+ }
13+ })()),
14+ ];
15+ })()[0 ];
16+ ?>
17+ --EXPECTF--
18+ Warning: Undefined variable $a in %s on line %d
19+
20+ Fatal error: Uncaught Error: Keys must be of type int|string during array unpacking in %s:%d
21+ Stack trace:
22+ #0 %s(%d): {closure}()
23+ #1 {main}
24+ thrown in %s on line %d
Original file line number Diff line number Diff line change 1+ --TEST--
2+ GH-11028 (Heap Buffer Overflow in zval_undefined_cv with generators) - throw in finally variant
3+ --FILE--
4+ <?php
5+ function generator () {
6+ try {
7+ yield null => 0 ;
8+ } finally {
9+ throw new Exception ("exception " );
10+ return [];
11+ }
12+ }
13+
14+ try {
15+ var_dump ([...generator ()]);
16+ } catch (Throwable $ e ) {
17+ echo $ e ->getMessage (), "\n" ;
18+ }
19+ ?>
20+ --EXPECT--
21+ exception
Original file line number Diff line number Diff line change @@ -279,14 +279,25 @@ static void zend_generator_dtor_storage(zend_object *object) /* {{{ */
279279 ZEND_CALL_VAR (ex , ex -> func -> op_array .opcodes [try_catch -> finally_end ].op1 .var );
280280
281281 zend_generator_cleanup_unfinished_execution (generator , ex , try_catch -> finally_op );
282- Z_OBJ_P (fast_call ) = EG (exception );
282+ zend_object * old_exception = EG (exception );
283+ const zend_op * old_opline_before_exception = EG (opline_before_exception );
283284 EG (exception ) = NULL ;
285+ Z_OBJ_P (fast_call ) = NULL ;
284286 Z_OPLINE_NUM_P (fast_call ) = (uint32_t )-1 ;
285287
286288 ex -> opline = & ex -> func -> op_array .opcodes [try_catch -> finally_op ];
287289 generator -> flags |= ZEND_GENERATOR_FORCED_CLOSE ;
288290 zend_generator_resume (generator );
289291
292+ if (old_exception ) {
293+ EG (opline_before_exception ) = old_opline_before_exception ;
294+ if (EG (exception )) {
295+ zend_exception_set_previous (EG (exception ), old_exception );
296+ } else {
297+ EG (exception ) = old_exception ;
298+ }
299+ }
300+
290301 /* TODO: If we hit another yield inside try/finally,
291302 * should we also jump to the next finally block? */
292303 break ;
You can’t perform that action at this time.
0 commit comments