diff options
-rw-r--r-- | NEWS | 4 | ||||
-rw-r--r-- | ext/ffi/ffi.c | 4 | ||||
-rw-r--r-- | ext/ffi/tests/bug79177.phpt | 47 |
3 files changed, 55 insertions, 0 deletions
@@ -14,6 +14,10 @@ PHP NEWS - DOM: . Fixed bug #80268 (loadHTML() truncates at NUL bytes). (cmb) +- FFI: + . Fixed bug #79177 (FFI doesn't handle well PHP exceptions within callback). + (cmb, Dmitry, Nikita) + - IMAP: . Fixed bug #64076 (imap_sort() does not return FALSE on failure). (cmb) . Fixed bug #76618 (segfault on imap_reopen). (girgias) diff --git a/ext/ffi/ffi.c b/ext/ffi/ffi.c index f350f91d8a..d119ea050c 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 0000000000..d764437b2d --- /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-- +<?php +require_once('skipif.inc'); +require_once('utils.inc'); +try { + ffi_cdef("extern void *zend_printf;", ffi_get_php_dll_name()); +} catch (Throwable $e) { + die('skip PHP symbols not available'); +} +?> +--FILE-- +<?php +require_once('utils.inc'); +$php = ffi_cdef(" +typedef char (*zend_write_func_t)(const char *str, size_t str_length); +extern zend_write_func_t zend_write; +", ffi_get_php_dll_name()); + +echo "Before\n"; + +$originalHandler = clone $php->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 |