ffi_type **arg_types = NULL;
void **arg_values = NULL;
uint32_t n, arg_count;
- ffi_arg ret;
+ void *ret;
zend_ffi_type *arg_type;
ALLOCA_FLAG(arg_types_use_heap = 0)
ALLOCA_FLAG(arg_values_use_heap = 0)
+ ALLOCA_FLAG(ret_use_heap = 0)
ZEND_ASSERT(type->kind == ZEND_FFI_TYPE_FUNC);
arg_count = type->func.args ? zend_hash_num_elements(type->func.args) : 0;
}
}
- ffi_call(&cif, addr, &ret, arg_values);
+ ret = do_alloca(MAX(ret_type->size, sizeof(ffi_arg)), ret_use_heap);
+ ffi_call(&cif, addr, ret, arg_values);
for (n = 0; n < arg_count; n++) {
if (arg_types[n]->type == FFI_TYPE_STRUCT) {
free_alloca(arg_values, arg_values_use_heap);
}
- zend_ffi_cdata_to_zval(NULL, (void*)&ret, ZEND_FFI_TYPE(type->func.ret_type), BP_VAR_R, return_value, 0, 1);
+ zend_ffi_cdata_to_zval(NULL, ret, ZEND_FFI_TYPE(type->func.ret_type), BP_VAR_R, return_value, 0, 1);
+ free_alloca(ret, ret_use_heap);
exit:
zend_string_release(EX(func)->common.function_name);
--- /dev/null
+--TEST--
+Bug #79096 (FFI Struct Segfault)
+--SKIPIF--
+<?php
+if (!extension_loaded('ffi')) die('skip ffi extension not available');
+if (!extension_loaded('zend-test')) die('skip zend-test extension not available');
+?>
+--FILE--
+<?php
+$header = <<<HEADER
+struct bug79096 {
+ uint64_t a;
+ uint64_t b;
+};
+
+struct bug79096 bug79096(void);
+HEADER;
+
+if (PHP_OS_FAMILY !== 'Windows') {
+ $ffi = FFI::cdef($header);
+} else {
+ try {
+ $ffi = FFI::cdef($header, 'php_zend_test.dll');
+ } catch (FFI\Exception $ex) {
+ $dll = $dll = 'php7' . (PHP_ZTS ? 'ts' : '') . (PHP_DEBUG ? '_debug' : '') . '.dll';
+ $ffi = FFI::cdef($header, $dll);
+ }
+}
+
+$struct = $ffi->bug79096();
+var_dump($struct);
+?>
+--EXPECTF--
+object(FFI\CData:struct bug79096)#%d (2) {
+ ["a"]=>
+ int(1)
+ ["b"]=>
+ int(1)
+}