diff --git a/ext/ffi/ffi.c b/ext/ffi/ffi.c index f350f91d8a3c2..d119ea050cbf5 100644 --- a/ext/ffi/ffi.c +++ b/ext/ffi/ffi.c @@ -886,6 +886,10 @@ static void zend_ffi_callback_trampoline(ffi_cif* cif, void* ret, void** args, v } free_alloca(fci.params, use_heap); + if (EG(exception)) { + zend_error(E_ERROR, "Throwing from FFI callbacks is not allowed"); + } + ret_type = ZEND_FFI_TYPE(callback_data->type->func.ret_type); if (ret_type->kind != ZEND_FFI_TYPE_VOID) { zend_ffi_zval_to_cdata(ret, ret_type, &retval); diff --git a/ext/ffi/tests/bug79177.phpt b/ext/ffi/tests/bug79177.phpt new file mode 100644 index 0000000000000..d764437b2d50c --- /dev/null +++ b/ext/ffi/tests/bug79177.phpt @@ -0,0 +1,47 @@ +--TEST-- +Bug #79177 (FFI doesn't handle well PHP exceptions within callback) +--SKIPIF-- + +--FILE-- +zend_write; +$php->zend_write = function($str, $len): string { + throw new \RuntimeException('Not allowed'); +}; +try { + echo "After\n"; +} catch (\Throwable $exception) { + // Do not output anything here, as handler is overridden +} finally { + $php->zend_write = $originalHandler; +} +if (isset($exception)) { + echo $exception->getMessage(), PHP_EOL; +} +?> +--EXPECTF-- +Before + +Warning: Uncaught RuntimeException: Not allowed in %s:%d +Stack trace: +#0 %s(%d): {closure}('After\n', 6) +#1 {main} + thrown in %s on line %d + +Fatal error: Throwing from FFI callbacks is not allowed in %s on line %d