Skip to content

Commit 50d07ff

Browse files
committed
mb_detect_encoding(): Use proper array|string parameter
Needed to add support for nullabiltiy in some places.
1 parent 47ddd95 commit 50d07ff

File tree

5 files changed

+38
-32
lines changed

5 files changed

+38
-32
lines changed

Diff for: Zend/zend_API.h

+12-3
Original file line numberDiff line numberDiff line change
@@ -1548,14 +1548,20 @@ ZEND_API ZEND_COLD void ZEND_FASTCALL zend_argument_value_error(uint32_t arg_num
15481548
#define Z_PARAM_VARIADIC(spec, dest, dest_num) \
15491549
Z_PARAM_VARIADIC_EX(spec, dest, dest_num, 0)
15501550

1551-
#define Z_PARAM_STR_OR_ARRAY_HT(dest_str, dest_ht) \
1551+
#define Z_PARAM_STR_OR_ARRAY_HT_EX(dest_str, dest_ht, allow_null) \
15521552
Z_PARAM_PROLOGUE(0, 0); \
1553-
if (UNEXPECTED(!zend_parse_arg_str_or_array_ht(_arg, &dest_str, &dest_ht))) { \
1553+
if (UNEXPECTED(!zend_parse_arg_str_or_array_ht(_arg, &dest_str, &dest_ht, allow_null))) { \
15541554
_expected_type = Z_EXPECTED_STRING_OR_ARRAY; \
15551555
_error_code = ZPP_ERROR_WRONG_ARG; \
15561556
break; \
15571557
}
15581558

1559+
#define Z_PARAM_STR_OR_ARRAY_HT(dest_str, dest_ht) \
1560+
Z_PARAM_STR_OR_ARRAY_HT_EX(dest_str, dest_ht, 0);
1561+
1562+
#define Z_PARAM_STR_OR_ARRAY_HT_OR_NULL(dest_str, dest_ht) \
1563+
Z_PARAM_STR_OR_ARRAY_HT_EX(dest_str, dest_ht, 1);
1564+
15591565
/* End of new parameter parsing API */
15601566

15611567
/* Inlined implementations shared by new and old parameter parsing APIs */
@@ -1775,14 +1781,17 @@ static zend_always_inline void zend_parse_arg_zval_deref(zval *arg, zval **dest,
17751781
}
17761782

17771783
static zend_always_inline int zend_parse_arg_str_or_array_ht(
1778-
zval *arg, zend_string **dest_str, HashTable **dest_ht)
1784+
zval *arg, zend_string **dest_str, HashTable **dest_ht, int allow_null)
17791785
{
17801786
if (EXPECTED(Z_TYPE_P(arg) == IS_STRING)) {
17811787
*dest_str = Z_STR_P(arg);
17821788
*dest_ht = NULL;
17831789
} else if (EXPECTED(Z_TYPE_P(arg) == IS_ARRAY)) {
17841790
*dest_ht = Z_ARRVAL_P(arg);
17851791
*dest_str = NULL;
1792+
} else if (allow_null && EXPECTED(Z_TYPE_P(arg) == IS_NULL)) {
1793+
*dest_ht = NULL;
1794+
*dest_str = NULL;
17861795
} else {
17871796
*dest_ht = NULL;
17881797
return zend_parse_arg_str_slow(arg, dest_str);

Diff for: ext/mbstring/mbstring.c

+21-24
Original file line numberDiff line numberDiff line change
@@ -2961,39 +2961,31 @@ PHP_FUNCTION(mb_detect_encoding)
29612961
{
29622962
char *str;
29632963
size_t str_len;
2964-
zend_bool strict=0;
2965-
zval *encoding_list = NULL;
2964+
zend_string *encoding_str = NULL;
2965+
HashTable *encoding_ht = NULL;
2966+
zend_bool strict = 0;
29662967

29672968
mbfl_string string;
29682969
const mbfl_encoding *ret;
29692970
const mbfl_encoding **elist;
29702971
size_t size;
29712972
zend_bool free_elist;
29722973

2973-
if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|z!b", &str, &str_len, &encoding_list, &strict) == FAILURE) {
2974-
RETURN_THROWS();
2975-
}
2974+
ZEND_PARSE_PARAMETERS_START(1, 3)
2975+
Z_PARAM_STRING(str, str_len)
2976+
Z_PARAM_OPTIONAL
2977+
Z_PARAM_STR_OR_ARRAY_HT_OR_NULL(encoding_str, encoding_ht)
2978+
Z_PARAM_BOOL(strict)
2979+
ZEND_PARSE_PARAMETERS_END();
29762980

29772981
/* make encoding list */
2978-
if (encoding_list) {
2979-
switch (Z_TYPE_P(encoding_list)) {
2980-
case IS_ARRAY:
2981-
if (FAILURE == php_mb_parse_encoding_array(Z_ARRVAL_P(encoding_list), &elist, &size, 0)) {
2982-
RETURN_FALSE;
2983-
}
2984-
break;
2985-
default:
2986-
if (!try_convert_to_string(encoding_list)) {
2987-
RETURN_THROWS();
2988-
}
2989-
if (FAILURE == php_mb_parse_encoding_list(Z_STRVAL_P(encoding_list), Z_STRLEN_P(encoding_list), &elist, &size, 0)) {
2990-
RETURN_FALSE;
2991-
}
2992-
break;
2982+
if (encoding_ht) {
2983+
if (FAILURE == php_mb_parse_encoding_array(encoding_ht, &elist, &size, 0)) {
2984+
RETURN_FALSE;
29932985
}
2994-
if (size == 0) {
2995-
efree(elist);
2996-
php_error_docref(NULL, E_WARNING, "Must specify at least one encoding");
2986+
free_elist = 1;
2987+
} else if (encoding_str) {
2988+
if (FAILURE == php_mb_parse_encoding_list(ZSTR_VAL(encoding_str), ZSTR_LEN(encoding_str), &elist, &size, 0)) {
29972989
RETURN_FALSE;
29982990
}
29992991
free_elist = 1;
@@ -3003,11 +2995,16 @@ PHP_FUNCTION(mb_detect_encoding)
30032995
free_elist = 0;
30042996
}
30052997

2998+
if (size == 0) {
2999+
efree(elist);
3000+
php_error_docref(NULL, E_WARNING, "Must specify at least one encoding");
3001+
RETURN_FALSE;
3002+
}
3003+
30063004
if (ZEND_NUM_ARGS() < 3) {
30073005
strict = MBSTRG(strict_detection);
30083006
}
30093007

3010-
30113008
mbfl_string_init(&string);
30123009
string.no_language = MBSTRG(language);
30133010
string.val = (unsigned char *)str;

Diff for: ext/mbstring/mbstring.stub.php

+1-2
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,7 @@ function mb_strtoupper(string $sourcestring, ?string $encoding = null): string|f
5656

5757
function mb_strtolower(string $sourcestring, ?string $encoding = null): string|false {}
5858

59-
/** @param array|string $encoding_list */
60-
function mb_detect_encoding(string $str, $encoding_list = null, bool $strict = false): string|false {}
59+
function mb_detect_encoding(string $str, array|string|null $encoding_list = null, bool $strict = false): string|false {}
6160

6261
function mb_list_encodings(): array {}
6362

Diff for: ext/mbstring/mbstring_arginfo.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ ZEND_END_ARG_INFO()
124124

125125
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_mb_detect_encoding, 0, 1, MAY_BE_STRING|MAY_BE_FALSE)
126126
ZEND_ARG_TYPE_INFO(0, str, IS_STRING, 0)
127-
ZEND_ARG_INFO(0, encoding_list)
127+
ZEND_ARG_TYPE_MASK(0, encoding_list, MAY_BE_ARRAY|MAY_BE_STRING|MAY_BE_NULL)
128128
ZEND_ARG_TYPE_INFO(0, strict, _IS_BOOL, 0)
129129
ZEND_END_ARG_INFO()
130130

Diff for: scripts/dev/gen_stub.php

+3-2
Original file line numberDiff line numberDiff line change
@@ -373,9 +373,10 @@ function parseFunctionLike(string $name, Node\FunctionLike $func, ?string $cond)
373373
throw new Exception("Error in function $name: only the last parameter can be variadic");
374374
}
375375

376+
$type = $param->type ? Type::fromNode($param->type) : null;
376377
if ($param->default instanceof Expr\ConstFetch &&
377378
$param->default->name->toLowerString() === "null" &&
378-
$param->type && !($param->type instanceof Node\NullableType)
379+
$type && !$type->isNullable()
379380
) {
380381
throw new Exception(
381382
"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)
387388
$varName,
388389
$sendBy,
389390
$param->variadic,
390-
$param->type ? Type::fromNode($param->type) : null
391+
$type
391392
);
392393
if (!$param->default && !$param->variadic) {
393394
$numRequiredArgs = $i + 1;

0 commit comments

Comments
 (0)