]> granicus.if.org Git - php/commitdiff
Fix default value handling of mysqli_fetch_object()
authorMáté Kocsis <kocsismate@woohoolabs.com>
Tue, 13 Oct 2020 22:12:51 +0000 (00:12 +0200)
committerNikita Popov <nikita.ppv@gmail.com>
Tue, 20 Oct 2020 14:48:12 +0000 (16:48 +0200)
Make [] acceptable both for classes without constructors and
classes with a constructor that takes no arguments.

Closes GH-6336.

ext/mysqli/mysqli.c
ext/mysqli/mysqli.stub.php
ext/mysqli/mysqli_arginfo.h
ext/mysqli/tests/mysqli_fetch_object.phpt
ext/mysqli/tests/mysqli_fetch_object_no_constructor.phpt
ext/mysqli/tests/mysqli_fetch_object_oo.phpt
ext/pdo/pdo_dbh.c
ext/pgsql/pgsql.c
ext/pgsql/pgsql.stub.php
ext/pgsql/pgsql_arginfo.h

index 05ffffa926a106fe19bcdd99691c0af93d18d509..48a544d0c73d7090445a0528c111f26c9372a057 100644 (file)
@@ -1200,16 +1200,9 @@ void php_mysqli_fetch_into_hash(INTERNAL_FUNCTION_PARAMETERS, int override_flags
                        fci.param_count = 0;
                        fci.named_params = NULL;
 
-                       if (ctor_params && Z_TYPE_P(ctor_params) != IS_NULL) {
+                       if (ctor_params) {
                                if (zend_fcall_info_args(&fci, ctor_params) == FAILURE) {
-                                       /* Two problems why we throw exceptions here: PHP is typeless
-                                        * and hence passing one argument that's not an array could be
-                                        * by mistake and the other way round is possible, too. The
-                                        * single value is an array. Also we'd have to make that one
-                                        * argument passed by reference.
-                                        */
-                                       zend_argument_error(zend_ce_exception, 3, "must be of type array, %s given", zend_zval_type_name(ctor_params));
-                                       RETURN_THROWS();
+                                       ZEND_UNREACHABLE();
                                }
                        }
 
@@ -1223,8 +1216,11 @@ void php_mysqli_fetch_into_hash(INTERNAL_FUNCTION_PARAMETERS, int override_flags
                                zval_ptr_dtor(&retval);
                        }
                        zend_fcall_info_args_clear(&fci, 1);
-               } else if (ctor_params) {
-                       zend_throw_exception_ex(zend_ce_exception, 0, "Class %s does not have a constructor hence you cannot use ctor_params", ZSTR_VAL(ce->name));
+               } else if (ctor_params && zend_hash_num_elements(Z_ARRVAL_P(ctor_params)) > 0) {
+                       zend_argument_error(zend_ce_exception, ERROR_ARG_POS(3),
+                               "must be empty when the specified class (%s) does not have a constructor",
+                               ZSTR_VAL(ce->name)
+                       );
                }
        }
 }
index 48704857742228d31720337f492987ee1bfb4603..c1059254fc14fbca17e401ac12576e90cc20f430 100644 (file)
@@ -364,7 +364,7 @@ class mysqli_result implements IteratorAggregate
      * @return object|null
      * @alias mysqli_fetch_object
      */
