Description
Description
The following code:
<?php
$ffi = FFI::cdef('
typedef long unsigned int size_t;
void *malloc(size_t size);
');
$ptr = $ffi->cast('uint8_t *', $ffi->malloc(8));
print "A: "; var_dump($ptr);
print "B: "; var_dump($ptr + 1);
print "C: "; var_dump($ptr);
print "D: "; var_dump($ptr + 1);
Resulted in this output:
A: object(FFI\CData:uint8_t*)#4 (1) {
[0]=>
int(0)
}
B: object(FFI\CData:uint8_t*)#5 (1) {
[0]=>
int(0)
}
C: Segmentation fault
But I expected this output instead:
Not sure what would be canonically correct
I get the following backtrace:
#0 0x00007ffff43a7915 in ?? () from /usr/lib/php/20210902/ffi.so
#1 0x00005555558be86d in zend_std_get_properties_for (obj=<optimized out>, purpose=<optimized out>) at ./Zend/zend_object_handlers.c:1880
#2 0x00005555557a77e1 in php_var_dump (struc=0x7ffff5413530, level=1) at ./ext/standard/var.c:163
#3 0x00005555557a7ce1 in zif_var_dump (execute_data=<optimized out>, return_value=<optimized out>) at ./ext/standard/var.c:228
#4 0x000055555589797b in ZEND_DO_ICALL_SPEC_RETVAL_UNUSED_HANDLER () at ./Zend/zend_vm_execute.h:1235
#5 execute_ex (ex=0x7ffff5455e40) at ./Zend/zend_vm_execute.h:55752
#6 0x000055555589eced in zend_execute (op_array=0x7ffff548c000, return_value=0x0) at ./Zend/zend_vm_execute.h:60123
#7 0x00005555558311cd in zend_execute_scripts (type=type@entry=8, retval=retval@entry=0x0, file_count=file_count@entry=3) at ./Zend/zend.c:1790
#8 0x00005555557ccc71 in php_execute_script (primary_file=primary_file@entry=0x7fffffffd760) at ./main/main.c:2538
#9 0x0000555555915673 in do_cli (argc=2, argv=0x555555ac5390) at ./sapi/cli/php_cli.c:969
#10 0x0000555555677f11 in main (argc=2, argv=0x555555ac5390) at ./sapi/cli/php_cli.c:1371
Here's line 1880:
https://github.com/php/php-src/blob/PHP-8.1.7/Zend/zend_object_handlers.c#L1880
Additionally,
This code (which swaps var_dump()
for var_export()
, to take the alternate path through zend_std_get_properties_for()
):
<?php
$ffi = FFI::cdef('
typedef long unsigned int size_t;
void *malloc(size_t size);
');
$ptr = $ffi->cast('uint8_t *', $ffi->malloc(8));
print "A: "; var_export($ptr);
print "\nB: "; var_export($ptr + 1);
print "\nC: "; var_export($ptr);
print "\nD: "; var_export($ptr + 1);
Results in this output:
A: FFI\CData::__set_state(array(
))
B: FFI\CData::__set_state(array(
))
C: FFI\CData::__set_state(array(
))
D: PHP Fatal error: Uncaught TypeError: Unsupported operand types: FFI\CData + int
But I expected this output instead:
Not sure what would be canonically correct
hOwEvEr,
ThIs code:
<?php
$ffi = FFI::cdef('
typedef long unsigned int size_t;
void *malloc(size_t size);
');
$ptr = $ffi->cast('uint8_t *', $ffi->malloc(27));
// Fill memory with "A..Z" for presentational purposes
for ($i = 0; $i < 26; $i++) {
$ptr[$i] = $i + 65; // 'A'
}
var_dump(FFI::string($ptr, 16));
var_dump(FFI::string($ptr + 5, 16));
var_dump(FFI::string($ptr + 5, 16));
Produces this output!!
string(16) "ABCDEFGHIJKLMNOP"
string(16) "FGHIJKLMNOPQRSTU"
PHP Fatal error: Uncaught TypeError: Unsupported operand types: FFI\CData + int
Commentary:
I'm currently using the FFI to mmap()
some data into memory (for both read and write). Reading and writing integer values (typecasted to uint16_t/uint32_t) is working perfectly fine (thanks for plumbing everything out so this is as simple as assigning to a PHP array :D), but now I needed to read and write sequences of characters (binary data I want written to specific offsets).
Naturally that's done in C by just assigning to ptr + offset
(where ptr might be uint8_t *
and offset is int
), so I wondered if the same worked here. It... *does*, I think...? Except it crashes. This is why I said I don't know what the canonically-correct outcome here is: this is currently Schrodinger's architecture, where I'm equally observing "yes that's the right way to do it" and *crash* and I don't know where to put the consensus :)
I was reading the values I wanted to mmap()
using (PHP-side) fread()
so I'll either just stick with that or play with FFI::memcpy() for now. Thanks again for FFI, it's really awesome.
PHP Version
PHP 8.1.7 from sury.org
Operating System
Debian 11.3