diff --git a/ext/ffi/ffi.c b/ext/ffi/ffi.c index e3da06698f659..8f4a25b0d6227 100644 --- a/ext/ffi/ffi.c +++ b/ext/ffi/ffi.c @@ -3904,9 +3904,14 @@ ZEND_METHOD(FFI, cast) /* {{{ */ /* automatically dereference void* pointers ??? */ cdata->ptr = *(void**)ptr; } else if (old_type->kind == ZEND_FFI_TYPE_ARRAY - && type->kind == ZEND_FFI_TYPE_POINTER) { - cdata->ptr = &cdata->ptr_holder; - cdata->ptr_holder = old_cdata->ptr; + && type->kind == ZEND_FFI_TYPE_POINTER + && zend_ffi_is_compatible_type(ZEND_FFI_TYPE(old_type->array.type), ZEND_FFI_TYPE(type->pointer.type))) { cdata->ptr = &cdata->ptr_holder; + cdata->ptr = &cdata->ptr_holder; + cdata->ptr_holder = old_cdata->ptr; + } else if (old_type->kind == ZEND_FFI_TYPE_POINTER + && type->kind == ZEND_FFI_TYPE_ARRAY + && zend_ffi_is_compatible_type(ZEND_FFI_TYPE(old_type->pointer.type), ZEND_FFI_TYPE(type->array.type))) { + cdata->ptr = old_cdata->ptr_holder; } else if (type->size > old_type->size) { zend_object_release(&cdata->std); zend_throw_error(zend_ffi_exception_ce, "attempt to cast to larger type"); diff --git a/ext/ffi/tests/gh7867.phpt b/ext/ffi/tests/gh7867.phpt new file mode 100644 index 0000000000000..7728d15b1c616 --- /dev/null +++ b/ext/ffi/tests/gh7867.phpt @@ -0,0 +1,75 @@ +--TEST-- +GH-7867 (FFI::cast() from pointer to array is broken) +--SKIPIF-- + +--FILE-- + +--EXPECTF-- +cast from start +object(FFI\CData:char*)#%d (1) { + [0]=> + string(1) "a" +} +object(FFI\CData:char[4])#%d (4) { + [0]=> + string(1) "a" + [1]=> + string(1) "b" + [2]=> + string(1) "c" + [3]=> + string(1) "d" +} +object(FFI\CData:char[4])#%d (4) { + [0]=> + string(1) "a" + [1]=> + string(1) "b" + [2]=> + string(1) "c" + [3]=> + string(1) "d" +} + +cast with offset +object(FFI\CData:char*)#%d (1) { + [0]=> + string(1) "e" +} +object(FFI\CData:char[4])#%d (4) { + [0]=> + string(1) "e" + [1]=> + string(1) "f" + [2]=> + string(1) "g" + [3]=> + string(1) "h" +} +object(FFI\CData:char[4])#%d (4) { + [0]=> + string(1) "e" + [1]=> + string(1) "f" + [2]=> + string(1) "g" + [3]=> + string(1) "h" +}