-    public function fetch_object(string $class = "stdClass", array $params = []) {}
+    public function fetch_object(string $class = "stdClass", array $constructor_args = []) {}
 
     /**
      * @return array|null
@@ -581,7 +581,7 @@ function mysqli_fetch_array(mysqli_result $result, int $mode = MYSQLI_BOTH): arr
 
 function mysqli_fetch_assoc(mysqli_result $result): ?array {}
 
-function mysqli_fetch_object(mysqli_result $result, string $class = "stdClass", array $params = []): ?object {}
+function mysqli_fetch_object(mysqli_result $result, string $class = "stdClass", array $constructor_args = []): ?object {}
 
 function mysqli_fetch_row(mysqli_result $result): ?array {}
 
index 73960d38eb0d7d47523d70c11dbbfd3039767cb2..509840a7fc57d9d312ab5c2d7759e8861ed675af 100644 (file)
@@ -1,5 +1,5 @@
 /* This is a generated file, edit the .stub.php file instead.
- * Stub hash: 88f90ff45ab8f9748968c39eae950d58e598b73f */
+ * Stub hash: 480939b71e1dacbdbb4634dbabf375943e399b6f */
 
 ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_mysqli_affected_rows, 0, 1, MAY_BE_LONG|MAY_BE_STRING)
        ZEND_ARG_OBJ_INFO(0, mysql, mysqli, 0)
@@ -115,7 +115,7 @@ ZEND_END_ARG_INFO()
 ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_mysqli_fetch_object, 0, 1, IS_OBJECT, 1)
        ZEND_ARG_OBJ_INFO(0, result, mysqli_result, 0)
        ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, class, IS_STRING, 0, "\"stdClass\"")
-       ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, params, IS_ARRAY, 0, "[]")
+       ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, constructor_args, IS_ARRAY, 0, "[]")
 ZEND_END_ARG_INFO()
 
 #define arginfo_mysqli_fetch_row arginfo_mysqli_fetch_assoc
@@ -614,7 +614,7 @@ ZEND_END_ARG_INFO()
 
 ZEND_BEGIN_ARG_INFO_EX(arginfo_class_mysqli_result_fetch_object, 0, 0, 0)
        ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, class, IS_STRING, 0, "\"stdClass\"")
-       ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, params, IS_ARRAY, 0, "[]")
+       ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, constructor_args, IS_ARRAY, 0, "[]")
 ZEND_END_ARG_INFO()
 
 #define arginfo_class_mysqli_result_fetch_row arginfo_class_mysqli_character_set_name
index f5708ac55853dac936052e324605548eaa71436c..8076311112ce2132906f5303545108705b96eadd 100644 (file)
@@ -147,6 +147,6 @@ Exception: Too few arguments to function mysqli_fetch_object_construct::__constr
 NULL
 NULL
 mysqli_result object is already closed
-[0] mysqli_fetch_object(): Argument #3 ($params) must be of type array, string given in %s on line %d
+[0] mysqli_fetch_object(): Argument #3 ($constructor_args) must be of type array, string given in %s on line %d
 mysqli_fetch_object(): Argument #2 ($class) must be a valid class name, this_class_does_not_exist given
 done!
index 979c523199716698dcb52cf7791043b8d5acf7d0..5d823648c71c408283095e31acfe1bdf83205e08 100644 (file)
@@ -57,7 +57,7 @@ object(mysqli_fetch_object_test)#%d (%d) {
 }
 
 Exception with mysqli. Note that at all other places we throws errors but no exceptions unless the error mode has been changed:
-Exception: Class mysqli_fetch_object_test does not have a constructor hence you cannot use ctor_params
+Exception: mysqli_fetch_object(): Argument #3 ($constructor_args) must be empty when the specified class (mysqli_fetch_object_test) does not have a constructor
 
 Fatal error with PHP (but no exception!):
 
index f402db82d87b370f27b8afc6a65c3c7e03471584..c541ad2d044bcc6cb1dff5699d3a2fe7cdf97637 100644 (file)
@@ -73,14 +73,9 @@ require_once('skipifconnectfailure.inc');
     }
 
     try {
-        $obj = $res->fetch_object('mysqli_fetch_object_construct', null);
-
-        if (($obj->ID !== "3") || ($obj->label !== "c") || ($obj->a !== NULL) || ($obj->b !== NULL) || (get_class($obj) != 'mysqli_fetch_object_construct')) {
-            printf("[009] Object seems wrong. [%d] %s\n", $mysqli->errno, $mysqli->error);
-            var_dump($obj);
-        }
-    } catch (Error $e) {
-        handle_catchable_fatal($e->getCode(), $e->getMessage(), $e->getFile(), $e->getLine());
+        $res->fetch_object('mysqli_fetch_object_construct', null);
+    } catch (TypeError $exception) {
+        echo $exception->getMessage() . "\n";
         mysqli_fetch_object($res);
     }
 
