Skip to content

Calling Generator::throw() on a running generator with a non-Generator delegate crashes #19326

@arnaud-lb

Description

@arnaud-lb

Description

Found by @iluuu1994 in #19315 (comment)

The following code:

class It implements IteratorAggregate {
    public function getIterator(): Generator {
        yield "";
        Fiber::suspend();
    }
}

function g() {
    yield from new It();
}

$b = g();
$b->rewind();

$fiber = new Fiber(function () use ($b) {
    $b->next();
});

$fiber->start();

try {
    $b->throw(new Exception('test'));
} catch (Error $e) {
    echo $e->getMessage(), "\n";
}

Resulted in this output:

Output
Cannot resume an already running generator
=================================================================
==1550094==ERROR: AddressSanitizer: heap-use-after-free on address 0x7ba869be9da0 at pc 0x000003022678 bp 0x7b38599fd3e0 sp 0x7b38599fd3d8
READ of size 8 at 0x7ba869be9da0 thread T0
    #0 0x000003022677 in zend_rethrow_exception Zend/zend_exceptions.h:84:6
    #1 0x0000032ae7e6 in ZEND_DO_FCALL_SPEC_RETVAL_UNUSED_HANDLER Zend/zend_vm_execute.h:2036:3
    #2 0x00000304feb7 in execute_ex Zend/zend_vm_execute.h:58709:12
    #3 0x0000036ea3a2 in zend_generator_resume Zend/zend_generators.c:823:3
    #4 0x000003700c4a in zend_generator_iterator_move_forward Zend/zend_generators.c:1155:2
    #5 0x0000036edd36 in zend_generator_get_next_delegated_value Zend/zend_generators.c:699:4
    #6 0x0000036e9433 in zend_generator_resume Zend/zend_generators.c:793:7
    #7 0x0000036f1eef in zim_Generator_next Zend/zend_generators.c:972:2
    #8 0x0000032ad77a in ZEND_DO_FCALL_SPEC_RETVAL_UNUSED_HANDLER Zend/zend_vm_execute.h:1992:4
    #9 0x00000304feb7 in execute_ex Zend/zend_vm_execute.h:58709:12
    #10 0x000002ffbcc0 in zend_call_function Zend/zend_execute_API.c:1012:3
    #11 0x0000036a128c in zend_fiber_execute Zend/zend_fibers.c:604:3
    #12 0x00000369b5a3 in zend_fiber_trampoline Zend/zend_fibers.c:387:2
    #13 0x0000027593ce in trampoline Zend/asm/make_x86_64_sysv_elf_gas.S:177

0x7ba869be9da0 is located 0 bytes inside of 80-byte region [0x7ba869be9da0,0x7ba869be9df0)
freed by thread T0 here:
    #0 0x0000004a5dca in free (sapi/cli/php+0x4a5dca) (BuildId: b8a61168a554287c1cecc178cfb3ec8d9fe72d4a)
    #1 0x000002d07a13 in __zend_free Zend/zend_alloc.c:3589:2
    #2 0x000002d1050e in _efree Zend/zend_alloc.c:2808:3
    #3 0x0000036e1203 in zend_generator_close Zend/zend_generators.c:170:3
    #4 0x0000036f8591 in zend_generator_free_storage Zend/zend_generators.c:362:2
    #5 0x0000039854ec in zend_objects_store_del Zend/zend_objects_API.c:196:4
    #6 0x000003a6b754 in rc_dtor_func Zend/zend_variables.c:57:2
    #7 0x000003a6b996 in i_zval_ptr_dtor Zend/zend_variables.h:45:4
    #8 0x000003a6b784 in zval_ptr_dtor Zend/zend_variables.c:84:2
    #9 0x0000036ffd6b in zend_generator_iterator_dtor Zend/zend_generators.c:1103:2
    #10 0x000003840b23 in iter_wrapper_free Zend/zend_iterators.c:67:2
    #11 0x0000039854ec in zend_objects_store_del Zend/zend_objects_API.c:196:4
    #12 0x000003a6b754 in rc_dtor_func Zend/zend_variables.c:57:2
    #13 0x000003a6b996 in i_zval_ptr_dtor Zend/zend_variables.h:45:4
    #14 0x000003a6b784 in zval_ptr_dtor Zend/zend_variables.c:84:2
    #15 0x0000036ef751 in zend_generator_throw_exception Zend/zend_generators.c:518:3
    #16 0x0000036f43ad in zim_Generator_throw Zend/zend_generators.c:1029:3
    #17 0x0000032ad77a in ZEND_DO_FCALL_SPEC_RETVAL_UNUSED_HANDLER Zend/zend_vm_execute.h:1992:4
    #18 0x00000304feb7 in execute_ex Zend/zend_vm_execute.h:58709:12
    #19 0x0000030511ab in zend_execute Zend/zend_vm_execute.h:64398:2
    #20 0x000003aa8f3f in zend_execute_script Zend/zend.c:1976:3
    #21 0x00000277f9ca in php_execute_script_ex main/main.c:2600:13
    #22 0x0000027801f8 in php_execute_script main/main.c:2640:9
    #23 0x000003ab600b in do_cli sapi/cli/php_cli.c:952:5
    #24 0x000003ab2e04 in main sapi/cli/php_cli.c:1363:18
    #25 0x7f386a8115f4 in __libc_start_call_main (/lib64/libc.so.6+0x35f4) (BuildId: c4b06a608071b2c9852fae62ca3b69cdc22cd022)
    #26 0x7f386a8116a7 in __libc_start_main@GLIBC_2.2.5 (/lib64/libc.so.6+0x36a7) (BuildId: c4b06a608071b2c9852fae62ca3b69cdc22cd022)
    #27 0x000000402554 in _start (sapi/cli/php+0x402554) (BuildId: b8a61168a554287c1cecc178cfb3ec8d9fe72d4a)

