diff --git a/ext/ffi/ffi.c b/ext/ffi/ffi.c index 30f7fd9f6b197..bc101789b1146 100644 --- a/ext/ffi/ffi.c +++ b/ext/ffi/ffi.c @@ -4215,6 +4215,11 @@ ZEND_METHOD(FFI, addr) /* {{{ */ cdata = (zend_ffi_cdata*)Z_OBJ_P(zv); type = ZEND_FFI_TYPE(cdata->type); + if (GC_REFCOUNT(&cdata->std) == 1 && Z_REFCOUNT_P(arg) == 1 && type->kind == ZEND_FFI_TYPE_POINTER) { + zend_throw_error(zend_ffi_exception_ce, "Cannot reference temporary pointer"); + RETURN_THROWS(); + } + new_type = emalloc(sizeof(zend_ffi_type)); new_type->kind = ZEND_FFI_TYPE_POINTER; new_type->attr = 0; diff --git a/ext/ffi/tests/addr_to_owned.phpt b/ext/ffi/tests/addr_to_owned.phpt new file mode 100644 index 0000000000000..ab79107d6cfd6 --- /dev/null +++ b/ext/ffi/tests/addr_to_owned.phpt @@ -0,0 +1,24 @@ +--TEST-- +FFI Referencing temporary owned data transfers ownership +--EXTENSIONS-- +ffi +--INI-- +ffi.enable=1 +--FILE-- +new('Foo')); +var_dump($structPtr); +?> +--EXPECT-- +object(FFI\CData:struct *)#3 (1) { + [0]=> + object(FFI\CData:struct )#2 (1) { + ["bar"]=> + int(0) + } +} diff --git a/ext/ffi/tests/nested_addr.phpt b/ext/ffi/tests/nested_addr.phpt new file mode 100644 index 0000000000000..fa79fd70e83ff --- /dev/null +++ b/ext/ffi/tests/nested_addr.phpt @@ -0,0 +1,23 @@ +--TEST-- +FFI Cannot nest FFI::addr() calls +--EXTENSIONS-- +ffi +--INI-- +ffi.enable=1 +--FILE-- +new('Foo'); +$structPtrPtr = \FFI::addr(\FFI::addr($struct)); +?> +--EXPECTF-- +Fatal error: Uncaught FFI\Exception: Cannot reference temporary pointer in %s:%d +Stack trace: +#0 %s(%d): FFI::addr(Object(FFI\CData:struct *)) +#1 {main} + thrown in %s on line %d