@@ -134,7 +129,7 @@ require_once('skipifconnectfailure.inc');
 mysqli object is not fully initialized
 [0] Object of class mysqli could not be converted to string in %s on line %d
 [0] mysqli_result::fetch_object() expects at most 2 arguments, 3 given in %s on line %d
-[0] mysqli_result::fetch_object(): Argument #2 ($params) must be of type array, null given in %s on line %d
+mysqli_result::fetch_object(): Argument #2 ($constructor_args) must be of type array, null given
 Exception: Too few arguments to function mysqli_fetch_object_construct::__construct(), 1 passed and exactly 2 expected
 NULL
 NULL
index 2e81db2bbf52d29131f9a042609fed959bd416bb..a0c2b74c331f52de5a4d727a077ffa9bb5cbef19 100644 (file)
@@ -517,7 +517,7 @@ PHP_METHOD(PDO, prepare)
                }
                if ((item = zend_hash_index_find(Z_ARRVAL_P(value), 0)) == NULL) {
                        zend_value_error("PDO::ATTR_STATEMENT_CLASS value must be an array with the format "
-                               "array(classname, array(ctor_args))");
+                               "array(classname, constructor_args)");
                        RETURN_THROWS();
                }
                if (Z_TYPE_P(item) != IS_STRING || (pce = zend_lookup_class(Z_STR_P(item))) == NULL) {
@@ -535,7 +535,7 @@ PHP_METHOD(PDO, prepare)
                }
                if ((item = zend_hash_index_find(Z_ARRVAL_P(value), 1)) != NULL) {
                        if (Z_TYPE_P(item) != IS_ARRAY) {
-                               zend_type_error("PDO::ATTR_STATEMENT_CLASS ctor_args must be of type ?array, %s given",
+                               zend_type_error("PDO::ATTR_STATEMENT_CLASS constructor_args must be of type ?array, %s given",
                                        zend_zval_type_name(value));
                                RETURN_THROWS();
                        }
@@ -765,7 +765,7 @@ static zend_result pdo_dbh_attribute_set(pdo_dbh_t *dbh, zend_long attr, zval *v
                        }
                        if ((item = zend_hash_index_find(Z_ARRVAL_P(value), 0)) == NULL) {
                                zend_value_error("PDO::ATTR_STATEMENT_CLASS value must be an array with the format "
-                                       "array(classname, array(ctor_args))");
+                                       "array(classname, constructor_args)");
                                return FAILURE;
                        }
                        if (Z_TYPE_P(item) != IS_STRING || (pce = zend_lookup_class(Z_STR_P(item))) == NULL) {
@@ -787,7 +787,7 @@ static zend_result pdo_dbh_attribute_set(pdo_dbh_t *dbh, zend_long attr, zval *v
                        }
                        if ((item = zend_hash_index_find(Z_ARRVAL_P(value), 1)) != NULL) {
                                if (Z_TYPE_P(item) != IS_ARRAY) {
-                                       zend_type_error("PDO::ATTR_STATEMENT_CLASS ctor_args must be of type ?array, %s given",
+                                       zend_type_error("PDO::ATTR_STATEMENT_CLASS constructor_args must be of type ?array, %s given",
                                                zend_zval_type_name(value));
                                        return FAILURE;
                                }
index aac2afd4936be8f7af2f3e0eae28bc01304d032d..4685c7cd741e552d4e11be086ec97e9b3b9dc144 100644 (file)
@@ -1836,7 +1836,7 @@ static void php_pgsql_fetch_hash(INTERNAL_FUNCTION_PARAMETERS, zend_long result_
        zend_class_entry *ce = NULL;
 
        if (into_object) {
-               if (zend_parse_parameters(ZEND_NUM_ARGS(), "r|l!Ca!", &result, &row, &row_is_null, &ce, &ctor_params) == FAILURE) {
+               if (zend_parse_parameters(ZEND_NUM_ARGS(), "r|l!Ca", &result, &row, &row_is_null, &ce, &ctor_params) == FAILURE) {
                        RETURN_THROWS();
                }
                if (!ce) {
@@ -1935,14 +1935,7 @@ static void php_pgsql_fetch_hash(INTERNAL_FUNCTION_PARAMETERS, zend_long result_
 
                        if (ctor_params) {
                                if (zend_fcall_info_args(&fci, ctor_params) == FAILURE) {
-                                       /* Two problems why we throw exceptions here: PHP is typeless
-                                        * and hence passing one argument that's not an array could be
-                                        * by mistake and the other way round is possible, too. The
-                                        * single value is an array. Also we'd have to make that one
-                                        * argument passed by reference.
-                                        */
-                                       zend_throw_exception(zend_ce_exception, "Parameter ctor_params must be an array", 0);
-                                       RETURN_THROWS();
+                                       ZEND_UNREACHABLE();
                                }
                        }
 
@@ -1958,8 +1951,11 @@ static void php_pgsql_fetch_hash(INTERNAL_FUNCTION_PARAMETERS, zend_long result_
                        if (fci.params) {
                                efree(fci.params);
                        }
-               } else if (ctor_params) {
-                       zend_throw_exception_ex(zend_ce_exception, 0, "Class %s does not have a constructor hence you cannot use ctor_params", ZSTR_VAL(ce->name));
+               } else if (ctor_params && zend_hash_num_elements(Z_ARRVAL_P(ctor_params)) > 0) {
+                       zend_argument_error(zend_ce_exception, 3,
+                               "must be empty when the specified class (%s) does not have a constructor",
+                               ZSTR_VAL(ce->name)
+                       );
                }
        }
 }
index 8460fd26b6b4a37c92d603950835a8ed9e7bab34..aff847bbc444ad8619ce0ad719a42b0cbc665464 100644 (file)
@@ -190,7 +190,7 @@ function pg_fetch_assoc($result, ?int $row = null): array|false {}
 function pg_fetch_array($result, ?int $row = null, int $mode = PGSQL_BOTH): array|false {}
 
 /** @param resource $result */
-function pg_fetch_object($result, ?int $row = null, string $class = "stdClass", ?array $ctor_args = null): object|false {}
+function pg_fetch_object($result, ?int $row = null, string $class = "stdClass", array $constructor_args = []): object|false {}
 
 /** @param resource $result */
 function pg_fetch_all($result, int $mode = PGSQL_ASSOC): array {}
index 5bdda3ea0766861f1e38cdcb859e3aaf5e87a52d..3d9a4f2d5d2b81d842b7122101e9e6bc00a28726 100644 (file)
@@ -1,5 +1,5 @@
 /* This is a generated file, edit the .stub.php file instead.
- * Stub hash: 26edbb4ade84f0faad592dd270756c17e396519b */
+ * Stub hash: de1718d3e6e66dfade25462b8461983b914120ed */
 
 ZEND_BEGIN_ARG_INFO_EX(arginfo_pg_connect, 0, 0, 1)
        ZEND_ARG_TYPE_INFO(0, connection_string, IS_STRING, 0)
@@ -152,7 +152,7 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_pg_fetch_object, 0, 1, MAY_BE_OB
        ZEND_ARG_INFO(0, result)
        ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, row, IS_LONG, 1, "null")
        ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, class, IS_STRING, 0, "\"stdClass\"")
-       ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, ctor_args, IS_ARRAY, 1, "null")
+       ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, constructor_args, IS_ARRAY, 0, "[]")
 ZEND_END_ARG_INFO()
 
 ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_pg_fetch_all, 0, 1, IS_ARRAY, 0)