From e902e4acd94b46a85efbc8b88e0808bb318b8ac2 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Wed, 11 Mar 2020 15:13:27 +0300 Subject: [PATCH] Allow to fetch function address --- ext/ffi/ffi.c | 20 +++++++++++++- ext/ffi/tests/101.phpt | 59 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 78 insertions(+), 1 deletion(-) create mode 100644 ext/ffi/tests/101.phpt diff --git a/ext/ffi/ffi.c b/ext/ffi/ffi.c index d99448dd69..b0bcd584fd 100644 --- a/ext/ffi/ffi.c +++ b/ext/ffi/ffi.c @@ -2354,7 +2354,7 @@ static zval *zend_ffi_read_var(zval *object, zval *member, int read_type, void * if (ffi->symbols) { sym = zend_hash_find_ptr(ffi->symbols, var_name); - if (sym && sym->kind != ZEND_FFI_SYM_VAR && sym->kind != ZEND_FFI_SYM_CONST) { + if (sym && sym->kind != ZEND_FFI_SYM_VAR && sym->kind != ZEND_FFI_SYM_CONST && sym->kind != ZEND_FFI_SYM_FUNC) { sym = NULL; } } @@ -2368,6 +2368,24 @@ static zval *zend_ffi_read_var(zval *object, zval *member, int read_type, void * if (sym->kind == ZEND_FFI_SYM_VAR) { zend_ffi_cdata_to_zval(NULL, sym->addr, ZEND_FFI_TYPE(sym->type), read_type, rv, (zend_ffi_flags)sym->is_const, 0); + } else if (sym->kind == ZEND_FFI_SYM_FUNC) { + zend_ffi_cdata *cdata; + zend_ffi_type *new_type = emalloc(sizeof(zend_ffi_type)); + + new_type->kind = ZEND_FFI_TYPE_POINTER; + new_type->attr = 0; + new_type->size = sizeof(void*); + new_type->align = _Alignof(void*); + new_type->pointer.type = ZEND_FFI_TYPE(sym->type); + + cdata = emalloc(sizeof(zend_ffi_cdata)); + zend_ffi_object_init(&cdata->std, zend_ffi_cdata_ce); + cdata->std.handlers = &zend_ffi_cdata_handlers; + cdata->type = ZEND_FFI_TYPE_MAKE_OWNED(new_type); + cdata->flags = ZEND_FFI_FLAG_CONST; + cdata->ptr_holder = sym->addr; + cdata->ptr = &cdata->ptr_holder; + ZVAL_OBJ(rv, &cdata->std); } else { ZVAL_LONG(rv, sym->value); } diff --git a/ext/ffi/tests/101.phpt b/ext/ffi/tests/101.phpt new file mode 100644 index 0000000000..91c6fc4ddf --- /dev/null +++ b/ext/ffi/tests/101.phpt @@ -0,0 +1,59 @@ +--TEST-- +FFI 101: PHP symbols (function address) +--SKIPIF-- + + +--INI-- +ffi.enable=1 +--FILE-- +get_zend_version; +var_dump(trim(explode("\n",$f())[0])); +//var_dump(trim(FFI::string($zend->get_zend_version()))); +var_dump($zend->zend_printf); +var_dump(($zend->zend_printf)("Hello %s!\n", "World")); + +$f = $zend->zend_hash_func; +var_dump($f("file", strlen("file"))); + +$str = $zend->new("char[16]"); +FFI::memcpy($str, "Hello World!", strlen("Hello World!")); +$f = $zend->zend_str_tolower; +$f($str, strlen("Hello World!")); +var_dump(FFI::string($str)); + +?> +--EXPECTF-- +string(%d) "Zend Engine %s" +object(FFI\CData:uint%d_t(*)())#%d (1) { + [0]=> + object(FFI\CData:uint%d_t())#%d (0) { + } +} +Hello World! +int(13) +int(%i) +string(12) "hello world!" -- 2.40.0