Skip to content

Commit 0427dcb

Browse files
committed
Fix bug79177.phpt wrt. JIT
JIT ignores that the `zend_write` callback is overwritten, so we define our own callback and caller. We also fix the "inconsistent DLL binding" warnings on Windows, by introducing `PHP_ZEND_TEST_API`. Closes GH-6391.
1 parent b5481de commit 0427dcb

File tree

3 files changed

+42
-30
lines changed

3 files changed

+42
-30
lines changed

ext/ffi/tests/bug79177.phpt

Lines changed: 23 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -2,46 +2,41 @@
22
Bug #79177 (FFI doesn't handle well PHP exceptions within callback)
33
--SKIPIF--
44
<?php
5-
require_once('skipif.inc');
6-
require_once('utils.inc');
7-
try {
8-
ffi_cdef("extern void *zend_printf;", ffi_get_php_dll_name());
9-
} catch (Throwable $e) {
10-
die('skip PHP symbols not available');
11-
}
5+
if (!extension_loaded('ffi')) die('skip ffi extension not available');
6+
if (!extension_loaded('zend-test')) die('skip zend-test extension not available');
127
?>
138
--FILE--
149
<?php
15-
require_once('utils.inc');
16-
$php = ffi_cdef("
17-
typedef char (*zend_write_func_t)(const char *str, size_t str_length);
18-
extern zend_write_func_t zend_write;
19-
", ffi_get_php_dll_name());
10+
require_once __DIR__ . '/utils.inc';
11+
$header = <<<HEADER
12+
extern int *(*bug79177_cb)(void);
13+
void bug79177(void);
14+
HEADER;
2015

21-
echo "Before\n";
16+
if (PHP_OS_FAMILY !== 'Windows') {
17+
$ffi = FFI::cdef($header);
18+
} else {
19+
try {
20+
$ffi = FFI::cdef($header, 'php_zend_test.dll');
21+
} catch (FFI\Exception $ex) {
22+
$ffi = FFI::cdef($header, ffi_get_php_dll_name());
23+
}
24+
}
2225

23-
$originalHandler = clone $php->zend_write;
24-
$php->zend_write = function($str, $len): string {
26+
$ffi->bug79177_cb = function() {
2527
throw new \RuntimeException('Not allowed');
2628
};
2729
try {
28-
echo "After\n";
29-
} catch (\Throwable $exception) {
30-
// Do not output anything here, as handler is overridden
31-
} finally {
32-
$php->zend_write = $originalHandler;
33-
}
34-
if (isset($exception)) {
35-
echo $exception->getMessage(), PHP_EOL;
36-
}
30+
$ffi->bug79177(); // this is supposed to raise a fatal error
31+
} catch (\Throwable $exception) {}
32+
echo "done\n";
3733
?>
3834
--EXPECTF--
39-
Before
40-
4135
Warning: Uncaught RuntimeException: Not allowed in %s:%d
4236
Stack trace:
43-
#0 %s(%d): {closure}('After\n', 6)
44-
#1 {main}
37+
#0 %s(%d): {closure}()
38+
#1 %s(%d): FFI->bug79177()
39+
#2 {main}
4540
thrown in %s on line %d
4641

4742
Fatal error: Throwing from FFI callbacks is not allowed in %s on line %d

ext/zend_test/php_test.h

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,18 @@ struct bug79096 {
3737
uint64_t b;
3838
};
3939

40-
ZEND_API struct bug79096 bug79096(void);
41-
ZEND_API void bug79532(off_t *array, size_t elems);
40+
#ifdef PHP_WIN32
41+
# define PHP_ZEND_TEST_API __declspec(dllexport)
42+
#elif defined(__GNUC__) && __GNUC__ >= 4
43+
# define PHP_ZEND_TEST_API __attribute__ ((visibility("default")))
44+
#else
45+
# define PHP_ZEND_TEST_API
46+
#endif
47+
48+
PHP_ZEND_TEST_API struct bug79096 bug79096(void);
49+
PHP_ZEND_TEST_API void bug79532(off_t *array, size_t elems);
50+
51+
extern PHP_ZEND_TEST_API int *(*bug79177_cb)(void);
52+
PHP_ZEND_TEST_API void bug79177(void);
4253

4354
#endif

ext/zend_test/test.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -336,3 +336,9 @@ void bug79532(off_t *array, size_t elems)
336336
array[i] = i;
337337
}
338338
}
339+
340+
PHP_ZEND_TEST_API int *(*bug79177_cb)(void);
341+
void bug79177(void)
342+
{
343+
bug79177_cb();
344+
}

0 commit comments

Comments
 (0)