summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikita Popov <nikita.ppv@gmail.com>2020-03-30 16:06:41 +0200
committerNikita Popov <nikita.ppv@gmail.com>2020-03-30 16:15:12 +0200
commit50d07ff28c9e91f310bf6145b657fccd17b09bec (patch)
treec212faee882b2fd805db7c36736fca7b67ea5ff9
parent47ddd95836142a5bea28abab26999e72d5f85493 (diff)
downloadphp-git-50d07ff28c9e91f310bf6145b657fccd17b09bec.tar.gz
mb_detect_encoding(): Use proper array|string parameter
Needed to add support for nullabiltiy in some places.
-rw-r--r--Zend/zend_API.h15
-rw-r--r--ext/mbstring/mbstring.c45
-rw-r--r--ext/mbstring/mbstring.stub.php3
-rw-r--r--ext/mbstring/mbstring_arginfo.h2
-rwxr-xr-xscripts/dev/gen_stub.php5
5 files changed, 38 insertions, 32 deletions
diff --git a/Zend/zend_API.h b/Zend/zend_API.h
index fe5694940c..a925651b83 100644
--- a/Zend/zend_API.h
+++ b/Zend/zend_API.h
@@ -1548,14 +1548,20 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_argument_value_error(uint32_t arg_num
#define Z_PARAM_VARIADIC(spec, dest, dest_num) \
Z_PARAM_VARIADIC_EX(spec, dest, dest_num, 0)
-#define Z_PARAM_STR_OR_ARRAY_HT(dest_str, dest_ht) \
+#define Z_PARAM_STR_OR_ARRAY_HT_EX(dest_str, dest_ht, allow_null) \
Z_PARAM_PROLOGUE(0, 0); \
- if (UNEXPECTED(!zend_parse_arg_str_or_array_ht(_arg, &dest_str, &dest_ht))) { \
+ if (UNEXPECTED(!zend_parse_arg_str_or_array_ht(_arg, &dest_str, &dest_ht, allow_null))) { \
_expected_type = Z_EXPECTED_STRING_OR_ARRAY; \
_error_code = ZPP_ERROR_WRONG_ARG; \
break; \
}
+#define Z_PARAM_STR_OR_ARRAY_HT(dest_str, dest_ht) \
+ Z_PARAM_STR_OR_ARRAY_HT_EX(dest_str, dest_ht, 0);
+
+#define Z_PARAM_STR_OR_ARRAY_HT_OR_NULL(dest_str, dest_ht) \
+ Z_PARAM_STR_OR_ARRAY_HT_EX(dest_str, dest_ht, 1);
+
/* End of new parameter parsing API */
/* Inlined implementations shared by new and old parameter parsing APIs */
@@ -1775,7 +1781,7 @@ static zend_always_inline void zend_parse_arg_zval_deref(zval *arg, zval **dest,
}
static zend_always_inline int zend_parse_arg_str_or_array_ht(
- zval *arg, zend_string **dest_str, HashTable **dest_ht)
+ zval *arg, zend_string **dest_str, HashTable **dest_ht, int allow_null)
{
if (EXPECTED(Z_TYPE_P(arg) == IS_STRING)) {
*dest_str = Z_STR_P(arg);
@@ -1783,6 +1789,9 @@ static zend_always_inline int zend_parse_arg_str_or_array_ht(
} else if (EXPECTED(Z_TYPE_P(arg) == IS_ARRAY)) {
*dest_ht = Z_ARRVAL_P(arg);
*dest_str = NULL;
+ } else if (allow_null && EXPECTED(Z_TYPE_P(arg) == IS_NULL)) {
+ *dest_ht = NULL;
+ *dest_str = NULL;
} else {
*dest_ht = NULL;
return zend_parse_arg_str_slow(arg, dest_str);
diff --git a/ext/mbstring/mbstring.c b/ext/mbstring/mbstring.c
index 1118200cd9..774e6adc7e 100644
--- a/ext/mbstring/mbstring.c
+++ b/ext/mbstring/mbstring.c
@@ -2961,8 +2961,9 @@ PHP_FUNCTION(mb_detect_encoding)
{
char *str;
size_t str_len;
- zend_bool strict=0;
- zval *encoding_list = NULL;
+ zend_string *encoding_str = NULL;
+ HashTable *encoding_ht = NULL;
+ zend_bool strict = 0;
mbfl_string string;
const mbfl_encoding *ret;
@@ -2970,30 +2971,21 @@ PHP_FUNCTION(mb_detect_encoding)
size_t size;
zend_bool free_elist;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|z!b", &str, &str_len, &encoding_list, &strict) == FAILURE) {
- RETURN_THROWS();
- }
+ ZEND_PARSE_PARAMETERS_START(1, 3)
+ Z_PARAM_STRING(str, str_len)
+ Z_PARAM_OPTIONAL
+ Z_PARAM_STR_OR_ARRAY_HT_OR_NULL(encoding_str, encoding_ht)
+ Z_PARAM_BOOL(strict)
+ ZEND_PARSE_PARAMETERS_END();
/* make encoding list */
- if (encoding_list) {
- switch (Z_TYPE_P(encoding_list)) {
- case IS_ARRAY:
- if (FAILURE == php_mb_parse_encoding_array(Z_ARRVAL_P(encoding_list), &elist, &size, 0)) {
- RETURN_FALSE;
- }
- break;
- default:
- if (!try_convert_to_string(encoding_list)) {
- RETURN_THROWS();
- }
- if (FAILURE == php_mb_parse_encoding_list(Z_STRVAL_P(encoding_list), Z_STRLEN_P(encoding_list), &elist, &size, 0)) {
- RETURN_FALSE;
- }
- break;
+ if (encoding_ht) {
+ if (FAILURE == php_mb_parse_encoding_array(encoding_ht, &elist, &size, 0)) {
+ RETURN_FALSE;
}
- if (size == 0) {
- efree(elist);
- php_error_docref(NULL, E_WARNING, "Must specify at least one encoding");
+ free_elist = 1;
+ } else if (encoding_str) {
+ if (FAILURE == php_mb_parse_encoding_list(ZSTR_VAL(encoding_str), ZSTR_LEN(encoding_str), &elist, &size, 0)) {
RETURN_FALSE;
}
free_elist = 1;
@@ -3003,11 +2995,16 @@ PHP_FUNCTION(mb_detect_encoding)
free_elist = 0;
}
+ if (size == 0) {
+ efree(elist);
+ php_error_docref(NULL, E_WARNING, "Must specify at least one encoding");
+ RETURN_FALSE;
+ }
+
if (ZEND_NUM_ARGS() < 3) {
strict = MBSTRG(strict_detection);
}
-
mbfl_string_init(&string);
string.no_language = MBSTRG(language);
string.val = (unsigned char *)str;
diff --git a/ext/mbstring/mbstring.stub.php b/ext/mbstring/mbstring.stub.php
index 67d8468f43..0463f570f4 100644
--- a/ext/mbstring/mbstring.stub.php
+++ b/ext/mbstring/mbstring.stub.php
@@ -56,8 +56,7 @@ function mb_strtoupper(string $sourcestring, ?string $encoding = null): string|f
function mb_strtolower(string $sourcestring, ?string $encoding = null): string|false {}
-/** @param array|string $encoding_list */
-function mb_detect_encoding(string $str, $encoding_list = null, bool $strict = false): string|false {}
+function mb_detect_encoding(string $str, array|string|null $encoding_list = null, bool $strict = false): string|false {}
function mb_list_encodings(): array {}
diff --git a/ext/mbstring/mbstring_arginfo.h b/ext/mbstring/mbstring_arginfo.h
index bb902af837..f454cc91e8 100644
--- a/ext/mbstring/mbstring_arginfo.h
+++ b/ext/mbstring/mbstring_arginfo.h
@@ -124,7 +124,7 @@ ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_mb_detect_encoding, 0, 1, MAY_BE_STRING|MAY_BE_FALSE)
ZEND_ARG_TYPE_INFO(0, str, IS_STRING, 0)
- ZEND_ARG_INFO(0, encoding_list)
+ ZEND_ARG_TYPE_MASK(0, encoding_list, MAY_BE_ARRAY|MAY_BE_STRING|MAY_BE_NULL)
ZEND_ARG_TYPE_INFO(0, strict, _IS_BOOL, 0)
ZEND_END_ARG_INFO()
diff --git a/scripts/dev/gen_stub.php b/scripts/dev/gen_stub.php
index 253c188b2a..f3a9a492b0 100755
--- a/scripts/dev/gen_stub.php
+++ b/scripts/dev/gen_stub.php
@@ -373,9 +373,10 @@ function parseFunctionLike(string $name, Node\FunctionLike $func, ?string $cond)
throw new Exception("Error in function $name: only the last parameter can be variadic");
}
+ $type = $param->type ? Type::fromNode($param->type) : null;
if ($param->default instanceof Expr\ConstFetch &&
$param->default->name->toLowerString() === "null" &&
- $param->type && !($param->type instanceof Node\NullableType)
+ $type && !$type->isNullable()
) {
throw new Exception(
"Parameter $varName of function $name has null default, but is not nullable");
@@ -387,7 +388,7 @@ function parseFunctionLike(string $name, Node\FunctionLike $func, ?string $cond)
$varName,
$sendBy,
$param->variadic,
- $param->type ? Type::fromNode($param->type) : null
+ $type
);
if (!$param->default && !$param->variadic) {
$numRequiredArgs = $i + 1;