diff options
author | Christoph M. Becker <cmbecker69@gmx.de> | 2020-10-28 12:01:28 +0100 |
---|---|---|
committer | Christoph M. Becker <cmbecker69@gmx.de> | 2020-10-28 13:34:56 +0100 |
commit | f547412cba52b499a4a130b0de1b6af2ea746e3a (patch) | |
tree | aaf926688964127bceef640b62a6ff8f0948ded7 | |
parent | 68dcaa29d8a2d51f0fed5fde9f3543a1338bfe44 (diff) | |
download | php-git-f547412cba52b499a4a130b0de1b6af2ea746e3a.tar.gz |
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] <https://github.com/php/php-src/pull/5120>
Closes GH-6366.
-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 |