Merge branch 'PHP-8.1'

* PHP-8.1:
  Fix GH-7867: FFI::cast() from pointer to array is broken
This commit is contained in:
Christoph M. Becker 2022-01-11 00:00:31 +01:00
commit ede1568967
No known key found for this signature in database
GPG Key ID: D66C9593118BCCB6
2 changed files with 83 additions and 3 deletions

View File

@ -3901,9 +3901,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");

75
ext/ffi/tests/gh7867.phpt Normal file
View File

@ -0,0 +1,75 @@
--TEST--
GH-7867 (FFI::cast() from pointer to array is broken)
--SKIPIF--
<?php
if (!extension_loaded("ffi")) die("skip ffi extension not available");
?>
--FILE--
<?php
$value = FFI::new('char[26]');
FFI::memcpy($value, implode('', range('a', 'z')), 26);
$slice = FFI::new('char[4]');
echo 'cast from start' . PHP_EOL;
FFI::memcpy($slice, $value, 4);
var_dump($value + 0, $slice, FFI::cast('char[4]', $value));
echo PHP_EOL;
echo 'cast with offset' . PHP_EOL;
FFI::memcpy($slice, $value + 4, 4);
var_dump($value + 4, $slice, FFI::cast('char[4]', $value + 4));
echo PHP_EOL;
?>
--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"
}