This commit is contained in:
Dmitry Stogov 2023-11-22 21:25:15 +03:00
parent 6f355c6c79
commit adaf726373
2 changed files with 33 additions and 1 deletions

View file

@ -4290,7 +4290,8 @@ ZEND_METHOD(FFI, addr) /* {{{ */
cdata = (zend_ffi_cdata*)Z_OBJ_P(zv); cdata = (zend_ffi_cdata*)Z_OBJ_P(zv);
type = ZEND_FFI_TYPE(cdata->type); type = ZEND_FFI_TYPE(cdata->type);
if (GC_REFCOUNT(&cdata->std) == 1 && Z_REFCOUNT_P(arg) == 1 && type->kind == ZEND_FFI_TYPE_POINTER) { if (GC_REFCOUNT(&cdata->std) == 1 && Z_REFCOUNT_P(arg) == 1 && type->kind == ZEND_FFI_TYPE_POINTER
&& cdata->ptr == &cdata->ptr_holder) {
zend_throw_error(zend_ffi_exception_ce, "FFI::addr() cannot create a reference to a temporary pointer"); zend_throw_error(zend_ffi_exception_ce, "FFI::addr() cannot create a reference to a temporary pointer");
RETURN_THROWS(); RETURN_THROWS();
} }

View file

@ -0,0 +1,31 @@
--TEST--
Assignment to CDATA though FFI::addr() trick
--EXTENSIONS--
ffi
--INI--
ffi.enable=1
--FILE--
<?php
$f = FFI::cdef("typedef struct { char *bar; } other;");
class Container {
public $data;
function __construct($f) { $this->data = $f->new("other"); }
function &getBar() { return $this->data->bar; } // return by ref to get CData instead of null
}
$container = new Container($f);
$data = $f->new("char[2]");
$data[0] = "1";
FFI::addr($container->getBar())[0] = $f->cast("char*", $data); // directly write it
var_dump($container);
?>
--EXPECT--
object(Container)#2 (1) {
["data"]=>
object(FFI\CData:struct <anonymous>)#3 (1) {
["bar"]=>
object(FFI\CData:char*)#6 (1) {
[0]=>
string(1) "1"
}
}
}