summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Stogov <dmitry@zend.com>2019-09-10 11:34:08 +0300
committerDmitry Stogov <dmitry@zend.com>2019-09-10 11:34:08 +0300
commit0128f6eb8466cacfac5141382490bc385c9db8c0 (patch)
treed4c3b4f77a1337aacf30358312cb2cc45cdb7c72
parent989959fb164906044aef5c8fdbc222a5e25d52dc (diff)
parent21c3cdf66824a0522779fa252a675173d02dc724 (diff)
downloadphp-git-0128f6eb8466cacfac5141382490bc385c9db8c0.tar.gz
Merge branch 'PHP-7.4'
* PHP-7.4: NEWS entry, test and minor cleanup for FFI::isNull() add FFI::isNull() to check whether a FFI\CData is a null pointer
-rw-r--r--ext/ffi/ffi.c30
-rw-r--r--ext/ffi/ffi.stub.php5
-rw-r--r--ext/ffi/ffi_arginfo.h2
-rw-r--r--ext/ffi/tests/045.phpt27
4 files changed, 64 insertions, 0 deletions
diff --git a/ext/ffi/ffi.c b/ext/ffi/ffi.c
index 765b63181e..aae8b3ab21 100644
--- a/ext/ffi/ffi.c
+++ b/ext/ffi/ffi.c
@@ -4329,6 +4329,35 @@ ZEND_METHOD(FFI, string) /* {{{ */
}
/* }}} */
+ZEND_METHOD(FFI, isNull) /* {{{ */
+{
+ zval *zv;
+ zend_ffi_cdata *cdata;
+ zend_ffi_type *type;
+
+ ZEND_FFI_VALIDATE_API_RESTRICTION();
+ ZEND_PARSE_PARAMETERS_START(1, 1)
+ Z_PARAM_ZVAL(zv);
+ ZEND_PARSE_PARAMETERS_END();
+
+ ZVAL_DEREF(zv);
+ if (Z_TYPE_P(zv) != IS_OBJECT || Z_OBJCE_P(zv) != zend_ffi_cdata_ce) {
+ zend_wrong_parameter_class_error(1, "FFI\\CData", zv);
+ return;
+ }
+
+ cdata = (zend_ffi_cdata*)Z_OBJ_P(zv);
+ type = ZEND_FFI_TYPE(cdata->type);
+
+ if (type->kind != ZEND_FFI_TYPE_POINTER){
+ zend_throw_error(zend_ffi_exception_ce, "FFI\\Cdata is not a pointer");
+ return;
+ }
+
+ RETURN_BOOL(*(void**)cdata->ptr == NULL);
+}
+/* }}} */
+
static const zend_function_entry zend_ffi_functions[] = {
ZEND_ME(FFI, cdef, arginfo_class_FFI_cdef, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
ZEND_ME(FFI, load, arginfo_class_FFI_load, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
@@ -4346,6 +4375,7 @@ static const zend_function_entry zend_ffi_functions[] = {
ZEND_ME(FFI, memcmp, arginfo_class_FFI_memcmp, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
ZEND_ME(FFI, memset, arginfo_class_FFI_memset, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
ZEND_ME(FFI, string, arginfo_class_FFI_string, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
+ ZEND_ME(FFI, isNull, arginfo_class_FFI_isNull, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC)
ZEND_FE_END
};
diff --git a/ext/ffi/ffi.stub.php b/ext/ffi/ffi.stub.php
index c315c55a1c..812217f990 100644
--- a/ext/ffi/ffi.stub.php
+++ b/ext/ffi/ffi.stub.php
@@ -88,4 +88,9 @@ class FFI
* @return ?string
*/
static function string(FFI\CData $ptr, int $size = UNKNOWN) {}
+
+ /**
+ * @prefer-ref $ptr
+ */
+ static function isNull(FFI\CData $ptr) {}
}
diff --git a/ext/ffi/ffi_arginfo.h b/ext/ffi/ffi_arginfo.h
index 0dfcd858ae..48fc90c2cd 100644
--- a/ext/ffi/ffi_arginfo.h
+++ b/ext/ffi/ffi_arginfo.h
@@ -69,3 +69,5 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_FFI_string, 0, 0, 1)
ZEND_ARG_OBJ_INFO(ZEND_SEND_PREFER_REF, ptr, FFI\\CData, 0)
ZEND_ARG_TYPE_INFO(0, size, IS_LONG, 0)
ZEND_END_ARG_INFO()
+
+#define arginfo_class_FFI_isNull arginfo_class_FFI_free
diff --git a/ext/ffi/tests/045.phpt b/ext/ffi/tests/045.phpt
new file mode 100644
index 0000000000..8d4558e0d3
--- /dev/null
+++ b/ext/ffi/tests/045.phpt
@@ -0,0 +1,27 @@
+--TEST--
+FFI 045: FFI::isNull()
+--SKIPIF--
+<?php require_once('skipif.inc'); ?>
+--INI--
+ffi.enable=1
+--FILE--
+<?php
+var_dump(FFI::isNull(FFI::new("int*")));
+$i = FFI::new("int");
+var_dump(FFI::isNull(FFI::addr($i)));
+try {
+ var_dump(FFI::isNull(null));
+} catch (Throwable $e) {
+ echo get_class($e) . ": " . $e->getMessage()."\n";
+}
+try {
+ var_dump(FFI::isNull(FFI::new("int[0]")));
+} catch (Throwable $e) {
+ echo get_class($e) . ": " . $e->getMessage()."\n";
+}
+?>
+--EXPECTF--
+bool(true)
+bool(false)
+TypeError: FFI::isNull() expects parameter 1 to be FFI\CData, null given
+FFI\Exception: FFI\Cdata is not a pointer