Skip to content

Commit

Permalink
Fix bug79177.phpt wrt. JIT
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
cmb69 committed Oct 30, 2020
1 parent b5481de commit 0427dcb
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 30 deletions.
51 changes: 23 additions & 28 deletions ext/ffi/tests/bug79177.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -2,46 +2,41 @@
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');
}
if (!extension_loaded('ffi')) die('skip ffi extension not available');
if (!extension_loaded('zend-test')) die('skip zend-test extension 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());
require_once __DIR__ . '/utils.inc';
$header = <<<HEADER
extern int *(*bug79177_cb)(void);
void bug79177(void);
HEADER;

echo "Before\n";
if (PHP_OS_FAMILY !== 'Windows') {
$ffi = FFI::cdef($header);
} else {
try {
$ffi = FFI::cdef($header, 'php_zend_test.dll');
} catch (FFI\Exception $ex) {
$ffi = FFI::cdef($header, ffi_get_php_dll_name());
}
}

$originalHandler = clone $php->zend_write;
$php->zend_write = function($str, $len): string {
$ffi->bug79177_cb = function() {
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;
}
$ffi->bug79177(); // this is supposed to raise a fatal error
} catch (\Throwable $exception) {}
echo "done\n";
?>
--EXPECTF--
Before

Warning: Uncaught RuntimeException: Not allowed in %s:%d
Stack trace:
#0 %s(%d): {closure}('After\n', 6)
#1 {main}
#0 %s(%d): {closure}()
#1 %s(%d): FFI->bug79177()
#2 {main}
thrown in %s on line %d

Fatal error: Throwing from FFI callbacks is not allowed in %s on line %d
15 changes: 13 additions & 2 deletions ext/zend_test/php_test.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,18 @@ struct bug79096 {
uint64_t b;
};

ZEND_API struct bug79096 bug79096(void);
ZEND_API void bug79532(off_t *array, size_t elems);
#ifdef PHP_WIN32
# define PHP_ZEND_TEST_API __declspec(dllexport)
#elif defined(__GNUC__) && __GNUC__ >= 4
# define PHP_ZEND_TEST_API __attribute__ ((visibility("default")))
#else
# define PHP_ZEND_TEST_API
#endif

PHP_ZEND_TEST_API struct bug79096 bug79096(void);
PHP_ZEND_TEST_API void bug79532(off_t *array, size_t elems);

extern PHP_ZEND_TEST_API int *(*bug79177_cb)(void);
PHP_ZEND_TEST_API void bug79177(void);

#endif
6 changes: 6 additions & 0 deletions ext/zend_test/test.c
Original file line number Diff line number Diff line change
Expand Up @@ -336,3 +336,9 @@ void bug79532(off_t *array, size_t elems)
array[i] = i;
}
}

PHP_ZEND_TEST_API int *(*bug79177_cb)(void);
void bug79177(void)
{
bug79177_cb();
}

0 comments on commit 0427dcb

Please sign in to comment.