Skip to content

Commit 4318982

Browse files
committed
Fix #79177 Check for undefined result in zend_ffi_callback_trampoline.
This situation can happen when userland exception is thrown within callback body.
1 parent 5215f07 commit 4318982

File tree

2 files changed

+33
-1
lines changed

2 files changed

+33
-1
lines changed

ext/ffi/ffi.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -878,7 +878,7 @@ static void zend_ffi_callback_trampoline(ffi_cif* cif, void* ret, void** args, v
878878
free_alloca(fci.params, use_heap);
879879

880880
ret_type = ZEND_FFI_TYPE(callback_data->type->func.ret_type);
881-
if (ret_type->kind != ZEND_FFI_TYPE_VOID) {
881+
if (ret_type->kind != ZEND_FFI_TYPE_VOID && Z_TYPE(retval) != IS_UNDEF) {
882882
zend_ffi_zval_to_cdata(ret, ret_type, &retval);
883883
}
884884
}

ext/ffi/tests/bug79177.phpt

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
--TEST--
2+
Bug #79177 (FFI doesn't handle well PHP exceptions within callback body)
3+
--SKIPIF--
4+
<?php require_once('skipif.inc');?>
5+
--INI--
6+
ffi.enable=1
7+
--FILE--
8+
<?php
9+
10+
use FFI\CData;
11+
12+
$php = FFI::cdef("
13+
typedef unsigned int fake_struct;
14+
typedef fake_struct* (*zend_write_func_t)(const char *str, size_t str_length);
15+
extern zend_write_func_t zend_write;
16+
");
17+
18+
$originalHandler = clone $php->zend_write;
19+
$php->zend_write = function($str, $len): CData {
20+
throw new \RuntimeException('Not allowed');
21+
};
22+
try {
23+
echo "After", PHP_EOL;
24+
} catch (\Throwable $exception) {
25+
// Do not output anything here, as handler is overridden
26+
} finally {
27+
$php->zend_write = $originalHandler;
28+
}
29+
echo get_class($exception), ': ', $exception->getMessage(), PHP_EOL;
30+
?>
31+
--EXPECT--
32+
RuntimeException: Not allowed

0 commit comments

Comments
 (0)