From e5c6b87d981a76585fb6ccff5781da293ac4067c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1t=C3=A9=20Kocsis?= Date: Mon, 24 Aug 2020 20:42:29 +0200 Subject: [PATCH 1/4] Move custom type checks to ZPP --- ext/mbstring/mbstring.c | 30 ++++----- ext/mbstring/mbstring.stub.php | 3 +- ext/mbstring/mbstring_arginfo.h | 4 +- ext/mysqli/mysqli.stub.php | 16 ++--- ext/mysqli/mysqli_api.c | 57 +++++++++-------- ext/mysqli/mysqli_arginfo.h | 6 +- ext/oci8/oci8.stub.php | 2 +- ext/oci8/oci8_arginfo.h | 2 +- ext/odbc/odbc.stub.php | 7 +-- ext/odbc/odbc_arginfo.h | 4 +- ext/odbc/php_odbc.c | 19 ++++-- .../xml_parser_set_option_variation3.phpt | 32 +++++----- ext/xml/xml.c | 41 +++++++++---- ext/xml/xml.stub.php | 3 +- ext/xml/xml_arginfo.h | 4 +- ext/xsl/php_xsl.stub.php | 14 ++--- ext/xsl/php_xsl_arginfo.h | 8 +-- ext/xsl/xsltprocessor.c | 39 ++++++++---- ext/zip/php_zip.c | 61 +++++++++---------- ext/zip/php_zip.stub.php | 7 +-- ext/zip/php_zip_arginfo.h | 4 +- 21 files changed, 187 insertions(+), 176 deletions(-) diff --git a/ext/mbstring/mbstring.c b/ext/mbstring/mbstring.c index 1fba2db34c0a5..13031d90d3e39 100644 --- a/ext/mbstring/mbstring.c +++ b/ext/mbstring/mbstring.c @@ -3513,8 +3513,8 @@ PHP_FUNCTION(mb_send_mail) size_t message_len; char *subject; size_t subject_len; - zval *headers = NULL; zend_string *extra_cmd = NULL; + HashTable *headers_ht = NULL; zend_string *str_headers = NULL, *tmp_headers; size_t n, i; char *to_r = NULL; @@ -3560,30 +3560,24 @@ PHP_FUNCTION(mb_send_mail) Z_PARAM_STRING(subject, subject_len) Z_PARAM_STRING(message, message_len) Z_PARAM_OPTIONAL - Z_PARAM_ZVAL(headers) - Z_PARAM_STR(extra_cmd) + Z_PARAM_STR_OR_ARRAY_HT_OR_NULL(str_headers, headers_ht) + Z_PARAM_STR_OR_NULL(extra_cmd) ZEND_PARSE_PARAMETERS_END(); /* ASCIIZ check */ MAIL_ASCIIZ_CHECK_MBSTRING(to, to_len); MAIL_ASCIIZ_CHECK_MBSTRING(subject, subject_len); MAIL_ASCIIZ_CHECK_MBSTRING(message, message_len); - if (headers) { - switch(Z_TYPE_P(headers)) { - case IS_STRING: - tmp_headers = zend_string_init(Z_STRVAL_P(headers), Z_STRLEN_P(headers), 0); - MAIL_ASCIIZ_CHECK_MBSTRING(ZSTR_VAL(tmp_headers), ZSTR_LEN(tmp_headers)); - str_headers = php_trim(tmp_headers, NULL, 0, 2); - zend_string_release_ex(tmp_headers, 0); - break; - case IS_ARRAY: - str_headers = php_mail_build_headers(Z_ARRVAL_P(headers)); - break; - default: - zend_argument_value_error(4, "must be of type string|array|null, %s given", zend_zval_type_name(headers)); - RETURN_THROWS(); - } + + if (str_headers) { + tmp_headers = zend_string_init(ZSTR_VAL(str_headers), ZSTR_LEN(str_headers), 0); + MAIL_ASCIIZ_CHECK_MBSTRING(ZSTR_VAL(tmp_headers), ZSTR_LEN(tmp_headers)); + str_headers = php_trim(tmp_headers, NULL, 0, 2); + zend_string_release_ex(tmp_headers, 0); + } else if (headers_ht) { + str_headers = php_mail_build_headers(headers_ht); } + if (extra_cmd) { MAIL_ASCIIZ_CHECK_MBSTRING(ZSTR_VAL(extra_cmd), ZSTR_LEN(extra_cmd)); } diff --git a/ext/mbstring/mbstring.stub.php b/ext/mbstring/mbstring.stub.php index 343a5d103d136..d089c24c194cb 100644 --- a/ext/mbstring/mbstring.stub.php +++ b/ext/mbstring/mbstring.stub.php @@ -77,8 +77,7 @@ function mb_encode_numericentity(string $string, array $convmap, ?string $encodi function mb_decode_numericentity(string $string, array $convmap, ?string $encoding = null): string {} -/** @param string|array|null $additional_headers */ -function mb_send_mail(string $to, string $subject, string $message, $additional_headers = null, ?string $additional_parameters = null): bool {} +function mb_send_mail(string $to, string $subject, string $message, array|string|null $additional_headers = null, ?string $additional_parameters = null): bool {} function mb_get_info(string $type = "all"): array|string|int|false {} diff --git a/ext/mbstring/mbstring_arginfo.h b/ext/mbstring/mbstring_arginfo.h index 7267b943ef06e..873a0c86a45cc 100644 --- a/ext/mbstring/mbstring_arginfo.h +++ b/ext/mbstring/mbstring_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 5ad8a8cf20eeae59713d19135ecccbee243754eb */ + * Stub hash: 84096daa0fd395f57401f11e9e79f7c8420e8a93 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_mb_language, 0, 0, MAY_BE_STRING|MAY_BE_BOOL) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, language, IS_STRING, 1, "null") @@ -178,7 +178,7 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_mb_send_mail, 0, 3, _IS_BOOL, 0) ZEND_ARG_TYPE_INFO(0, to, IS_STRING, 0) ZEND_ARG_TYPE_INFO(0, subject, IS_STRING, 0) ZEND_ARG_TYPE_INFO(0, message, IS_STRING, 0) - ZEND_ARG_INFO_WITH_DEFAULT_VALUE(0, additional_headers, "null") + ZEND_ARG_TYPE_MASK(0, additional_headers, MAY_BE_ARRAY|MAY_BE_STRING|MAY_BE_NULL, "null") ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, additional_parameters, IS_STRING, 1, "null") ZEND_END_ARG_INFO() diff --git a/ext/mysqli/mysqli.stub.php b/ext/mysqli/mysqli.stub.php index 940f3c4fcc749..30b8403354501 100644 --- a/ext/mysqli/mysqli.stub.php +++ b/ext/mysqli/mysqli.stub.php @@ -237,18 +237,16 @@ public function select_db(string $database) {} public function set_charset(string $charset) {} /** - * @param string|int $value * @return bool * @alias mysqli_options */ - public function options(int $option, $value) {} + public function options(int $option, string|int $value) {} /** - * @param string|int $value * @return bool * @alias mysqli_options */ - public function set_opt(int $option, $value) {} + public function set_opt(int $option, string|int $value) {} /** * @return bool @@ -630,8 +628,7 @@ function mysqli_num_fields(mysqli_result $mysql_result): int {} function mysqli_num_rows(mysqli_result $mysqli_result): int|string {} -/** @param string|int $value */ -function mysqli_options(mysqli $mysqli_link, int $option, $value): bool {} +function mysqli_options(mysqli $mysqli_link, int $option, string|int $value): bool {} function mysqli_ping(mysqli $mysqli_link): bool {} @@ -752,8 +749,5 @@ function mysqli_refresh(mysqli $mysqli_link, int $options): bool {} /** @alias mysqli_real_escape_string */ function mysqli_escape_string(mysqli $mysqli_link, string $string_to_escape): string {} -/** - * @param string|int $value - * @alias mysqli_options - */ -function mysqli_set_opt(mysqli $mysqli_link, int $option, $value): bool {} +/** @alias mysqli_options */ +function mysqli_set_opt(mysqli $mysqli_link, int $option, string|int $value): bool {} diff --git a/ext/mysqli/mysqli_api.c b/ext/mysqli/mysqli_api.c index 3f89e838fd894..6790302091b5b 100644 --- a/ext/mysqli/mysqli_api.c +++ b/ext/mysqli/mysqli_api.c @@ -1675,16 +1675,26 @@ static int mysqli_options_get_option_zval_type(int option) PHP_FUNCTION(mysqli_options) { MY_MYSQL *mysql; - zval *mysql_link = NULL; - zval *mysql_value; + zval *mysql_link = getThis(); + zend_string *mysql_value_str; + zend_long mysql_value_long; zend_long mysql_option; - unsigned int l_value; zend_long ret; int expected_type; - if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Olz", &mysql_link, mysqli_link_class_entry, &mysql_option, &mysql_value) == FAILURE) { - RETURN_THROWS(); + if (mysql_link) { + ZEND_PARSE_PARAMETERS_START(2, 2) + Z_PARAM_LONG(mysql_option) + Z_PARAM_STR_OR_LONG(mysql_value_str, mysql_value_long) + ZEND_PARSE_PARAMETERS_END(); + } else { + ZEND_PARSE_PARAMETERS_START(3, 3) + Z_PARAM_OBJECT_OF_CLASS(mysql_link, mysqli_link_class_entry) + Z_PARAM_LONG(mysql_option) + Z_PARAM_STR_OR_LONG(mysql_value_str, mysql_value_long) + ZEND_PARSE_PARAMETERS_END(); } + MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_INITIALIZED); #ifndef MYSQLI_USE_MYSQLND @@ -1695,31 +1705,20 @@ PHP_FUNCTION(mysqli_options) } #endif expected_type = mysqli_options_get_option_zval_type(mysql_option); - if (expected_type != Z_TYPE_P(mysql_value)) { - switch (expected_type) { - case IS_STRING: - if (!try_convert_to_string(mysql_value)) { - RETURN_THROWS(); - } - break; - case IS_LONG: - convert_to_long_ex(mysql_value); - break; - default: - break; + if (expected_type == IS_STRING) { + if (!mysql_value_str) { + zend_argument_type_error(3, "must be of type string for the chosen option"); + RETURN_THROWS(); } - } - switch (expected_type) { - case IS_STRING: - ret = mysql_options(mysql->mysql, mysql_option, Z_STRVAL_P(mysql_value)); - break; - case IS_LONG: - l_value = Z_LVAL_P(mysql_value); - ret = mysql_options(mysql->mysql, mysql_option, (char *)&l_value); - break; - default: - ret = 1; - break; + ret = mysql_options(mysql->mysql, mysql_option, ZSTR_VAL(mysql_value_str)); + } else if (expected_type == IS_LONG) { + if (mysql_value_str) { + zend_argument_type_error(3, "must be of type int for the chosen option"); + RETURN_THROWS(); + } + ret = mysql_options(mysql->mysql, mysql_option, (char *) &mysql_value_long); + } else if (expected_type == IS_NULL) { + ret = 1; } RETURN_BOOL(!ret); diff --git a/ext/mysqli/mysqli_arginfo.h b/ext/mysqli/mysqli_arginfo.h index 7d7c69e943919..bd692c0ae51b0 100644 --- a/ext/mysqli/mysqli_arginfo.h +++ b/ext/mysqli/mysqli_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: a8626c7c42e4d117b08df7f42a7523f60f357b82 */ + * Stub hash: 5695d494cc9a1f780e65c525c47e047780bf80f1 */ 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_link, mysqli, 0) @@ -208,7 +208,7 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_mysqli_options, 0, 3, _IS_BOOL, 0) ZEND_ARG_OBJ_INFO(0, mysqli_link, mysqli, 0) ZEND_ARG_TYPE_INFO(0, option, IS_LONG, 0) - ZEND_ARG_INFO(0, value) + ZEND_ARG_TYPE_MASK(0, value, MAY_BE_STRING|MAY_BE_LONG, NULL) ZEND_END_ARG_INFO() #define arginfo_mysqli_ping arginfo_mysqli_more_results @@ -545,7 +545,7 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_class_mysqli_options, 0, 0, 2) ZEND_ARG_TYPE_INFO(0, option, IS_LONG, 0) - ZEND_ARG_INFO(0, value) + ZEND_ARG_TYPE_MASK(0, value, MAY_BE_STRING|MAY_BE_LONG, NULL) ZEND_END_ARG_INFO() #define arginfo_class_mysqli_set_opt arginfo_class_mysqli_options diff --git a/ext/oci8/oci8.stub.php b/ext/oci8/oci8.stub.php index 5c964c16f828c..7a17430dc0aea 100644 --- a/ext/oci8/oci8.stub.php +++ b/ext/oci8/oci8.stub.php @@ -266,7 +266,7 @@ function oci_fetch_all($statement_resource, &$output, int $skip = 0, int $maximu /** * @param resource $statement_resource - * @param mixed $output + * @param array $output * @alias oci_fetch_all * @deprecated */ diff --git a/ext/oci8/oci8_arginfo.h b/ext/oci8/oci8_arginfo.h index 77638aa9a0e67..729ac02240444 100644 --- a/ext/oci8/oci8_arginfo.h +++ b/ext/oci8/oci8_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: a5a245b354b48a56c274c8f74c974d92ec430853 */ + * Stub hash: 447880a4bc4add36beab835cc07c09a254dc0c2b */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_oci_define_by_name, 0, 3, _IS_BOOL, 0) ZEND_ARG_INFO(0, statement_resource) diff --git a/ext/odbc/odbc.stub.php b/ext/odbc/odbc.stub.php index 89371024eb9cf..cb318f7ac9d4f 100644 --- a/ext/odbc/odbc.stub.php +++ b/ext/odbc/odbc.stub.php @@ -57,11 +57,8 @@ function odbc_fetch_into($result_id, &$result_array, int $rownumber = 0): int|fa /** @param resource $result_id */ function odbc_fetch_row($result_id, int $row_number = UNKNOWN): bool {} -/** - * @param resource $result_id - * @param string|int $field - */ -function odbc_result($result_id, $field): string|bool|null {} +/** @param resource $result_id */ +function odbc_result($result_id, string|int $field): string|bool|null {} /** @param resource $result_id */ function odbc_result_all($result_id, string $format = ''): int|false {} diff --git a/ext/odbc/odbc_arginfo.h b/ext/odbc/odbc_arginfo.h index 2f5ffbe547af0..778ab242a0b10 100644 --- a/ext/odbc/odbc_arginfo.h +++ b/ext/odbc/odbc_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 14702a5bd87902871d456de2289f4ae236e5bfa5 */ + * Stub hash: cf17952d8c3b88f218bbb8d1c21ba40079574c04 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_odbc_close_all, 0, 0, IS_VOID, 0) ZEND_END_ARG_INFO() @@ -70,7 +70,7 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_odbc_result, 0, 2, MAY_BE_STRING|MAY_BE_BOOL|MAY_BE_NULL) ZEND_ARG_INFO(0, result_id) - ZEND_ARG_INFO(0, field) + ZEND_ARG_TYPE_MASK(0, field, MAY_BE_STRING|MAY_BE_LONG, NULL) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_odbc_result_all, 0, 1, MAY_BE_LONG|MAY_BE_FALSE) diff --git a/ext/odbc/php_odbc.c b/ext/odbc/php_odbc.c index 7a4495f0d1f3b..c96aab82e791d 100644 --- a/ext/odbc/php_odbc.c +++ b/ext/odbc/php_odbc.c @@ -1736,24 +1736,31 @@ PHP_FUNCTION(odbc_fetch_row) PHP_FUNCTION(odbc_result) { char *field; - zend_string *field_str; + zend_string *field_str, *pv_field_str; + zend_long pv_field_long; int field_ind; SQLSMALLINT sql_c_type = SQL_C_CHAR; odbc_result *result; int i = 0; RETCODE rc; SQLLEN fieldsize; - zval *pv_res, *pv_field; + zval *pv_res; #ifdef HAVE_SQL_EXTENDED_FETCH SQLULEN crow; SQLUSMALLINT RowStatus[1]; #endif - field_ind = -1; - field = NULL; + ZEND_PARSE_PARAMETERS_START(2, 2) + Z_PARAM_RESOURCE(pv_res) + Z_PARAM_STR_OR_LONG(pv_field_str, pv_field_ind) + ZEND_PARSE_PARAMETERS_END(); - if (zend_parse_parameters(ZEND_NUM_ARGS(), "rz", &pv_res, &pv_field) == FAILURE) { - RETURN_THROWS(); + if (pv_field_str) { + field = ZSTR_VAL(pv_field_str); + field_ind = -1; + } else { + field = NULL; + field_ind = pv_field_long - 1; } if (Z_TYPE_P(pv_field) == IS_STRING) { diff --git a/ext/xml/tests/xml_parser_set_option_variation3.phpt b/ext/xml/tests/xml_parser_set_option_variation3.phpt index b9d4b945e7112..167050e3d4462 100644 --- a/ext/xml/tests/xml_parser_set_option_variation3.phpt +++ b/ext/xml/tests/xml_parser_set_option_variation3.phpt @@ -78,8 +78,12 @@ $values = array( foreach($values as $value) { echo @"\nArg value $value \n"; - var_dump( xml_parser_set_option($parser, $option, $value) ); -}; + try { + var_dump(xml_parser_set_option($parser, $option, $value)); + } catch (TypeError $exception) { + echo $exception->getMessage() . "\n"; + } +} fclose($fp); xml_parser_free($parser); @@ -116,19 +120,19 @@ Arg value 0.5 bool(true) Arg value Array -bool(true) +xml_parser_set_option(): Argument #3 ($value) must be of type string|int, array given Arg value Array -bool(true) +xml_parser_set_option(): Argument #3 ($value) must be of type string|int, array given Arg value Array -bool(true) +xml_parser_set_option(): Argument #3 ($value) must be of type string|int, array given Arg value Array -bool(true) +xml_parser_set_option(): Argument #3 ($value) must be of type string|int, array given Arg value Array -bool(true) +xml_parser_set_option(): Argument #3 ($value) must be of type string|int, array given Arg value bool(true) @@ -149,22 +153,20 @@ Arg value bool(true) Arg value -bool(true) +xml_parser_set_option(): Argument #3 ($value) must be of type string for the chosen option Arg value -bool(true) +xml_parser_set_option(): Argument #3 ($value) must be of type string for the chosen option Arg value string -bool(true) +xml_parser_set_option(): Argument #3 ($value) must be of type string for the chosen option Arg value string -bool(true) +xml_parser_set_option(): Argument #3 ($value) must be of type string for the chosen option Arg value Some Ascii Data - -Notice: Object of class aClass could not be converted to int in %s on line %d -bool(true) +xml_parser_set_option(): Argument #3 ($value) must be of type string for the chosen option Arg value Resource id %s -bool(true) +xml_parser_set_option(): Argument #3 ($value) must be of type string|int, resource given Done diff --git a/ext/xml/xml.c b/ext/xml/xml.c index c670c2ef52e12..02a4f877c7941 100644 --- a/ext/xml/xml.c +++ b/ext/xml/xml.c @@ -1412,35 +1412,54 @@ PHP_FUNCTION(xml_parser_free) PHP_FUNCTION(xml_parser_set_option) { xml_parser *parser; - zval *pind, *val; - zend_long opt; + zval *pind; + zend_long opt, val_long; + zend_string *val_str; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "Olz", &pind, xml_parser_ce, &opt, &val) == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_START(3, 3) + Z_PARAM_OBJECT_OF_CLASS(pind, xml_parser_ce) + Z_PARAM_LONG(opt) + Z_PARAM_STR_OR_LONG(val_str, val_long) + ZEND_PARSE_PARAMETERS_END(); parser = Z_XMLPARSER_P(pind); switch (opt) { case PHP_XML_OPTION_CASE_FOLDING: - parser->case_folding = zval_get_long(val); + if (val_str) { + zend_argument_type_error(3, "must be of type int for the chosen option"); + RETURN_THROWS(); + } + + parser->case_folding = val_long; break; case PHP_XML_OPTION_SKIP_TAGSTART: - parser->toffset = zval_get_long(val); + if (val_str) { + zend_argument_type_error(3, "must be of type int for the chosen option"); + RETURN_THROWS(); + } + + parser->toffset = val_long; if (parser->toffset < 0) { - php_error_docref(NULL, E_NOTICE, "tagstart ignored, because it is out of range"); + php_error_docref(NULL, E_WARNING, "tagstart ignored, because it is out of range"); parser->toffset = 0; } break; case PHP_XML_OPTION_SKIP_WHITE: - parser->skipwhite = zval_get_long(val); + if (val_str) { + zend_argument_type_error(3, "must be of type int for the chosen option"); + RETURN_THROWS(); + } + + parser->skipwhite = val_long; break; case PHP_XML_OPTION_TARGET_ENCODING: { const xml_encoding *enc; - if (!try_convert_to_string(val)) { + if (!val_str) { + zend_argument_type_error(3, "must be of type string for the chosen option"); RETURN_THROWS(); } - enc = xml_get_encoding((XML_Char*)Z_STRVAL_P(val)); + enc = xml_get_encoding((XML_Char*) ZSTR_VAL(val_str)); if (enc == NULL) { zend_argument_value_error(3, "is not a supported target encoding"); RETURN_THROWS(); diff --git a/ext/xml/xml.stub.php b/ext/xml/xml.stub.php index 5f90d91fe4655..6e89f330720a7 100644 --- a/ext/xml/xml.stub.php +++ b/ext/xml/xml.stub.php @@ -58,8 +58,7 @@ function xml_get_current_byte_index(XmlParser $parser): int {} function xml_parser_free(XmlParser $parser): bool {} -/** @param string|int $value */ -function xml_parser_set_option(XmlParser $parser, int $option, $value): bool {} +function xml_parser_set_option(XmlParser $parser, int $option, string|int $value): bool {} function xml_parser_get_option(XmlParser $parser, int $option): string|int {} diff --git a/ext/xml/xml_arginfo.h b/ext/xml/xml_arginfo.h index ea17fca77d8ec..47037060391d2 100644 --- a/ext/xml/xml_arginfo.h +++ b/ext/xml/xml_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: b3c718c2aeba9a9c05b6cb281fd7ccaa3791d34e */ + * Stub hash: adc99bbb801c9b3ebd69e8967f7a2f74782763aa */ ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_xml_parser_create, 0, 0, XmlParser, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, encoding, IS_STRING, 1, "null") @@ -74,7 +74,7 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_xml_parser_set_option, 0, 3, _IS_BOOL, 0) ZEND_ARG_OBJ_INFO(0, parser, XmlParser, 0) ZEND_ARG_TYPE_INFO(0, option, IS_LONG, 0) - ZEND_ARG_INFO(0, value) + ZEND_ARG_TYPE_MASK(0, value, MAY_BE_STRING|MAY_BE_LONG, NULL) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_xml_parser_get_option, 0, 2, MAY_BE_STRING|MAY_BE_LONG) diff --git a/ext/xsl/php_xsl.stub.php b/ext/xsl/php_xsl.stub.php index 9e79c9c63489c..04cad46cbe8cc 100644 --- a/ext/xsl/php_xsl.stub.php +++ b/ext/xsl/php_xsl.stub.php @@ -25,11 +25,8 @@ public function transformToUri(object $document, string $uri) {} */ public function transformToXml(object $document) {} - /** - * @param string|array $name - * @return bool - */ - public function setParameter(string $namespace, $name, string $value = UNKNOWN) {} + /** @return bool */ + public function setParameter(string $namespace, array|string $name, ?string $value = null) {} /** @return string|false */ public function getParameter(string $namespace, string $name) {} @@ -40,11 +37,8 @@ public function removeParameter(string $namespace, string $name) {} /** @return bool */ public function hasExsltSupport() {} - /** - * @param string|array|null $restrict - * @return void - */ - public function registerPHPFunctions($restrict = null) {} + /** @return void */ + public function registerPHPFunctions(array|string|null $restrict = null) {} /** @return bool */ public function setProfiling(?string $filename) {} diff --git a/ext/xsl/php_xsl_arginfo.h b/ext/xsl/php_xsl_arginfo.h index d707c72a7dba6..a776dded68695 100644 --- a/ext/xsl/php_xsl_arginfo.h +++ b/ext/xsl/php_xsl_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 13fd80938fec3bea7ac4bbcfb6e0b69b230fba72 */ + * Stub hash: 4a3997bafb6c17714ee94443837be2d2842386e2 */ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_XSLTProcessor_importStylesheet, 0, 0, 1) ZEND_ARG_TYPE_INFO(0, stylesheet, IS_OBJECT, 0) @@ -21,8 +21,8 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_class_XSLTProcessor_setParameter, 0, 0, 2) ZEND_ARG_TYPE_INFO(0, namespace, IS_STRING, 0) - ZEND_ARG_INFO(0, name) - ZEND_ARG_TYPE_INFO(0, value, IS_STRING, 0) + ZEND_ARG_TYPE_MASK(0, name, MAY_BE_ARRAY|MAY_BE_STRING, NULL) + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, value, IS_STRING, 1, "null") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_class_XSLTProcessor_getParameter, 0, 0, 2) @@ -36,7 +36,7 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_XSLTProcessor_hasExsltSupport, 0, 0, 0) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_class_XSLTProcessor_registerPHPFunctions, 0, 0, 0) - ZEND_ARG_INFO_WITH_DEFAULT_VALUE(0, restrict, "null") + ZEND_ARG_TYPE_MASK(0, restrict, MAY_BE_ARRAY|MAY_BE_STRING|MAY_BE_NULL, "null") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_class_XSLTProcessor_setProfiling, 0, 0, 1) diff --git a/ext/xsl/xsltprocessor.c b/ext/xsl/xsltprocessor.c index 29b3ff5fb34e2..26edbb9045668 100644 --- a/ext/xsl/xsltprocessor.c +++ b/ext/xsl/xsltprocessor.c @@ -666,21 +666,35 @@ PHP_METHOD(XSLTProcessor, setParameter) { zval *id = ZEND_THIS; - zval *array_value, *entry, new_string; + zval *entry, new_string; + HashTable *array_value; xsl_object *intern; char *namespace; size_t namespace_len; - zend_string *string_key, *name, *value; + zend_string *string_key, *name, *value = NULL; + + ZEND_PARSE_PARAMETERS_START(2, 3) + Z_PARAM_STRING(namespace, namespace_len) + Z_PARAM_STR_OR_ARRAY_HT(name, array_value) + Z_PARAM_OPTIONAL + Z_PARAM_STR_OR_NULL(value) + ZEND_PARSE_PARAMETERS_END(); + + intern = Z_XSL_P(id); + + if (array_value) { + if (value) { + zend_argument_value_error(3, "must be null when argument #2 ($name) is an array"); + RETURN_THROWS(); + } - if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "sa", &namespace, &namespace_len, &array_value) == SUCCESS) { - intern = Z_XSL_P(id); - ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(array_value), string_key, entry) { + ZEND_HASH_FOREACH_STR_KEY_VAL(array_value, string_key, entry) { zval tmp; zend_string *str; if (string_key == NULL) { - php_error_docref(NULL, E_WARNING, "Invalid parameter array"); - RETURN_FALSE; + zend_argument_type_error(2, "must contain only string keys"); + RETURN_THROWS(); } str = zval_try_get_string(entry); if (UNEXPECTED(!str)) { @@ -690,18 +704,17 @@ PHP_METHOD(XSLTProcessor, setParameter) zend_hash_update(intern->parameter, string_key, &tmp); } ZEND_HASH_FOREACH_END(); RETURN_TRUE; - } else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "sSS", &namespace, &namespace_len, &name, &value) == SUCCESS) { - - intern = Z_XSL_P(id); + } else { + if (!value) { + zend_argument_value_error(3, "cannot be null when argument #2 ($name) is a string"); + RETURN_THROWS(); + } ZVAL_STR_COPY(&new_string, value); zend_hash_update(intern->parameter, name, &new_string); RETURN_TRUE; - } else { - WRONG_PARAM_COUNT; } - } /* }}} end XSLTProcessor::setParameter */ diff --git a/ext/zip/php_zip.c b/ext/zip/php_zip.c index c1a569afec4a7..6ebbc42858da1 100644 --- a/ext/zip/php_zip.c +++ b/ext/zip/php_zip.c @@ -2712,16 +2712,20 @@ PHP_METHOD(ZipArchive, extractTo) struct zip *intern; zval *self = ZEND_THIS; - zval *zval_files = NULL; + zend_string *files_str = NULL; + HashTable *files_ht = NULL; + zval *zval_file = NULL; php_stream_statbuf ssb; char *pathto; size_t pathto_len; int ret; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "p|z", &pathto, &pathto_len, &zval_files) == FAILURE) { - RETURN_THROWS(); - } + ZEND_PARSE_PARAMETERS_START(1, 2) + Z_PARAM_PATH(pathto, pathto_len) + Z_PARAM_OPTIONAL + Z_PARAM_STR_OR_ARRAY_HT_OR_NULL(files_str, files_ht) + ZEND_PARSE_PARAMETERS_END(); ZIP_FROM_OBJECT(intern, self); @@ -2736,37 +2740,29 @@ PHP_METHOD(ZipArchive, extractTo) } } - if (zval_files && Z_TYPE_P(zval_files) != IS_NULL) { - uint32_t nelems, i; + uint32_t nelems, i; - switch (Z_TYPE_P(zval_files)) { - case IS_STRING: - if (!php_zip_extract_file(intern, pathto, Z_STRVAL_P(zval_files), Z_STRLEN_P(zval_files))) { - RETURN_FALSE; - } - break; - case IS_ARRAY: - nelems = zend_hash_num_elements(Z_ARRVAL_P(zval_files)); - if (nelems == 0 ) { - RETURN_FALSE; - } - for (i = 0; i < nelems; i++) { - if ((zval_file = zend_hash_index_find(Z_ARRVAL_P(zval_files), i)) != NULL) { - switch (Z_TYPE_P(zval_file)) { - case IS_LONG: - break; - case IS_STRING: - if (!php_zip_extract_file(intern, pathto, Z_STRVAL_P(zval_file), Z_STRLEN_P(zval_file))) { - RETURN_FALSE; - } - break; + if (files_str) { + if (!php_zip_extract_file(intern, pathto, ZSTR_VAL(files_str), ZSTR_LEN(files_str))) { + RETURN_FALSE; + } + } else if (files_ht) { + nelems = zend_hash_num_elements(files_ht); + if (nelems == 0 ) { + RETURN_FALSE; + } + for (i = 0; i < nelems; i++) { + if ((zval_file = zend_hash_index_find(files_ht, i)) != NULL) { + switch (Z_TYPE_P(zval_file)) { + case IS_LONG: + break; + case IS_STRING: + if (!php_zip_extract_file(intern, pathto, Z_STRVAL_P(zval_file), Z_STRLEN_P(zval_file))) { + RETURN_FALSE; } - } + break; } - break; - default: - zend_argument_type_error(2, "must be of type array|string|null, %s given", zend_zval_type_name(zval_files)); - RETURN_THROWS(); + } } } else { /* Extract all files */ @@ -2784,6 +2780,7 @@ PHP_METHOD(ZipArchive, extractTo) } } } + RETURN_TRUE; } /* }}} */ diff --git a/ext/zip/php_zip.stub.php b/ext/zip/php_zip.stub.php index 01f055f0ab4ba..cde266261d640 100644 --- a/ext/zip/php_zip.stub.php +++ b/ext/zip/php_zip.stub.php @@ -161,11 +161,8 @@ public function unchangeIndex(int $index) {} /** @return bool */ public function unchangeName(string $name) {} - /** - * @param array|string|null $files - * @return bool - */ - public function extractTo(string $pathto, $files = null) {} + /** @return bool */ + public function extractTo(string $pathto, array|string|null $files = null) {} /** @return string|false */ public function getFromName(string $entryname, int $len = 0, int $flags = 0) {} diff --git a/ext/zip/php_zip_arginfo.h b/ext/zip/php_zip_arginfo.h index 87222c9e08075..c9f90d57f9873 100644 --- a/ext/zip/php_zip_arginfo.h +++ b/ext/zip/php_zip_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 880148896a71ad9bd076bb42c735ff1b83cd0731 */ + * Stub hash: 49f168c537e48f8a3998d67812a5e2e6a2463533 */ ZEND_BEGIN_ARG_INFO_EX(arginfo_zip_open, 0, 0, 1) ZEND_ARG_TYPE_INFO(0, filename, IS_STRING, 0) @@ -175,7 +175,7 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_class_ZipArchive_extractTo, 0, 0, 1) ZEND_ARG_TYPE_INFO(0, pathto, IS_STRING, 0) - ZEND_ARG_INFO_WITH_DEFAULT_VALUE(0, files, "null") + ZEND_ARG_TYPE_MASK(0, files, MAY_BE_ARRAY|MAY_BE_STRING|MAY_BE_NULL, "null") ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_class_ZipArchive_getFromName, 0, 0, 1) From a5e4764a63934f6f27c51d6637878824884e5ecf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1t=C3=A9=20Kocsis?= Date: Mon, 24 Aug 2020 23:49:15 +0200 Subject: [PATCH 2/4] Fix tests --- ext/mysqli/mysqli_api.c | 2 +- ext/mysqli/tests/mysqli_options.phpt | 11 +++++++---- ext/odbc/php_odbc.c | 11 ++--------- ext/xml/tests/bug72714.phpt | 3 ++- .../tests/xml_parser_set_option_variation3.phpt | 13 ++++++++----- .../xsltprocessor_setparameter-nostring.phpt | 17 ++++++++++------- 6 files changed, 30 insertions(+), 27 deletions(-) diff --git a/ext/mysqli/mysqli_api.c b/ext/mysqli/mysqli_api.c index 6790302091b5b..b9ec07280fb53 100644 --- a/ext/mysqli/mysqli_api.c +++ b/ext/mysqli/mysqli_api.c @@ -1717,7 +1717,7 @@ PHP_FUNCTION(mysqli_options) RETURN_THROWS(); } ret = mysql_options(mysql->mysql, mysql_option, (char *) &mysql_value_long); - } else if (expected_type == IS_NULL) { + } else { ret = 1; } diff --git a/ext/mysqli/tests/mysqli_options.phpt b/ext/mysqli/tests/mysqli_options.phpt index bec663a64a72c..310fc936d0d00 100644 --- a/ext/mysqli/tests/mysqli_options.phpt +++ b/ext/mysqli/tests/mysqli_options.phpt @@ -38,7 +38,12 @@ require_once('skipifconnectfailure.inc'); var_dump("MYSQLI_READ_DEFAULT_FILE", mysqli_options($link, MYSQLI_READ_DEFAULT_FILE, 'extra_my.cnf')); var_dump("MYSQLI_OPT_CONNECT_TIMEOUT", mysqli_options($link, MYSQLI_OPT_CONNECT_TIMEOUT, 10)); var_dump("MYSQLI_OPT_LOCAL_INFILE", mysqli_options($link, MYSQLI_OPT_LOCAL_INFILE, 1)); - var_dump("MYSQLI_INIT_COMMAND", mysqli_options($link, MYSQLI_INIT_COMMAND, array('SET AUTOCOMMIT=0', 'SET AUTOCOMMIT=1'))); + try { + var_dump("MYSQLI_INIT_COMMAND"); + mysqli_options($link, MYSQLI_INIT_COMMAND, array('SET AUTOCOMMIT=0', 'SET AUTOCOMMIT=1')); + } catch (TypeError $exception) { + echo $exception->getMessage() . "\n"; + } if (!$link2 = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) printf("[006] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n", @@ -106,10 +111,8 @@ bool(true) bool(true) %s(23) "MYSQLI_OPT_LOCAL_INFILE" bool(true) - -Warning: Array to string conversion in %s on line %d %s(19) "MYSQLI_INIT_COMMAND" -bool(true) +mysqli_options(): Argument #3 ($value) must be of type string|int, array given %s(25) "MYSQLI_READ_DEFAULT_GROUP" bool(true) %s(24) "MYSQLI_READ_DEFAULT_FILE" diff --git a/ext/odbc/php_odbc.c b/ext/odbc/php_odbc.c index c96aab82e791d..af62ecb29dada 100644 --- a/ext/odbc/php_odbc.c +++ b/ext/odbc/php_odbc.c @@ -1752,7 +1752,7 @@ PHP_FUNCTION(odbc_result) ZEND_PARSE_PARAMETERS_START(2, 2) Z_PARAM_RESOURCE(pv_res) - Z_PARAM_STR_OR_LONG(pv_field_str, pv_field_ind) + Z_PARAM_STR_OR_LONG(pv_field_str, pv_field_long) ZEND_PARSE_PARAMETERS_END(); if (pv_field_str) { @@ -1760,14 +1760,7 @@ PHP_FUNCTION(odbc_result) field_ind = -1; } else { field = NULL; - field_ind = pv_field_long - 1; - } - - if (Z_TYPE_P(pv_field) == IS_STRING) { - field = Z_STRVAL_P(pv_field); - } else { - convert_to_long_ex(pv_field); - field_ind = Z_LVAL_P(pv_field) - 1; + field_ind = (int) pv_field_long - 1; } if ((result = (odbc_result *)zend_fetch_resource(Z_RES_P(pv_res), "ODBC result", le_result)) == NULL) { diff --git a/ext/xml/tests/bug72714.phpt b/ext/xml/tests/bug72714.phpt index 53b923904534d..1c5a724e566b9 100644 --- a/ext/xml/tests/bug72714.phpt +++ b/ext/xml/tests/bug72714.phpt @@ -3,6 +3,7 @@ Bug #72714 (_xml_startElementHandler() segmentation fault) --SKIPIF-- --FILE-- --EXPECTF-- -Notice: xml_parser_set_option(): tagstart ignored, because it is out of range in %s%ebug72714.php on line %d +Warning: xml_parser_set_option(): tagstart ignored, because it is out of range in %s on line %d string(9) "NS1:TOTAL" string(0) "" diff --git a/ext/xml/tests/xml_parser_set_option_variation3.phpt b/ext/xml/tests/xml_parser_set_option_variation3.phpt index 167050e3d4462..fba584da1ceca 100644 --- a/ext/xml/tests/xml_parser_set_option_variation3.phpt +++ b/ext/xml/tests/xml_parser_set_option_variation3.phpt @@ -5,6 +5,9 @@ Test xml_parser_set_option() function : usage variations if (!extension_loaded("xml")) { print "skip - XML extension not loaded"; } +if (PHP_INT_SIZE != 8) { + die('skip 64-bit only'); +} ?> --FILE-- --FILE-- importStylesheet($xsl); -var_dump($proc->setParameter('', array(4, 'abc'))); +try { + $proc->setParameter('', array(4, 'abc')); +} catch (TypeError $exception) { + echo $exception->getMessage() . "\n"; +} $proc->transformToXml($dom); ?> ---EXPECTF-- -Warning: XSLTProcessor::setParameter(): Invalid parameter array in %s on line %d -bool(false) +--EXPECT-- +XSLTProcessor::setParameter(): Argument #2 ($name) must contain only string keys --CREDITS-- Christian Weiske, cweiske@php.net PHP Testfest Berlin 2009-05-09 From 0ff1d89e395325526992268db9b1bad7ec9145f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1t=C3=A9=20Kocsis?= Date: Thu, 27 Aug 2020 11:09:18 +0200 Subject: [PATCH 3/4] Address code review --- Zend/zend_operators.c | 2 +- ext/mysqli/mysqli_api.c | 22 ++++++++++++++++++---- 2 files changed, 19 insertions(+), 5 deletions(-) diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c index 4d20d564648a2..e126f784cfead 100644 --- a/Zend/zend_operators.c +++ b/Zend/zend_operators.c @@ -816,7 +816,7 @@ ZEND_API zend_long ZEND_FASTCALL zval_get_long_func(zval *op) /* {{{ */ } else { /* Previously we used strtol here, not is_numeric_string, * and strtol gives you LONG_MAX/_MIN on overflow. - * We use use saturating conversion to emulate strtol()'s + * We use saturating conversion to emulate strtol()'s * behaviour. */ return zend_dval_to_lval_cap(dval); diff --git a/ext/mysqli/mysqli_api.c b/ext/mysqli/mysqli_api.c index b9ec07280fb53..0eb441860a5fb 100644 --- a/ext/mysqli/mysqli_api.c +++ b/ext/mysqli/mysqli_api.c @@ -1706,15 +1706,29 @@ PHP_FUNCTION(mysqli_options) #endif expected_type = mysqli_options_get_option_zval_type(mysql_option); if (expected_type == IS_STRING) { + bool is_long_arg = 0; if (!mysql_value_str) { - zend_argument_type_error(3, "must be of type string for the chosen option"); - RETURN_THROWS(); + mysql_value_str = zend_long_to_str(mysql_value_long); + is_long_arg = 1; } ret = mysql_options(mysql->mysql, mysql_option, ZSTR_VAL(mysql_value_str)); + + if (is_long_arg) { + zend_string_release(mysql_value_str); + } } else if (expected_type == IS_LONG) { if (mysql_value_str) { - zend_argument_type_error(3, "must be of type int for the chosen option"); - RETURN_THROWS(); + double rv; + zend_long lv; + zend_uchar type; + + type = is_numeric_string(ZSTR_VAL(mysql_value_str), ZSTR_LEN(mysql_value_str), &lv, &rv, 0); + if (type == IS_LONG) { + mysql_value_long = lv; + } else { + zend_argument_type_error(getThis() ? 1 : 2, "must be a numeric string for the chosen option"); + RETURN_THROWS(); + } } ret = mysql_options(mysql->mysql, mysql_option, (char *) &mysql_value_long); } else { From 8b07b3e344b689da30a476eb52c29bcd44a0e76f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A1t=C3=A9=20Kocsis?= Date: Tue, 1 Sep 2020 17:29:52 +0200 Subject: [PATCH 4/4] Revert too strict string|int changes --- ext/mysqli/mysqli.stub.php | 16 +++-- ext/mysqli/mysqli_api.c | 71 ++++++++----------- ext/mysqli/mysqli_arginfo.h | 6 +- ext/mysqli/tests/mysqli_options.phpt | 11 ++- ext/xml/tests/bug72714.phpt | 1 - .../xml_parser_set_option_variation3.phpt | 35 ++++----- ext/xml/xml.c | 40 +++-------- ext/xml/xml.stub.php | 3 +- ext/xml/xml_arginfo.h | 4 +- 9 files changed, 77 insertions(+), 110 deletions(-) diff --git a/ext/mysqli/mysqli.stub.php b/ext/mysqli/mysqli.stub.php index 30b8403354501..940f3c4fcc749 100644 --- a/ext/mysqli/mysqli.stub.php +++ b/ext/mysqli/mysqli.stub.php @@ -237,16 +237,18 @@ public function select_db(string $database) {} public function set_charset(string $charset) {} /** + * @param string|int $value * @return bool * @alias mysqli_options */ - public function options(int $option, string|int $value) {} + public function options(int $option, $value) {} /** + * @param string|int $value * @return bool * @alias mysqli_options */ - public function set_opt(int $option, string|int $value) {} + public function set_opt(int $option, $value) {} /** * @return bool @@ -628,7 +630,8 @@ function mysqli_num_fields(mysqli_result $mysql_result): int {} function mysqli_num_rows(mysqli_result $mysqli_result): int|string {} -function mysqli_options(mysqli $mysqli_link, int $option, string|int $value): bool {} +/** @param string|int $value */ +function mysqli_options(mysqli $mysqli_link, int $option, $value): bool {} function mysqli_ping(mysqli $mysqli_link): bool {} @@ -749,5 +752,8 @@ function mysqli_refresh(mysqli $mysqli_link, int $options): bool {} /** @alias mysqli_real_escape_string */ function mysqli_escape_string(mysqli $mysqli_link, string $string_to_escape): string {} -/** @alias mysqli_options */ -function mysqli_set_opt(mysqli $mysqli_link, int $option, string|int $value): bool {} +/** + * @param string|int $value + * @alias mysqli_options + */ +function mysqli_set_opt(mysqli $mysqli_link, int $option, $value): bool {} diff --git a/ext/mysqli/mysqli_api.c b/ext/mysqli/mysqli_api.c index 0eb441860a5fb..3f89e838fd894 100644 --- a/ext/mysqli/mysqli_api.c +++ b/ext/mysqli/mysqli_api.c @@ -1675,26 +1675,16 @@ static int mysqli_options_get_option_zval_type(int option) PHP_FUNCTION(mysqli_options) { MY_MYSQL *mysql; - zval *mysql_link = getThis(); - zend_string *mysql_value_str; - zend_long mysql_value_long; + zval *mysql_link = NULL; + zval *mysql_value; zend_long mysql_option; + unsigned int l_value; zend_long ret; int expected_type; - if (mysql_link) { - ZEND_PARSE_PARAMETERS_START(2, 2) - Z_PARAM_LONG(mysql_option) - Z_PARAM_STR_OR_LONG(mysql_value_str, mysql_value_long) - ZEND_PARSE_PARAMETERS_END(); - } else { - ZEND_PARSE_PARAMETERS_START(3, 3) - Z_PARAM_OBJECT_OF_CLASS(mysql_link, mysqli_link_class_entry) - Z_PARAM_LONG(mysql_option) - Z_PARAM_STR_OR_LONG(mysql_value_str, mysql_value_long) - ZEND_PARSE_PARAMETERS_END(); + if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Olz", &mysql_link, mysqli_link_class_entry, &mysql_option, &mysql_value) == FAILURE) { + RETURN_THROWS(); } - MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_INITIALIZED); #ifndef MYSQLI_USE_MYSQLND @@ -1705,34 +1695,31 @@ PHP_FUNCTION(mysqli_options) } #endif expected_type = mysqli_options_get_option_zval_type(mysql_option); - if (expected_type == IS_STRING) { - bool is_long_arg = 0; - if (!mysql_value_str) { - mysql_value_str = zend_long_to_str(mysql_value_long); - is_long_arg = 1; - } - ret = mysql_options(mysql->mysql, mysql_option, ZSTR_VAL(mysql_value_str)); - - if (is_long_arg) { - zend_string_release(mysql_value_str); - } - } else if (expected_type == IS_LONG) { - if (mysql_value_str) { - double rv; - zend_long lv; - zend_uchar type; - - type = is_numeric_string(ZSTR_VAL(mysql_value_str), ZSTR_LEN(mysql_value_str), &lv, &rv, 0); - if (type == IS_LONG) { - mysql_value_long = lv; - } else { - zend_argument_type_error(getThis() ? 1 : 2, "must be a numeric string for the chosen option"); - RETURN_THROWS(); - } + if (expected_type != Z_TYPE_P(mysql_value)) { + switch (expected_type) { + case IS_STRING: + if (!try_convert_to_string(mysql_value)) { + RETURN_THROWS(); + } + break; + case IS_LONG: + convert_to_long_ex(mysql_value); + break; + default: + break; } - ret = mysql_options(mysql->mysql, mysql_option, (char *) &mysql_value_long); - } else { - ret = 1; + } + switch (expected_type) { + case IS_STRING: + ret = mysql_options(mysql->mysql, mysql_option, Z_STRVAL_P(mysql_value)); + break; + case IS_LONG: + l_value = Z_LVAL_P(mysql_value); + ret = mysql_options(mysql->mysql, mysql_option, (char *)&l_value); + break; + default: + ret = 1; + break; } RETURN_BOOL(!ret); diff --git a/ext/mysqli/mysqli_arginfo.h b/ext/mysqli/mysqli_arginfo.h index bd692c0ae51b0..7d7c69e943919 100644 --- a/ext/mysqli/mysqli_arginfo.h +++ b/ext/mysqli/mysqli_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: 5695d494cc9a1f780e65c525c47e047780bf80f1 */ + * Stub hash: a8626c7c42e4d117b08df7f42a7523f60f357b82 */ 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_link, mysqli, 0) @@ -208,7 +208,7 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_mysqli_options, 0, 3, _IS_BOOL, 0) ZEND_ARG_OBJ_INFO(0, mysqli_link, mysqli, 0) ZEND_ARG_TYPE_INFO(0, option, IS_LONG, 0) - ZEND_ARG_TYPE_MASK(0, value, MAY_BE_STRING|MAY_BE_LONG, NULL) + ZEND_ARG_INFO(0, value) ZEND_END_ARG_INFO() #define arginfo_mysqli_ping arginfo_mysqli_more_results @@ -545,7 +545,7 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_class_mysqli_options, 0, 0, 2) ZEND_ARG_TYPE_INFO(0, option, IS_LONG, 0) - ZEND_ARG_TYPE_MASK(0, value, MAY_BE_STRING|MAY_BE_LONG, NULL) + ZEND_ARG_INFO(0, value) ZEND_END_ARG_INFO() #define arginfo_class_mysqli_set_opt arginfo_class_mysqli_options diff --git a/ext/mysqli/tests/mysqli_options.phpt b/ext/mysqli/tests/mysqli_options.phpt index 310fc936d0d00..bec663a64a72c 100644 --- a/ext/mysqli/tests/mysqli_options.phpt +++ b/ext/mysqli/tests/mysqli_options.phpt @@ -38,12 +38,7 @@ require_once('skipifconnectfailure.inc'); var_dump("MYSQLI_READ_DEFAULT_FILE", mysqli_options($link, MYSQLI_READ_DEFAULT_FILE, 'extra_my.cnf')); var_dump("MYSQLI_OPT_CONNECT_TIMEOUT", mysqli_options($link, MYSQLI_OPT_CONNECT_TIMEOUT, 10)); var_dump("MYSQLI_OPT_LOCAL_INFILE", mysqli_options($link, MYSQLI_OPT_LOCAL_INFILE, 1)); - try { - var_dump("MYSQLI_INIT_COMMAND"); - mysqli_options($link, MYSQLI_INIT_COMMAND, array('SET AUTOCOMMIT=0', 'SET AUTOCOMMIT=1')); - } catch (TypeError $exception) { - echo $exception->getMessage() . "\n"; - } + var_dump("MYSQLI_INIT_COMMAND", mysqli_options($link, MYSQLI_INIT_COMMAND, array('SET AUTOCOMMIT=0', 'SET AUTOCOMMIT=1'))); if (!$link2 = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) printf("[006] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n", @@ -111,8 +106,10 @@ bool(true) bool(true) %s(23) "MYSQLI_OPT_LOCAL_INFILE" bool(true) + +Warning: Array to string conversion in %s on line %d %s(19) "MYSQLI_INIT_COMMAND" -mysqli_options(): Argument #3 ($value) must be of type string|int, array given +bool(true) %s(25) "MYSQLI_READ_DEFAULT_GROUP" bool(true) %s(24) "MYSQLI_READ_DEFAULT_FILE" diff --git a/ext/xml/tests/bug72714.phpt b/ext/xml/tests/bug72714.phpt index 1c5a724e566b9..08fff0c06b16b 100644 --- a/ext/xml/tests/bug72714.phpt +++ b/ext/xml/tests/bug72714.phpt @@ -3,7 +3,6 @@ Bug #72714 (_xml_startElementHandler() segmentation fault) --SKIPIF-- --FILE-- --FILE-- getMessage() . "\n"; - } + echo @"\nArg value $value \n"; + var_dump(xml_parser_set_option($parser, $option, $value)); } fclose($fp); @@ -123,19 +116,19 @@ Arg value 0.5 bool(true) Arg value Array -xml_parser_set_option(): Argument #3 ($value) must be of type string|int, array given +bool(true) Arg value Array -xml_parser_set_option(): Argument #3 ($value) must be of type string|int, array given +bool(true) Arg value Array -xml_parser_set_option(): Argument #3 ($value) must be of type string|int, array given +bool(true) Arg value Array -xml_parser_set_option(): Argument #3 ($value) must be of type string|int, array given +bool(true) Arg value Array -xml_parser_set_option(): Argument #3 ($value) must be of type string|int, array given +bool(true) Arg value bool(true) @@ -156,20 +149,22 @@ Arg value bool(true) Arg value -xml_parser_set_option(): Argument #3 ($value) must be of type int for the chosen option +bool(true) Arg value -xml_parser_set_option(): Argument #3 ($value) must be of type int for the chosen option +bool(true) Arg value string -xml_parser_set_option(): Argument #3 ($value) must be of type int for the chosen option +bool(true) Arg value string -xml_parser_set_option(): Argument #3 ($value) must be of type int for the chosen option +bool(true) Arg value Some Ascii Data -xml_parser_set_option(): Argument #3 ($value) must be of type int for the chosen option + +Notice: Object of class aClass could not be converted to int in %s on line %d +bool(true) Arg value Resource id %s -xml_parser_set_option(): Argument #3 ($value) must be of type string|int, resource given +bool(true) Done diff --git a/ext/xml/xml.c b/ext/xml/xml.c index 02a4f877c7941..00f8798ad0875 100644 --- a/ext/xml/xml.c +++ b/ext/xml/xml.c @@ -1412,58 +1412,40 @@ PHP_FUNCTION(xml_parser_free) PHP_FUNCTION(xml_parser_set_option) { xml_parser *parser; - zval *pind; - zend_long opt, val_long; - zend_string *val_str; + zval *pind, *val; + zend_long opt; - ZEND_PARSE_PARAMETERS_START(3, 3) - Z_PARAM_OBJECT_OF_CLASS(pind, xml_parser_ce) - Z_PARAM_LONG(opt) - Z_PARAM_STR_OR_LONG(val_str, val_long) - ZEND_PARSE_PARAMETERS_END(); + if (zend_parse_parameters(ZEND_NUM_ARGS(), "Olz", &pind, xml_parser_ce, &opt, &val) == FAILURE) { + RETURN_THROWS(); + } parser = Z_XMLPARSER_P(pind); switch (opt) { case PHP_XML_OPTION_CASE_FOLDING: - if (val_str) { - zend_argument_type_error(3, "must be of type int for the chosen option"); - RETURN_THROWS(); - } - - parser->case_folding = val_long; + parser->case_folding = zval_get_long(val); break; case PHP_XML_OPTION_SKIP_TAGSTART: - if (val_str) { - zend_argument_type_error(3, "must be of type int for the chosen option"); - RETURN_THROWS(); - } - - parser->toffset = val_long; + parser->toffset = zval_get_long(val); if (parser->toffset < 0) { php_error_docref(NULL, E_WARNING, "tagstart ignored, because it is out of range"); parser->toffset = 0; } break; case PHP_XML_OPTION_SKIP_WHITE: - if (val_str) { - zend_argument_type_error(3, "must be of type int for the chosen option"); - RETURN_THROWS(); - } - - parser->skipwhite = val_long; + parser->skipwhite = zval_get_long(val); break; case PHP_XML_OPTION_TARGET_ENCODING: { const xml_encoding *enc; - if (!val_str) { - zend_argument_type_error(3, "must be of type string for the chosen option"); + if (!try_convert_to_string(val)) { RETURN_THROWS(); } - enc = xml_get_encoding((XML_Char*) ZSTR_VAL(val_str)); + enc = xml_get_encoding((XML_Char*)Z_STRVAL_P(val)); if (enc == NULL) { zend_argument_value_error(3, "is not a supported target encoding"); RETURN_THROWS(); } + parser->target_encoding = enc->name; break; } diff --git a/ext/xml/xml.stub.php b/ext/xml/xml.stub.php index 6e89f330720a7..5f90d91fe4655 100644 --- a/ext/xml/xml.stub.php +++ b/ext/xml/xml.stub.php @@ -58,7 +58,8 @@ function xml_get_current_byte_index(XmlParser $parser): int {} function xml_parser_free(XmlParser $parser): bool {} -function xml_parser_set_option(XmlParser $parser, int $option, string|int $value): bool {} +/** @param string|int $value */ +function xml_parser_set_option(XmlParser $parser, int $option, $value): bool {} function xml_parser_get_option(XmlParser $parser, int $option): string|int {} diff --git a/ext/xml/xml_arginfo.h b/ext/xml/xml_arginfo.h index 47037060391d2..ea17fca77d8ec 100644 --- a/ext/xml/xml_arginfo.h +++ b/ext/xml/xml_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit the .stub.php file instead. - * Stub hash: adc99bbb801c9b3ebd69e8967f7a2f74782763aa */ + * Stub hash: b3c718c2aeba9a9c05b6cb281fd7ccaa3791d34e */ ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_xml_parser_create, 0, 0, XmlParser, 0) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, encoding, IS_STRING, 1, "null") @@ -74,7 +74,7 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_xml_parser_set_option, 0, 3, _IS_BOOL, 0) ZEND_ARG_OBJ_INFO(0, parser, XmlParser, 0) ZEND_ARG_TYPE_INFO(0, option, IS_LONG, 0) - ZEND_ARG_TYPE_MASK(0, value, MAY_BE_STRING|MAY_BE_LONG, NULL) + ZEND_ARG_INFO(0, value) ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_xml_parser_get_option, 0, 2, MAY_BE_STRING|MAY_BE_LONG)