Skip to content

Commit

Permalink
Fix #79177: FFI doesn't handle well PHP exceptions within callback
Browse files Browse the repository at this point in the history
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] <#5120>

Closes GH-6366.
  • Loading branch information
cmb69 committed Oct 28, 2020
1 parent 68dcaa2 commit f547412
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 0 deletions.
4 changes: 4 additions & 0 deletions NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
4 changes: 4 additions & 0 deletions ext/ffi/ffi.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
47 changes: 47 additions & 0 deletions ext/ffi/tests/bug79177.phpt
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit f547412

Please sign in to comment.