Move fiber stack allocation within try

If VM stack allocation fails, the bailout will be caught within the fiber.
This commit is contained in:
Aaron Piotrowski 2021-05-08 23:30:48 -05:00
parent b5c0e7e0ec
commit 3c3ec441e4
No known key found for this signature in database
GPG key ID: ADD1EF783EDE9EEB
2 changed files with 49 additions and 21 deletions

View file

@ -0,0 +1,26 @@
--TEST--
Out of Memory from recursive fiber creation
--INI--
memory_limit=10K
--SKIPIF--
<?php
if (getenv("USE_ZEND_ALLOC") === "0") {
die("skip Zend MM disabled");
}
?>
--FILE--
<?php
function create_fiber(): Fiber
{
$fiber = new Fiber('create_fiber');
$fiber->start();
return $fiber;
}
$fiber = new Fiber('create_fiber');
$fiber->start();
?>
--EXPECTF--
Fatal error: Allowed memory size of %d bytes exhausted%s(tried to allocate %d bytes) in %sout-of-memory-in-recursive-fiber.php on line %d

View file

@ -336,29 +336,31 @@ static void ZEND_STACK_ALIGNED zend_fiber_execute(zend_fiber_context *context)
error_reporting = E_ALL;
}
zend_vm_stack stack = zend_fiber_vm_stack_alloc(ZEND_FIBER_VM_STACK_SIZE);
EG(vm_stack) = stack;
EG(vm_stack_top) = stack->top + ZEND_CALL_FRAME_SLOT;
EG(vm_stack_end) = stack->end;
EG(vm_stack_page_size) = ZEND_FIBER_VM_STACK_SIZE;
fiber->execute_data = (zend_execute_data *) stack->top;
fiber->stack_bottom = fiber->execute_data;
memset(fiber->execute_data, 0, sizeof(zend_execute_data));
fiber->execute_data->func = &zend_fiber_function;
fiber->stack_bottom->prev_execute_data = EG(current_execute_data);
EG(current_execute_data) = fiber->execute_data;
EG(jit_trace_num) = 0;
EG(error_reporting) = error_reporting;
fiber->fci.retval = &fiber->value;
fiber->status = ZEND_FIBER_STATUS_RUNNING;
EG(vm_stack) = NULL;
zend_first_try {
zend_vm_stack stack = zend_fiber_vm_stack_alloc(ZEND_FIBER_VM_STACK_SIZE);
EG(vm_stack) = stack;
EG(vm_stack_top) = stack->top + ZEND_CALL_FRAME_SLOT;
EG(vm_stack_end) = stack->end;
EG(vm_stack_page_size) = ZEND_FIBER_VM_STACK_SIZE;
fiber->execute_data = (zend_execute_data *) stack->top;
fiber->stack_bottom = fiber->execute_data;
memset(fiber->execute_data, 0, sizeof(zend_execute_data));
fiber->execute_data->func = &zend_fiber_function;
fiber->stack_bottom->prev_execute_data = EG(current_execute_data);
EG(current_execute_data) = fiber->execute_data;
EG(jit_trace_num) = 0;
EG(error_reporting) = error_reporting;
fiber->fci.retval = &fiber->value;
fiber->status = ZEND_FIBER_STATUS_RUNNING;
zend_call_function(&fiber->fci, &fiber->fci_cache);
zval_ptr_dtor(&fiber->fci.function_name);