From 373b783d383b4a4b4e4aaed280231380d1eb3b75 Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Fri, 8 Jan 2021 14:44:53 +0100 Subject: [PATCH 1/2] Fix #80575: Casting mysqli to array produces null on every field We implement a `get_properties_for` handler for casting to array, and also use this instead of the `get_debug_info` handler. --- ext/mysqli/mysqli.c | 14 +++++++++++--- ext/mysqli/tests/bug80575.phpt | 16 ++++++++++++++++ 2 files changed, 27 insertions(+), 3 deletions(-) create mode 100644 ext/mysqli/tests/bug80575.phpt diff --git a/ext/mysqli/mysqli.c b/ext/mysqli/mysqli.c index c4dbcb251a66..6ca2b04f00f1 100644 --- a/ext/mysqli/mysqli.c +++ b/ext/mysqli/mysqli.c @@ -428,12 +428,20 @@ static int mysqli_object_has_property(zval *object, zval *member, int has_set_ex return ret; } /* }}} */ -HashTable *mysqli_object_get_debug_info(zval *object, int *is_temp) +static HashTable *mysqli_object_get_properties_for(zval *object, zend_prop_purpose purpose) /* {{{ */ { mysqli_object *obj = Z_MYSQLI_P(object); HashTable *retval, *props = obj->prop_handler; mysqli_prop_handler *entry; + switch (purpose) { + case ZEND_PROP_PURPOSE_DEBUG: + case ZEND_PROP_PURPOSE_ARRAY_CAST: + break; + default: + return zend_std_get_properties_for(object, purpose); + } + retval = zend_new_array(zend_hash_num_elements(props) + 1); ZEND_HASH_FOREACH_PTR(props, entry) { @@ -447,7 +455,6 @@ HashTable *mysqli_object_get_debug_info(zval *object, int *is_temp) } } ZEND_HASH_FOREACH_END(); - *is_temp = 1; return retval; } @@ -585,7 +592,8 @@ PHP_MINIT_FUNCTION(mysqli) mysqli_object_handlers.read_property = mysqli_read_property; mysqli_object_handlers.write_property = mysqli_write_property; mysqli_object_handlers.has_property = mysqli_object_has_property; - mysqli_object_handlers.get_debug_info = mysqli_object_get_debug_info; + mysqli_object_handlers.get_properties_for = mysqli_object_get_properties_for; + memcpy(&mysqli_object_driver_handlers, &mysqli_object_handlers, sizeof(zend_object_handlers)); mysqli_object_driver_handlers.free_obj = mysqli_driver_free_storage; memcpy(&mysqli_object_link_handlers, &mysqli_object_handlers, sizeof(zend_object_handlers)); diff --git a/ext/mysqli/tests/bug80575.phpt b/ext/mysqli/tests/bug80575.phpt new file mode 100644 index 000000000000..46db2d5dc61e --- /dev/null +++ b/ext/mysqli/tests/bug80575.phpt @@ -0,0 +1,16 @@ +--TEST-- +Bug #80575 (Casting mysqli to array produces null on every field) +--SKIPIF-- + +--FILE-- + +--EXPECT-- +int(0) From 689203f0a11c1e373371844706d04f152cee75fb Mon Sep 17 00:00:00 2001 From: "Christoph M. Becker" Date: Tue, 12 Jan 2021 15:11:51 +0100 Subject: [PATCH 2/2] Implement ::__debugInfo() instead of relying on magic --- ext/mysqli/mysqli_fe.c | 1 + ext/mysqli/mysqli_fe.h | 1 + ext/mysqli/mysqli_nonapi.c | 12 ++++++++++++ ext/mysqli/tests/bug80575.phpt | 2 ++ 4 files changed, 16 insertions(+) diff --git a/ext/mysqli/mysqli_fe.c b/ext/mysqli/mysqli_fe.c index 4869228ef25b..92fbd23a3bbd 100644 --- a/ext/mysqli/mysqli_fe.c +++ b/ext/mysqli/mysqli_fe.c @@ -593,6 +593,7 @@ const zend_function_entry mysqli_link_methods[] = { PHP_FALIAS(thread_safe, mysqli_thread_safe, arginfo_mysqli_no_params) PHP_FALIAS(use_result, mysqli_use_result, arginfo_mysqli_no_params) PHP_FALIAS(refresh,mysqli_refresh, arginfo_class_mysqli_refresh) + PHP_ME(mysqli, __debugInfo, arginfo_mysqli_no_params, 0) PHP_FE_END }; /* }}} */ diff --git a/ext/mysqli/mysqli_fe.h b/ext/mysqli/mysqli_fe.h index c6e8293d1af0..7c61be290ebe 100644 --- a/ext/mysqli/mysqli_fe.h +++ b/ext/mysqli/mysqli_fe.h @@ -128,6 +128,7 @@ PHP_FUNCTION(mysqli_thread_id); PHP_FUNCTION(mysqli_thread_safe); PHP_FUNCTION(mysqli_use_result); PHP_FUNCTION(mysqli_warning_count); +PHP_METHOD(mysqli, __debugInfo); PHP_FUNCTION(mysqli_stmt_construct); PHP_FUNCTION(mysqli_result_construct); diff --git a/ext/mysqli/mysqli_nonapi.c b/ext/mysqli/mysqli_nonapi.c index 2c655cffb8a4..49fb32879432 100644 --- a/ext/mysqli/mysqli_nonapi.c +++ b/ext/mysqli/mysqli_nonapi.c @@ -1280,4 +1280,16 @@ PHP_FUNCTION(mysqli_get_links_stats) add_assoc_long_ex(return_value, "active_plinks", sizeof("active_plinks") - 1, MyG(num_active_persistent)); add_assoc_long_ex(return_value, "cached_plinks", sizeof("cached_plinks") - 1, MyG(num_inactive_persistent)); } + +PHP_METHOD(mysqli, __debugInfo) +{ + if (zend_parse_parameters_none() == FAILURE) { + return; + } + + zval *self = ZEND_THIS; + zend_object *obj = Z_OBJ_P(self); + HashTable *ht = obj->handlers->get_properties_for(self, ZEND_PROP_PURPOSE_ARRAY_CAST); + RETURN_ARR(ht); +} /* }}} */ diff --git a/ext/mysqli/tests/bug80575.phpt b/ext/mysqli/tests/bug80575.phpt index 46db2d5dc61e..c76e00ffeda0 100644 --- a/ext/mysqli/tests/bug80575.phpt +++ b/ext/mysqli/tests/bug80575.phpt @@ -11,6 +11,8 @@ require_once('skipifconnectfailure.inc'); require_once('connect.inc'); $link = new mysqli($host, $user, $passwd, $db, $port, $socket); var_dump(((array) $link)["affected_rows"]); +var_dump($link->__debugInfo()["affected_rows"]); ?> --EXPECT-- int(0) +int(0)