From f547412cba52b499a4a130b0de1b6af2ea746e3a Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Wed, 28 Oct 2020 12:01:28 +0100 Subject: [PATCH] Fix #79177: FFI doesn't handle well PHP exceptions within callback We have to error on unhandled exceptions in FFI callbacks, to avoid passing back undefined values. This has been discussed and agreed upon in a previous PR[1]. [1] Closes GH-6366. --- NEWS | 4 ++++ ext/ffi/ffi.c | 4 ++++ ext/ffi/tests/bug79177.phpt | 47 +++++++++++++++++++++++++++++++++++++ 3 files changed, 55 insertions(+) create mode 100644 ext/ffi/tests/bug79177.phpt diff --git a/NEWS b/NEWS index 95de673b3f..017896befa 100644 --- a/NEWS +++ b/NEWS @@ -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-- + +--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 -- 2.50.1