From 2ab123b84e438458e1070e99cfdcdcd7174fabea Mon Sep 17 00:00:00 2001 From: =?utf8?q?M=C3=A1t=C3=A9=20Kocsis?= Date: Tue, 10 Dec 2019 00:03:02 +0100 Subject: [PATCH] Convert string|array union parameter types Closes GH-4995 --- ext/mbstring/mbstring.c | 2 +- ext/standard/basic_functions.stub.php | 8 +--- ext/standard/basic_functions_arginfo.h | 4 +- ext/standard/mail.c | 40 +++++++------------ ext/standard/php_mail.h | 2 +- ext/standard/string.c | 31 +++++++------- .../tests/strings/strtr_variation6.phpt | 22 +++++----- .../tests/strings/strtr_variation8.phpt | 36 ++++++++--------- 8 files changed, 63 insertions(+), 82 deletions(-) diff --git a/ext/mbstring/mbstring.c b/ext/mbstring/mbstring.c index 7f92aa2bd0..516d401094 100644 --- a/ext/mbstring/mbstring.c +++ b/ext/mbstring/mbstring.c @@ -3929,7 +3929,7 @@ PHP_FUNCTION(mb_send_mail) zend_string_release_ex(tmp_headers, 0); break; case IS_ARRAY: - str_headers = php_mail_build_headers(headers); + str_headers = php_mail_build_headers(Z_ARRVAL_P(headers)); break; default: php_error_docref(NULL, E_WARNING, "headers parameter must be string or array"); diff --git a/ext/standard/basic_functions.stub.php b/ext/standard/basic_functions.stub.php index db6dfb1c74..f2313ff831 100755 --- a/ext/standard/basic_functions.stub.php +++ b/ext/standard/basic_functions.stub.php @@ -586,10 +586,7 @@ function lcfirst(string $str): string {} function ucwords(string $str, string $delimiters = " \t\r\n\f\v"): string {} -/** - * @param string|array $from - */ -function strtr(string $str, $from, string $to = UNKNOWN): string {} +function strtr(string $str, string|array $from, string $to = UNKNOWN): string {} function strrev(string $str): string {} @@ -1015,8 +1012,7 @@ function link(string $target, string $link): bool {} /* mail.c */ -/** @param string|array $additional_headers */ -function mail(string $to, string $subject, string $message, $additional_headers = UNKNOWN, string $additional_parameters = ""): bool {} +function mail(string $to, string $subject, string $message, string|array $additional_headers = UNKNOWN, string $additional_parameters = ""): bool {} /* math.c */ diff --git a/ext/standard/basic_functions_arginfo.h b/ext/standard/basic_functions_arginfo.h index d3f0182bde..816e7c2427 100755 --- a/ext/standard/basic_functions_arginfo.h +++ b/ext/standard/basic_functions_arginfo.h @@ -934,7 +934,7 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_strtr, 0, 2, IS_STRING, 0) ZEND_ARG_TYPE_INFO(0, str, IS_STRING, 0) - ZEND_ARG_INFO(0, from) + ZEND_ARG_TYPE_MASK(0, from, MAY_BE_STRING|MAY_BE_ARRAY) ZEND_ARG_TYPE_INFO(0, to, IS_STRING, 0) ZEND_END_ARG_INFO() @@ -1575,7 +1575,7 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_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(0, additional_headers) + ZEND_ARG_TYPE_MASK(0, additional_headers, MAY_BE_STRING|MAY_BE_ARRAY) ZEND_ARG_TYPE_INFO(0, additional_parameters, IS_STRING, 0) ZEND_END_ARG_INFO() diff --git a/ext/standard/mail.c b/ext/standard/mail.c index b6f987d80f..9e7d9a5b3b 100644 --- a/ext/standard/mail.c +++ b/ext/standard/mail.c @@ -152,16 +152,14 @@ static void php_mail_build_headers_elems(smart_str *s, zend_string *key, zval *v } -PHPAPI zend_string *php_mail_build_headers(zval *headers) +PHPAPI zend_string *php_mail_build_headers(HashTable *headers) { zend_ulong idx; zend_string *key; zval *val; smart_str s = {0}; - ZEND_ASSERT(Z_TYPE_P(headers) == IS_ARRAY); - - ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(headers), idx, key, val) { + ZEND_HASH_FOREACH_KEY_VAL(headers, idx, key, val) { if (!key) { php_error_docref(NULL, E_WARNING, "Found numeric header (" ZEND_LONG_FMT ")", idx); continue; @@ -256,8 +254,9 @@ PHP_FUNCTION(mail) { char *to=NULL, *message=NULL; char *subject=NULL; - zend_string *extra_cmd=NULL, *str_headers=NULL, *tmp_headers; - zval *headers = NULL; + zend_string *extra_cmd=NULL; + zend_string *headers_str = NULL; + HashTable *headers_ht = NULL; size_t to_len, message_len; size_t subject_len, i; char *force_extra_parameters = INI_STR("mail.force_extra_parameters"); @@ -269,7 +268,7 @@ PHP_FUNCTION(mail) Z_PARAM_STRING(subject, subject_len) Z_PARAM_STRING(message, message_len) Z_PARAM_OPTIONAL - Z_PARAM_ZVAL(headers) + Z_PARAM_STR_OR_ARRAY_HT(headers_str, headers_ht) Z_PARAM_STR(extra_cmd) ZEND_PARSE_PARAMETERS_END(); @@ -277,22 +276,13 @@ PHP_FUNCTION(mail) MAIL_ASCIIZ_CHECK(to, to_len); MAIL_ASCIIZ_CHECK(subject, subject_len); MAIL_ASCIIZ_CHECK(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(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(headers); - break; - default: - php_error_docref(NULL, E_WARNING, "headers parameter must be string or array"); - RETURN_FALSE; - } + if (headers_str) { + MAIL_ASCIIZ_CHECK(ZSTR_VAL(headers_str), ZSTR_LEN(headers_str)); + headers_str = php_trim(headers_str, NULL, 0, 2); + } else if (headers_ht) { + headers_str = php_mail_build_headers(headers_ht); } + if (extra_cmd) { MAIL_ASCIIZ_CHECK(ZSTR_VAL(extra_cmd), ZSTR_LEN(extra_cmd)); } @@ -343,14 +333,14 @@ PHP_FUNCTION(mail) extra_cmd = php_escape_shell_cmd(ZSTR_VAL(extra_cmd)); } - if (php_mail(to_r, subject_r, message, str_headers ? ZSTR_VAL(str_headers) : NULL, extra_cmd ? ZSTR_VAL(extra_cmd) : NULL)) { + if (php_mail(to_r, subject_r, message, headers_str ? ZSTR_VAL(headers_str) : NULL, extra_cmd ? ZSTR_VAL(extra_cmd) : NULL)) { RETVAL_TRUE; } else { RETVAL_FALSE; } - if (str_headers) { - zend_string_release_ex(str_headers, 0); + if (headers_str) { + zend_string_release_ex(headers_str, 0); } if (extra_cmd) { diff --git a/ext/standard/php_mail.h b/ext/standard/php_mail.h index 0e226ba6a1..29fb5b77f4 100644 --- a/ext/standard/php_mail.h +++ b/ext/standard/php_mail.h @@ -21,7 +21,7 @@ PHP_FUNCTION(mail); PHP_MINFO_FUNCTION(mail); -PHPAPI zend_string *php_mail_build_headers(zval *headers); +PHPAPI zend_string *php_mail_build_headers(HashTable *headers); PHPAPI extern int php_mail(char *to, char *subject, char *message, char *headers, char *extra_cmd); #define PHP_MAIL_BUILD_HEADER_CHECK(target, s, key, val) \ diff --git a/ext/standard/string.c b/ext/standard/string.c index 72b8123d94..1bfbb7044b 100644 --- a/ext/standard/string.c +++ b/ext/standard/string.c @@ -3236,21 +3236,24 @@ PHPAPI zend_string *php_str_to_str(const char *haystack, size_t length, const ch Translates characters in str using given translation tables */ PHP_FUNCTION(strtr) { - zval *from; - zend_string *str; + zend_string *str, *from_str = NULL; + HashTable *from_ht = NULL; char *to = NULL; size_t to_len = 0; int ac = ZEND_NUM_ARGS(); ZEND_PARSE_PARAMETERS_START(2, 3) Z_PARAM_STR(str) - Z_PARAM_ZVAL(from) + Z_PARAM_STR_OR_ARRAY_HT(from_str, from_ht) Z_PARAM_OPTIONAL Z_PARAM_STRING(to, to_len) ZEND_PARSE_PARAMETERS_END(); - if (ac == 2 && Z_TYPE_P(from) != IS_ARRAY) { - zend_type_error("The second argument is not an array"); + if (ac == 2 && from_ht == NULL) { + zend_type_error("If two arguments are passed, the second argument must be an array"); + return; + } else if (ac != 2 && from_str == NULL) { + zend_type_error("If three arguments are passed, the second argument must be a string"); return; } @@ -3260,16 +3263,14 @@ PHP_FUNCTION(strtr) } if (ac == 2) { - HashTable *pats = Z_ARRVAL_P(from); - - if (zend_hash_num_elements(pats) < 1) { + if (zend_hash_num_elements(from_ht) < 1) { RETURN_STR_COPY(str); - } else if (zend_hash_num_elements(pats) == 1) { + } else if (zend_hash_num_elements(from_ht) == 1) { zend_long num_key; zend_string *str_key, *tmp_str, *replace, *tmp_replace; zval *entry; - ZEND_HASH_FOREACH_KEY_VAL(pats, num_key, str_key, entry) { + ZEND_HASH_FOREACH_KEY_VAL(from_ht, num_key, str_key, entry) { tmp_str = NULL; if (UNEXPECTED(!str_key)) { str_key = tmp_str = zend_long_to_str(num_key); @@ -3296,17 +3297,13 @@ PHP_FUNCTION(strtr) return; } ZEND_HASH_FOREACH_END(); } else { - php_strtr_array(return_value, str, pats); + php_strtr_array(return_value, str, from_ht); } } else { - if (!try_convert_to_string(from)) { - return; - } - RETURN_STR(php_strtr_ex(str, - Z_STRVAL_P(from), + ZSTR_VAL(from_str), to, - MIN(Z_STRLEN_P(from), to_len))); + MIN(ZSTR_LEN(from_str), to_len))); } } /* }}} */ diff --git a/ext/standard/tests/strings/strtr_variation6.phpt b/ext/standard/tests/strings/strtr_variation6.phpt index 7deffa12fd..e0c2458ede 100644 --- a/ext/standard/tests/strings/strtr_variation6.phpt +++ b/ext/standard/tests/strings/strtr_variation6.phpt @@ -80,8 +80,12 @@ $count = 1; for($index = 0; $index < count($from_arr); $index++) { echo "-- Iteration $count --\n"; $from = $from_arr[$index]; - var_dump( strtr($str, $from, $to) ); - $count ++; + try { + var_dump(strtr($str, $from, $to)); + } catch (TypeError $exception) { + echo $exception->getMessage() . "\n"; + } + $count++; } fclose($file_handle); //closing the file handle @@ -101,17 +105,11 @@ string(6) "m1tatm" -- Iteration 6 -- string(6) "tm0atm" -- Iteration 7 -- - -Warning: Array to string conversion in %s on line %d -string(6) "0120tm" +If three arguments are passed, the second argument must be a string -- Iteration 8 -- - -Warning: Array to string conversion in %s on line %d -string(6) "0120tm" +If three arguments are passed, the second argument must be a string -- Iteration 9 -- - -Warning: Array to string conversion in %s on line %d -string(6) "0120tm" +If three arguments are passed, the second argument must be a string -- Iteration 10 -- string(6) "0a2atm" -- Iteration 11 -- @@ -127,7 +125,7 @@ string(6) "012atm" -- Iteration 16 -- string(6) "012ttm" -- Iteration 17 -- -string(6) "012atm" +strtr() expects parameter 2 to be string or array, resource given -- Iteration 18 -- string(6) "012atm" -- Iteration 19 -- diff --git a/ext/standard/tests/strings/strtr_variation8.phpt b/ext/standard/tests/strings/strtr_variation8.phpt index 2e2843335d..97d3163e21 100644 --- a/ext/standard/tests/strings/strtr_variation8.phpt +++ b/ext/standard/tests/strings/strtr_variation8.phpt @@ -78,8 +78,8 @@ for($index = 0; $index < count($replace_pairs_arr); $index++) { echo "\n-- Iteration $count --\n"; $replace_pairs = $replace_pairs_arr[$index]; try { - var_dump( strtr($str, $replace_pairs) ); - } catch (\TypeError $e) { + var_dump(strtr($str, $replace_pairs)); + } catch (TypeError $e) { echo $e->getMessage() . "\n"; } @@ -94,22 +94,22 @@ echo "*** Done ***"; *** Testing strtr() function: with unexpected inputs for 'replace_pairs' *** -- Iteration 1 -- -The second argument is not an array +If two arguments are passed, the second argument must be an array -- Iteration 2 -- -The second argument is not an array +If two arguments are passed, the second argument must be an array -- Iteration 3 -- -The second argument is not an array +If two arguments are passed, the second argument must be an array -- Iteration 4 -- -The second argument is not an array +If two arguments are passed, the second argument must be an array -- Iteration 5 -- -The second argument is not an array +If two arguments are passed, the second argument must be an array -- Iteration 6 -- -The second argument is not an array +If two arguments are passed, the second argument must be an array -- Iteration 7 -- string(6) "012atm" @@ -121,32 +121,32 @@ string(6) "012atm" string(6) "122atm" -- Iteration 10 -- -The second argument is not an array +If two arguments are passed, the second argument must be an array -- Iteration 11 -- -The second argument is not an array +If two arguments are passed, the second argument must be an array -- Iteration 12 -- -The second argument is not an array +If two arguments are passed, the second argument must be an array -- Iteration 13 -- -The second argument is not an array +If two arguments are passed, the second argument must be an array -- Iteration 14 -- -The second argument is not an array +If two arguments are passed, the second argument must be an array -- Iteration 15 -- -The second argument is not an array +If two arguments are passed, the second argument must be an array -- Iteration 16 -- -The second argument is not an array +If two arguments are passed, the second argument must be an array -- Iteration 17 -- -The second argument is not an array +strtr() expects parameter 2 to be string or array, resource given -- Iteration 18 -- -The second argument is not an array +If two arguments are passed, the second argument must be an array -- Iteration 19 -- -The second argument is not an array +If two arguments are passed, the second argument must be an array *** Done *** -- 2.40.0