Skip to content

Commit 5661feb

Browse files
committed
Fixed bug #77632 (FFI Segfaults When Called With Variadics)
1 parent 2ed013c commit 5661feb

File tree

2 files changed

+22
-15
lines changed

2 files changed

+22
-15
lines changed

ext/ffi/ffi.c

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1776,14 +1776,12 @@ static int zend_ffi_cdata_get_closure(zval *obj, zend_class_entry **ce_ptr, zend
17761776
func->common.arg_flags[2] = 0;
17771777
func->common.fn_flags = ZEND_ACC_CALL_VIA_TRAMPOLINE;
17781778
func->common.function_name = ZSTR_KNOWN(ZEND_STR_MAGIC_INVOKE);
1779-
func->common.num_args = func->common.required_num_args = type->func.args ? zend_hash_num_elements(type->func.args) : 0;
1779+
/* set to 0 to avoid arg_info[] allocation, because all values are passed by value anyway */
1780+
func->common.num_args = 0;
1781+
func->common.required_num_args = type->func.args ? zend_hash_num_elements(type->func.args) : 0;
1782+
func->common.arg_info = NULL;
17801783
func->internal_function.handler = ZEND_FN(ffi_trampoline);
17811784

1782-
if (func->common.num_args > MAX_ARG_FLAG_NUM) {
1783-
func->common.arg_info = emalloc(sizeof(zend_arg_info) * func->common.num_args);
1784-
memset(func->common.arg_info, 0, sizeof(zend_arg_info) * func->common.num_args);
1785-
}
1786-
17871785
func->internal_function.reserved[0] = type;
17881786
func->internal_function.reserved[1] = *(void**)cdata->ptr;
17891787

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

24482446
zend_string_release(EX(func)->common.function_name);
24492447
if (EX(func)->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) {
2450-
if (EX(func)->common.arg_info) {
2451-
efree(EX(func)->common.arg_info);
2452-
}
24532448
zend_free_trampoline(EX(func));
24542449
EX(func) = NULL;
24552450
}
@@ -2507,14 +2502,12 @@ static zend_function *zend_ffi_get_func(zend_object **obj, zend_string *name, co
25072502
func->common.arg_flags[2] = 0;
25082503
func->common.fn_flags = ZEND_ACC_CALL_VIA_TRAMPOLINE;
25092504
func->common.function_name = zend_string_copy(name);
2510-
func->common.num_args = func->common.required_num_args = type->func.args ? zend_hash_num_elements(type->func.args) : 0;
2505+
/* set to 0 to avoid arg_info[] allocation, because all values are passed by value anyway */
2506+
func->common.num_args = 0;
2507+
func->common.required_num_args = type->func.args ? zend_hash_num_elements(type->func.args) : 0;
2508+
func->common.arg_info = NULL;
25112509
func->internal_function.handler = ZEND_FN(ffi_trampoline);
25122510

2513-
if (func->common.num_args > MAX_ARG_FLAG_NUM) {
2514-
func->common.arg_info = emalloc(sizeof(zend_arg_info) * func->common.num_args);
2515-
memset(func->common.arg_info, 0, sizeof(zend_arg_info) * func->common.num_args);
2516-
}
2517-
25182511
func->internal_function.reserved[0] = type;
25192512
func->internal_function.reserved[1] = sym->addr;
25202513

ext/ffi/tests/bug77632.phpt

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
--TEST--
2+
Bug #77632 (FFI Segfaults When Called With Variadics)
3+
--SKIPIF--
4+
<?php require_once('skipif.inc'); ?>
5+
--INI--
6+
ffi.enable=1
7+
--FILE--
8+
<?php
9+
$libc = FFI::cdef("int printf(const char *format, ...);", "libc.so.6");
10+
$args = ["test\n"];
11+
$libc->printf(...$args);
12+
?>
13+
--EXPECT--
14+
test

0 commit comments

Comments
 (0)