Skip to content

Commit 3c3ec44

Browse files
committed
Move fiber stack allocation within try
If VM stack allocation fails, the bailout will be caught within the fiber.
1 parent b5c0e7e commit 3c3ec44

File tree

2 files changed

+44
-16
lines changed

2 files changed

+44
-16
lines changed
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
--TEST--
2+
Out of Memory from recursive fiber creation
3+
--INI--
4+
memory_limit=10K
5+
--SKIPIF--
6+
<?php
7+
if (getenv("USE_ZEND_ALLOC") === "0") {
8+
die("skip Zend MM disabled");
9+
}
10+
?>
11+
--FILE--
12+
<?php
13+
14+
function create_fiber(): Fiber
15+
{
16+
$fiber = new Fiber('create_fiber');
17+
$fiber->start();
18+
return $fiber;
19+
}
20+
21+
$fiber = new Fiber('create_fiber');
22+
$fiber->start();
23+
24+
?>
25+
--EXPECTF--
26+
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

Zend/zend_fibers.c

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -336,29 +336,31 @@ static void ZEND_STACK_ALIGNED zend_fiber_execute(zend_fiber_context *context)
336336
error_reporting = E_ALL;
337337
}
338338

339-
zend_vm_stack stack = zend_fiber_vm_stack_alloc(ZEND_FIBER_VM_STACK_SIZE);
340-
EG(vm_stack) = stack;
341-
EG(vm_stack_top) = stack->top + ZEND_CALL_FRAME_SLOT;
342-
EG(vm_stack_end) = stack->end;
343-
EG(vm_stack_page_size) = ZEND_FIBER_VM_STACK_SIZE;
339+
EG(vm_stack) = NULL;
344340

345-
fiber->execute_data = (zend_execute_data *) stack->top;
346-
fiber->stack_bottom = fiber->execute_data;
341+
zend_first_try {
342+
zend_vm_stack stack = zend_fiber_vm_stack_alloc(ZEND_FIBER_VM_STACK_SIZE);
343+
EG(vm_stack) = stack;
344+
EG(vm_stack_top) = stack->top + ZEND_CALL_FRAME_SLOT;
345+
EG(vm_stack_end) = stack->end;
346+
EG(vm_stack_page_size) = ZEND_FIBER_VM_STACK_SIZE;
347347

348-
memset(fiber->execute_data, 0, sizeof(zend_execute_data));
348+
fiber->execute_data = (zend_execute_data *) stack->top;
349+
fiber->stack_bottom = fiber->execute_data;
349350

350-
fiber->execute_data->func = &zend_fiber_function;
351-
fiber->stack_bottom->prev_execute_data = EG(current_execute_data);
351+
memset(fiber->execute_data, 0, sizeof(zend_execute_data));
352352

353-
EG(current_execute_data) = fiber->execute_data;
354-
EG(jit_trace_num) = 0;
355-
EG(error_reporting) = error_reporting;
353+
fiber->execute_data->func = &zend_fiber_function;
354+
fiber->stack_bottom->prev_execute_data = EG(current_execute_data);
356355

357-
fiber->fci.retval = &fiber->value;
356+
EG(current_execute_data) = fiber->execute_data;
357+
EG(jit_trace_num) = 0;
358+
EG(error_reporting) = error_reporting;
358359

359-
fiber->status = ZEND_FIBER_STATUS_RUNNING;
360+
fiber->fci.retval = &fiber->value;
361+
362+
fiber->status = ZEND_FIBER_STATUS_RUNNING;
360363

361-
zend_first_try {
362364
zend_call_function(&fiber->fci, &fiber->fci_cache);
363365

364366
zval_ptr_dtor(&fiber->fci.function_name);

0 commit comments

Comments
 (0)