diff --git a/ext/ffi/ffi.c b/ext/ffi/ffi.c index 76e67d06adf..ac1aabc4f66 100644 --- a/ext/ffi/ffi.c +++ b/ext/ffi/ffi.c @@ -1215,20 +1215,10 @@ static zval *zend_ffi_cdata_read_field(zend_object *obj, zend_string *field_name if (cache_slot && *cache_slot == type) { field = *(cache_slot + 1); } else { + if (type->kind == ZEND_FFI_TYPE_POINTER) { + type = ZEND_FFI_TYPE(type->pointer.type); + } if (UNEXPECTED(type->kind != ZEND_FFI_TYPE_STRUCT)) { - if (type->kind == ZEND_FFI_TYPE_POINTER) { - /* transparently dereference the pointer */ - if (UNEXPECTED(!ptr)) { - zend_throw_error(zend_ffi_exception_ce, "NULL pointer dereference"); - return &EG(uninitialized_zval); - } - ptr = (void*)(*(char**)ptr); - if (UNEXPECTED(!ptr)) { - zend_throw_error(zend_ffi_exception_ce, "NULL pointer dereference"); - return &EG(uninitialized_zval); - } - type = ZEND_FFI_TYPE(type->pointer.type); - } if (UNEXPECTED(type->kind != ZEND_FFI_TYPE_STRUCT)) { zend_throw_error(zend_ffi_exception_ce, "Attempt to read field '%s' of non C struct/union", ZSTR_VAL(field_name)); return &EG(uninitialized_zval); @@ -1247,6 +1237,20 @@ static zval *zend_ffi_cdata_read_field(zend_object *obj, zend_string *field_name } } + if (ZEND_FFI_TYPE(cdata->type)->kind == ZEND_FFI_TYPE_POINTER) { + /* transparently dereference the pointer */ + if (UNEXPECTED(!ptr)) { + zend_throw_error(zend_ffi_exception_ce, "NULL pointer dereference"); + return &EG(uninitialized_zval); + } + ptr = (void*)(*(char**)ptr); + if (UNEXPECTED(!ptr)) { + zend_throw_error(zend_ffi_exception_ce, "NULL pointer dereference"); + return &EG(uninitialized_zval); + } + type = ZEND_FFI_TYPE(type->pointer.type); + } + #if 0 if (UNEXPECTED(!ptr)) { zend_throw_error(zend_ffi_exception_ce, "NULL pointer dereference"); @@ -1284,20 +1288,10 @@ static zval *zend_ffi_cdata_write_field(zend_object *obj, zend_string *field_nam if (cache_slot && *cache_slot == type) { field = *(cache_slot + 1); } else { + if (type->kind == ZEND_FFI_TYPE_POINTER) { + type = ZEND_FFI_TYPE(type->pointer.type); + } if (UNEXPECTED(type->kind != ZEND_FFI_TYPE_STRUCT)) { - if (type->kind == ZEND_FFI_TYPE_POINTER) { - /* transparently dereference the pointer */ - if (UNEXPECTED(!ptr)) { - zend_throw_error(zend_ffi_exception_ce, "NULL pointer dereference"); - return value; - } - ptr = (void*)(*(char**)ptr); - if (UNEXPECTED(!ptr)) { - zend_throw_error(zend_ffi_exception_ce, "NULL pointer dereference"); - return value; - } - type = ZEND_FFI_TYPE(type->pointer.type); - } if (UNEXPECTED(type->kind != ZEND_FFI_TYPE_STRUCT)) { zend_throw_error(zend_ffi_exception_ce, "Attempt to assign field '%s' of non C struct/union", ZSTR_VAL(field_name)); return value; @@ -1316,6 +1310,19 @@ static zval *zend_ffi_cdata_write_field(zend_object *obj, zend_string *field_nam } } + if (ZEND_FFI_TYPE(cdata->type)->kind == ZEND_FFI_TYPE_POINTER) { + /* transparently dereference the pointer */ + if (UNEXPECTED(!ptr)) { + zend_throw_error(zend_ffi_exception_ce, "NULL pointer dereference"); + return value; + } + ptr = (void*)(*(char**)ptr); + if (UNEXPECTED(!ptr)) { + zend_throw_error(zend_ffi_exception_ce, "NULL pointer dereference"); + return value; + } + } + #if 0 if (UNEXPECTED(!ptr)) { zend_throw_error(zend_ffi_exception_ce, "NULL pointer dereference"); diff --git a/ext/ffi/tests/047.phpt b/ext/ffi/tests/047.phpt new file mode 100644 index 00000000000..8bd83320b50 --- /dev/null +++ b/ext/ffi/tests/047.phpt @@ -0,0 +1,38 @@ +--TEST-- +FFI 047: FFI::CData->cdata meaning +--EXTENSIONS-- +ffi +--INI-- +ffi.enable=1 +--FILE-- +cdata = 42; +var_dump($x); + +$x = FFI::new("int*"); +try { + $x->cdata = 42; + var_dump($x); +} catch (Throwable $e) { + echo $e->getMessage() . "\n"; +} + +$x = FFI::new("struct {int cdata;}"); +try { + $x->cdata = 42; + var_dump($x); +} catch (Throwable $e) { + echo $e->getMessage() . "\n"; +} +?> +--EXPECTF-- +object(FFI\CData:int32_t)#%d (1) { + ["cdata"]=> + int(42) +} +Attempt to assign field 'cdata' of non C struct/union +object(FFI\CData:struct )#%d (1) { + ["cdata"]=> + int(42) +}