From 09724a0d7d016db4e71a64f78507c932d32eda80 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Mon, 29 Jun 2020 13:40:45 +0200 Subject: [PATCH 1/2] Fix #79749: Converting FFI instances to bool fails Casting objects to bool is supposed to yield `true`. Since the `cast_object` handler is required now, we have to implement the `_IS_BOOL` conversion there. --- ext/ffi/ffi.c | 19 ++++++++++++++----- ext/ffi/tests/bug79749.phpt | 17 +++++++++++++++++ 2 files changed, 31 insertions(+), 5 deletions(-) create mode 100644 ext/ffi/tests/bug79749.phpt diff --git a/ext/ffi/ffi.c b/ext/ffi/ffi.c index 28baf1fd31c78..2552fb08f543d 100644 --- a/ext/ffi/ffi.c +++ b/ext/ffi/ffi.c @@ -1096,6 +1096,9 @@ static int zend_ffi_cdata_cast_object(zend_object *readobj, zval *writeobj, int } convert_to_string(writeobj); return SUCCESS; + } else if (type == _IS_BOOL) { + ZVAL_TRUE(writeobj); + return SUCCESS; } return FAILURE; @@ -4640,9 +4643,15 @@ static HashTable *zend_fake_get_gc(zend_object *ob, zval **table, int *n) /* {{{ } /* }}} */ -static int zend_fake_cast_object(zend_object *obj, zval *result, int type) +static int zend_cast_object(zend_object *obj, zval *result, int type) { - return FAILURE; + switch (type) { + case _IS_BOOL: + ZVAL_TRUE(result); + return SUCCESS; + default: + return FAILURE; + } } static ZEND_COLD zend_never_inline void zend_ffi_use_after_free(void) /* {{{ */ @@ -4897,7 +4906,7 @@ ZEND_MINIT_FUNCTION(ffi) zend_ffi_handlers.unset_dimension = zend_fake_unset_dimension; zend_ffi_handlers.get_method = zend_ffi_get_func; zend_ffi_handlers.compare = NULL; - zend_ffi_handlers.cast_object = zend_fake_cast_object; + zend_ffi_handlers.cast_object = zend_cast_object; zend_ffi_handlers.get_debug_info = NULL; zend_ffi_handlers.get_closure = NULL; zend_ffi_handlers.get_properties = zend_fake_get_properties; @@ -4976,7 +4985,7 @@ ZEND_MINIT_FUNCTION(ffi) zend_ffi_cdata_free_handlers.get_method = zend_fake_get_method; zend_ffi_cdata_free_handlers.get_class_name = zend_ffi_cdata_get_class_name; zend_ffi_cdata_free_handlers.compare = zend_ffi_cdata_compare_objects; - zend_ffi_cdata_free_handlers.cast_object = zend_fake_cast_object; + zend_ffi_cdata_free_handlers.cast_object = zend_cast_object; zend_ffi_cdata_free_handlers.count_elements = NULL; zend_ffi_cdata_free_handlers.get_debug_info = zend_ffi_free_get_debug_info; zend_ffi_cdata_free_handlers.get_closure = NULL; @@ -5006,7 +5015,7 @@ ZEND_MINIT_FUNCTION(ffi) zend_ffi_ctype_handlers.get_method = zend_fake_get_method; zend_ffi_ctype_handlers.get_class_name = zend_ffi_ctype_get_class_name; zend_ffi_ctype_handlers.compare = zend_ffi_ctype_compare_objects; - zend_ffi_ctype_handlers.cast_object = zend_fake_cast_object; + zend_ffi_ctype_handlers.cast_object = zend_cast_object; zend_ffi_ctype_handlers.count_elements = NULL; zend_ffi_ctype_handlers.get_debug_info = zend_ffi_ctype_get_debug_info; zend_ffi_ctype_handlers.get_closure = NULL; diff --git a/ext/ffi/tests/bug79749.phpt b/ext/ffi/tests/bug79749.phpt new file mode 100644 index 0000000000000..5e0862a20756c --- /dev/null +++ b/ext/ffi/tests/bug79749.phpt @@ -0,0 +1,17 @@ +--TEST-- +Bug #79749 (Converting FFI instances to bool fails) +--SKIPIF-- + +--FILE-- + +--EXPECT-- +bool(true) +bool(true) +bool(true) From a10f4112f1a5af77d2fbfb83a5707c5933fa17ba Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Mon, 29 Jun 2020 15:39:17 +0200 Subject: [PATCH 2/2] Rename zend_cast_object back to zend_fake_cast_object The former name may easily be confused with a ZE standard object cast. --- ext/ffi/ffi.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ext/ffi/ffi.c b/ext/ffi/ffi.c index 2552fb08f543d..946f6c9845299 100644 --- a/ext/ffi/ffi.c +++ b/ext/ffi/ffi.c @@ -4643,7 +4643,7 @@ static HashTable *zend_fake_get_gc(zend_object *ob, zval **table, int *n) /* {{{ } /* }}} */ -static int zend_cast_object(zend_object *obj, zval *result, int type) +static int zend_fake_cast_object(zend_object *obj, zval *result, int type) { switch (type) { case _IS_BOOL: @@ -4906,7 +4906,7 @@ ZEND_MINIT_FUNCTION(ffi) zend_ffi_handlers.unset_dimension = zend_fake_unset_dimension; zend_ffi_handlers.get_method = zend_ffi_get_func; zend_ffi_handlers.compare = NULL; - zend_ffi_handlers.cast_object = zend_cast_object; + zend_ffi_handlers.cast_object = zend_fake_cast_object; zend_ffi_handlers.get_debug_info = NULL; zend_ffi_handlers.get_closure = NULL; zend_ffi_handlers.get_properties = zend_fake_get_properties; @@ -4985,7 +4985,7 @@ ZEND_MINIT_FUNCTION(ffi) zend_ffi_cdata_free_handlers.get_method = zend_fake_get_method; zend_ffi_cdata_free_handlers.get_class_name = zend_ffi_cdata_get_class_name; zend_ffi_cdata_free_handlers.compare = zend_ffi_cdata_compare_objects; - zend_ffi_cdata_free_handlers.cast_object = zend_cast_object; + zend_ffi_cdata_free_handlers.cast_object = zend_fake_cast_object; zend_ffi_cdata_free_handlers.count_elements = NULL; zend_ffi_cdata_free_handlers.get_debug_info = zend_ffi_free_get_debug_info; zend_ffi_cdata_free_handlers.get_closure = NULL; @@ -5015,7 +5015,7 @@ ZEND_MINIT_FUNCTION(ffi) zend_ffi_ctype_handlers.get_method = zend_fake_get_method; zend_ffi_ctype_handlers.get_class_name = zend_ffi_ctype_get_class_name; zend_ffi_ctype_handlers.compare = zend_ffi_ctype_compare_objects; - zend_ffi_ctype_handlers.cast_object = zend_cast_object; + zend_ffi_ctype_handlers.cast_object = zend_fake_cast_object; zend_ffi_ctype_handlers.count_elements = NULL; zend_ffi_ctype_handlers.get_debug_info = zend_ffi_ctype_get_debug_info; zend_ffi_ctype_handlers.get_closure = NULL;