Skip to content

Commit

Permalink
Fixed bug #77632 (FFI Segfaults When Called With Variadics)
Browse files Browse the repository at this point in the history
  • Loading branch information
dstogov committed Feb 18, 2019
1 parent 2ed013c commit 5661feb
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 15 deletions.
23 changes: 8 additions & 15 deletions ext/ffi/ffi.c
Expand Up @@ -1776,14 +1776,12 @@ static int zend_ffi_cdata_get_closure(zval *obj, zend_class_entry **ce_ptr, zend
func->common.arg_flags[2] = 0;
func->common.fn_flags = ZEND_ACC_CALL_VIA_TRAMPOLINE;
func->common.function_name = ZSTR_KNOWN(ZEND_STR_MAGIC_INVOKE);
func->common.num_args = func->common.required_num_args = type->func.args ? zend_hash_num_elements(type->func.args) : 0;
/* set to 0 to avoid arg_info[] allocation, because all values are passed by value anyway */
func->common.num_args = 0;
func->common.required_num_args = type->func.args ? zend_hash_num_elements(type->func.args) : 0;
func->common.arg_info = NULL;
func->internal_function.handler = ZEND_FN(ffi_trampoline);

if (func->common.num_args > MAX_ARG_FLAG_NUM) {
func->common.arg_info = emalloc(sizeof(zend_arg_info) * func->common.num_args);
memset(func->common.arg_info, 0, sizeof(zend_arg_info) * func->common.num_args);
}

func->internal_function.reserved[0] = type;
func->internal_function.reserved[1] = *(void**)cdata->ptr;

Expand Down Expand Up @@ -2447,9 +2445,6 @@ static ZEND_FUNCTION(ffi_trampoline) /* {{{ */

zend_string_release(EX(func)->common.function_name);
if (EX(func)->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) {
if (EX(func)->common.arg_info) {
efree(EX(func)->common.arg_info);
}
zend_free_trampoline(EX(func));
EX(func) = NULL;
}
Expand Down Expand Up @@ -2507,14 +2502,12 @@ static zend_function *zend_ffi_get_func(zend_object **obj, zend_string *name, co
func->common.arg_flags[2] = 0;
func->common.fn_flags = ZEND_ACC_CALL_VIA_TRAMPOLINE;
func->common.function_name = zend_string_copy(name);
func->common.num_args = func->common.required_num_args = type->func.args ? zend_hash_num_elements(type->func.args) : 0;
/* set to 0 to avoid arg_info[] allocation, because all values are passed by value anyway */
func->common.num_args = 0;
func->common.required_num_args = type->func.args ? zend_hash_num_elements(type->func.args) : 0;
func->common.arg_info = NULL;
func->internal_function.handler = ZEND_FN(ffi_trampoline);

if (func->common.num_args > MAX_ARG_FLAG_NUM) {
func->common.arg_info = emalloc(sizeof(zend_arg_info) * func->common.num_args);
memset(func->common.arg_info, 0, sizeof(zend_arg_info) * func->common.num_args);
}

func->internal_function.reserved[0] = type;
func->internal_function.reserved[1] = sym->addr;

Expand Down
14 changes: 14 additions & 0 deletions ext/ffi/tests/bug77632.phpt
@@ -0,0 +1,14 @@
--TEST--
Bug #77632 (FFI Segfaults When Called With Variadics)
--SKIPIF--
<?php require_once('skipif.inc'); ?>
--INI--
ffi.enable=1
--FILE--
<?php
$libc = FFI::cdef("int printf(const char *format, ...);", "libc.so.6");
$args = ["test\n"];
$libc->printf(...$args);
?>
--EXPECT--
test

0 comments on commit 5661feb

Please sign in to comment.