Skip to content

Commit c774ca8

Browse files
committed
Merge branch 'PHP-7.4'
* PHP-7.4: Allow to fetch function address
2 parents 583c7a4 + ecdaf83 commit c774ca8

File tree

2 files changed

+78
-1
lines changed

2 files changed

+78
-1
lines changed

ext/ffi/ffi.c

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2335,7 +2335,7 @@ static zval *zend_ffi_read_var(zend_object *obj, zend_string *var_name, int read
23352335

23362336
if (ffi->symbols) {
23372337
sym = zend_hash_find_ptr(ffi->symbols, var_name);
2338-
if (sym && sym->kind != ZEND_FFI_SYM_VAR && sym->kind != ZEND_FFI_SYM_CONST) {
2338+
if (sym && sym->kind != ZEND_FFI_SYM_VAR && sym->kind != ZEND_FFI_SYM_CONST && sym->kind != ZEND_FFI_SYM_FUNC) {
23392339
sym = NULL;
23402340
}
23412341
}
@@ -2346,6 +2346,24 @@ static zval *zend_ffi_read_var(zend_object *obj, zend_string *var_name, int read
23462346

23472347
if (sym->kind == ZEND_FFI_SYM_VAR) {
23482348
zend_ffi_cdata_to_zval(NULL, sym->addr, ZEND_FFI_TYPE(sym->type), read_type, rv, (zend_ffi_flags)sym->is_const, 0);
2349+
} else if (sym->kind == ZEND_FFI_SYM_FUNC) {
2350+
zend_ffi_cdata *cdata;
2351+
zend_ffi_type *new_type = emalloc(sizeof(zend_ffi_type));
2352+
2353+
new_type->kind = ZEND_FFI_TYPE_POINTER;
2354+
new_type->attr = 0;
2355+
new_type->size = sizeof(void*);
2356+
new_type->align = _Alignof(void*);
2357+
new_type->pointer.type = ZEND_FFI_TYPE(sym->type);
2358+
2359+
cdata = emalloc(sizeof(zend_ffi_cdata));
2360+
zend_ffi_object_init(&cdata->std, zend_ffi_cdata_ce);
2361+
cdata->std.handlers = &zend_ffi_cdata_handlers;
2362+
cdata->type = ZEND_FFI_TYPE_MAKE_OWNED(new_type);
2363+
cdata->flags = ZEND_FFI_FLAG_CONST;
2364+
cdata->ptr_holder = sym->addr;
2365+
cdata->ptr = &cdata->ptr_holder;
2366+
ZVAL_OBJ(rv, &cdata->std);
23492367
} else {
23502368
ZVAL_LONG(rv, sym->value);
23512369
}

ext/ffi/tests/101.phpt

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
--TEST--
2+
FFI 101: PHP symbols (function address)
3+
--SKIPIF--
4+
<?php require_once('skipif.inc'); ?>
5+
<?php
6+
try {
7+
FFI::cdef("extern void *zend_printf;");
8+
} catch (Throwable $e) {
9+
die('skip PHP symbols not available');
10+
}
11+
?>
12+
--INI--
13+
ffi.enable=1
14+
--FILE--
15+
<?php
16+
// Check if target supports "fastcall" calling convention
17+
try {
18+
FFI::cdef("extern size_t __attribute__((fastcall)) (*zend_printf)(const char *format);");
19+
$fastcall = "__attribute__((fastcall)) ";
20+
} catch (Throwable $e) {
21+
$fastcall = "";
22+
}
23+
$zend = FFI::cdef("
24+
const char *get_zend_version(void);
25+
//char *get_zend_version(void);
26+
extern size_t (*zend_printf)(const char *format, ...);
27+
28+
unsigned long $fastcall zend_hash_func(const char *str, size_t len);
29+
30+
void $fastcall zend_str_tolower(char *str, size_t length);
31+
32+
");
33+
$f = $zend->get_zend_version;
34+
var_dump(trim(explode("\n",$f())[0]));
35+
//var_dump(trim(FFI::string($zend->get_zend_version())));
36+
var_dump($zend->zend_printf);
37+
var_dump(($zend->zend_printf)("Hello %s!\n", "World"));
38+
39+
$f = $zend->zend_hash_func;
40+
var_dump($f("file", strlen("file")));
41+
42+
$str = $zend->new("char[16]");
43+
FFI::memcpy($str, "Hello World!", strlen("Hello World!"));
44+
$f = $zend->zend_str_tolower;
45+
$f($str, strlen("Hello World!"));
46+
var_dump(FFI::string($str));
47+
48+
?>
49+
--EXPECTF--
50+
string(%d) "Zend Engine %s"
51+
object(FFI\CData:uint%d_t(*)())#%d (1) {
52+
[0]=>
53+
object(FFI\CData:uint%d_t())#%d (0) {
54+
}
55+
}
56+
Hello World!
57+
int(13)
58+
int(%i)
59+
string(12) "hello world!"

0 commit comments

Comments
 (0)