-
Notifications
You must be signed in to change notification settings - Fork 7.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Fix GH-7867: FFI::cast() from pointer to array is broken
Casting from pointer to array is special, so we must not fall back to the general FFI casting. There is a particular issue regarding the size comparison, namely that the pointer size is always 8 for 64bit architectures, but the size of an array is determined by its declaration, so as is casting a pointer to an array with more than 8 elements would fail, but casting to an array with less than 9 elements succeeds, but the internal pointer would point to some arbitrary memory. We fix this by properly supporting the cast. An alternative would be to deny this kind of cast generally, since it is not necessarily safe. However, FFI isn't necessarily safe anyway. We also check pointer/array type compatibility when casting. Co-authored-by: Dmitry Stogov <dmitry@zend.com> Closes GH-7876.
- Loading branch information
Showing
3 changed files
with
87 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -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" | ||
} |