previously allocated by thread T0 here:
    #0 0x0000004a6068 in malloc (sapi/cli/php+0x4a6068) (BuildId: b8a61168a554287c1cecc178cfb3ec8d9fe72d4a)
    #1 0x000002d10c93 in __zend_malloc Zend/zend_alloc.c:3561:14
    #2 0x000002d10326 in _emalloc Zend/zend_alloc.c:2798:10
    #3 0x00000349e464 in ZEND_GENERATOR_CREATE_SPEC_HANDLER Zend/zend_vm_execute.h:2318:43
    #4 0x00000304feb7 in execute_ex Zend/zend_vm_execute.h:58709:12
    #5 0x000002ffbcc0 in zend_call_function Zend/zend_execute_API.c:1012:3
    #6 0x000002fffe6a in zend_call_known_function Zend/zend_execute_API.c:1106:23
    #7 0x00000383df98 in zend_call_known_instance_method Zend/zend_API.h:867:2
    #8 0x00000382de4b in zend_call_known_instance_method_with_0_params Zend/zend_API.h:873:2
    #9 0x00000382de13 in zend_user_it_new_iterator Zend/zend_interfaces.c:93:2
    #10 0x000003831614 in zend_user_it_get_new_iterator Zend/zend_interfaces.c:242:2
    #11 0x0000035243f3 in ZEND_YIELD_FROM_SPEC_TMPVAR_HANDLER Zend/zend_vm_execute.h:15630:33
    #12 0x00000304feb7 in execute_ex Zend/zend_vm_execute.h:58709:12
    #13 0x0000036ea3a2 in zend_generator_resume Zend/zend_generators.c:823:3
    #14 0x0000036f01fc in zend_generator_ensure_initialized Zend/zend_generators.c:879:3
    #15 0x0000036efb64 in zend_generator_rewind Zend/zend_generators.c:887:2
    #16 0x0000036efb36 in zim_Generator_rewind Zend/zend_generators.c:904:2
    #17 0x0000032ad77a in ZEND_DO_FCALL_SPEC_RETVAL_UNUSED_HANDLER Zend/zend_vm_execute.h:1992:4
    #18 0x00000304feb7 in execute_ex Zend/zend_vm_execute.h:58709:12
    #19 0x0000030511ab in zend_execute Zend/zend_vm_execute.h:64398:2
    #20 0x000003aa8f3f in zend_execute_script Zend/zend.c:1976:3
    #21 0x00000277f9ca in php_execute_script_ex main/main.c:2600:13
    #22 0x0000027801f8 in php_execute_script main/main.c:2640:9
    #23 0x000003ab600b in do_cli sapi/cli/php_cli.c:952:5
    #24 0x000003ab2e04 in main sapi/cli/php_cli.c:1363:18
    #25 0x7f386a8115f4 in __libc_start_call_main (/lib64/libc.so.6+0x35f4) (BuildId: c4b06a608071b2c9852fae62ca3b69cdc22cd022)
    #26 0x7f386a8116a7 in __libc_start_main@GLIBC_2.2.5 (/lib64/libc.so.6+0x36a7) (BuildId: c4b06a608071b2c9852fae62ca3b69cdc22cd022)
    #27 0x000000402554 in _start (sapi/cli/php+0x402554) (BuildId: b8a61168a554287c1cecc178cfb3ec8d9fe72d4a)

The delegated generator It::getIterator() is released by zend_generator_throw_exception(). We then UFA when resuming the Fiber in it.

PHP Version

PHP 8.3

Operating System

No response

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions