diff options
author | Dmitry Stogov <dmitry@zend.com> | 2020-03-12 11:41:12 +0300 |
---|---|---|
committer | Dmitry Stogov <dmitry@zend.com> | 2020-03-12 11:41:12 +0300 |
commit | c774ca8d807320cf3ef95edb4594a7f71e10e917 (patch) | |
tree | 3b5fd3c2c0387199bd3576ec756bfe07f1f47870 | |
parent | 583c7a4cbbbabbf6afadac74d81f3ccfb96e4321 (diff) | |
parent | ecdaf83f5f0888332c76eca7fb644c536b70e817 (diff) | |
download | php-git-c774ca8d807320cf3ef95edb4594a7f71e10e917.tar.gz |
Merge branch 'PHP-7.4'
* PHP-7.4:
Allow to fetch function address
-rw-r--r-- | ext/ffi/ffi.c | 20 | ||||
-rw-r--r-- | ext/ffi/tests/101.phpt | 59 |
2 files changed, 78 insertions, 1 deletions
diff --git a/ext/ffi/ffi.c b/ext/ffi/ffi.c index 6014a4660c..9b26406486 100644 --- a/ext/ffi/ffi.c +++ b/ext/ffi/ffi.c @@ -2335,7 +2335,7 @@ static zval *zend_ffi_read_var(zend_object *obj, zend_string *var_name, int read 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; } } @@ -2346,6 +2346,24 @@ static zval *zend_ffi_read_var(zend_object *obj, zend_string *var_name, int read 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-- +<?php require_once('skipif.inc'); ?> +<?php +try { + FFI::cdef("extern void *zend_printf;"); +} catch (Throwable $e) { + die('skip PHP symbols not available'); +} +?> +--INI-- +ffi.enable=1 +--FILE-- +<?php +// Check if target supports "fastcall" calling convention +try { + FFI::cdef("extern size_t __attribute__((fastcall)) (*zend_printf)(const char *format);"); + $fastcall = "__attribute__((fastcall)) "; +} catch (Throwable $e) { + $fastcall = ""; +} +$zend = FFI::cdef(" + const char *get_zend_version(void); + //char *get_zend_version(void); + extern size_t (*zend_printf)(const char *format, ...); + + unsigned long $fastcall zend_hash_func(const char *str, size_t len); + + void $fastcall zend_str_tolower(char *str, size_t length); + +"); +$f = $zend->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!" |