mirror of
https://github.com/php/php-src.git
synced 2025-08-15 21:48:51 +02:00
Fix generator memory leaks when interrupted during argument evaluation (#9756)
This commit is contained in:
parent
75970077b0
commit
5d1f3e047c
14 changed files with 537 additions and 3 deletions
|
@ -95,6 +95,20 @@ ZEND_API zend_execute_data* zend_generator_freeze_call_stack(zend_execute_data *
|
|||
}
|
||||
/* }}} */
|
||||
|
||||
static zend_execute_data* zend_generator_revert_call_stack(zend_execute_data *call)
|
||||
{
|
||||
zend_execute_data *prev = NULL;
|
||||
|
||||
do {
|
||||
zend_execute_data *next = call->prev_execute_data;
|
||||
call->prev_execute_data = prev;
|
||||
prev = call;
|
||||
call = next;
|
||||
} while (call);
|
||||
|
||||
return prev;
|
||||
}
|
||||
|
||||
static void zend_generator_cleanup_unfinished_execution(
|
||||
zend_generator *generator, zend_execute_data *execute_data, uint32_t catch_op_num) /* {{{ */
|
||||
{
|
||||
|
@ -370,6 +384,15 @@ static HashTable *zend_generator_get_gc(zend_object *object, zval **table, int *
|
|||
zend_get_gc_buffer_add_zval(gc_buffer, &extra_named_params);
|
||||
}
|
||||
|
||||
if (UNEXPECTED(generator->frozen_call_stack)) {
|
||||
/* The frozen stack is linked in reverse order */
|
||||
zend_execute_data *call = zend_generator_revert_call_stack(generator->frozen_call_stack);
|
||||
/* -1 required because we want the last run opcode, not the next to-be-run one. */
|
||||
uint32_t op_num = execute_data->opline - op_array->opcodes - 1;
|
||||
zend_unfinished_calls_gc(execute_data, call, op_num, gc_buffer);
|
||||
zend_generator_revert_call_stack(call);
|
||||
}
|
||||
|
||||
if (execute_data->opline != op_array->opcodes) {
|
||||
uint32_t i, op_num = execute_data->opline - op_array->opcodes - 1;
|
||||
for (i = 0; i < op_array->last_live_range; i++) {
|
||||
|
@ -604,7 +627,7 @@ ZEND_API zend_generator *zend_generator_update_current(zend_generator *generator
|
|||
static zend_result zend_generator_get_next_delegated_value(zend_generator *generator) /* {{{ */
|
||||
{
|
||||
--generator->execute_data->opline;
|
||||
|
||||
|
||||
zval *value;
|
||||
if (Z_TYPE(generator->values) == IS_ARRAY) {
|
||||
HashTable *ht = Z_ARR(generator->values);
|
||||
|
@ -670,7 +693,7 @@ static zend_result zend_generator_get_next_delegated_value(zend_generator *gener
|
|||
ZVAL_LONG(&generator->key, iter->index);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
++generator->execute_data->opline;
|
||||
return SUCCESS;
|
||||
|
||||
|
@ -726,7 +749,7 @@ try_again:
|
|||
generator->execute_data->prev_execute_data = &orig_generator->execute_fake;
|
||||
orig_generator->execute_fake.prev_execute_data = original_execute_data;
|
||||
}
|
||||
|
||||
|
||||
/* Ensure this is run after executor_data swap to have a proper stack trace */
|
||||
if (UNEXPECTED(!Z_ISUNDEF(generator->values))) {
|
||||
if (EXPECTED(zend_generator_get_next_delegated_value(generator) == SUCCESS)) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue