Skip to content

Commit

Permalink
Fix GH-9008: mb_detect_encoding(): wrong results with null $encodings
Browse files Browse the repository at this point in the history
Passing `null` to `$encodings` is supposed to behave like passing the
result of `mb_detect_order()`.  Therefore, we need to remove the non-
encodings from the `elist` in this case as well.  Thus, we duplicate
the global `elist`, so we can modify it.

Closes GH-9063.
  • Loading branch information
cmb69 committed Jul 20, 2022
1 parent d430652 commit c2bdaa4
Show file tree
Hide file tree
Showing 3 changed files with 41 additions and 14 deletions.
4 changes: 4 additions & 0 deletions NEWS
Expand Up @@ -5,6 +5,10 @@ PHP NEWS
- Core:
. Fixed --CGI-- support of run-tests.php. (cmb)

- MBString:
. Fix bug GH-9008 (mb_detect_encoding(): wrong results with null $encodings).
(cmb)

04 Aug 2022, PHP 8.1.9

- CLI:
Expand Down
27 changes: 13 additions & 14 deletions ext/mbstring/mbstring.c
Expand Up @@ -2694,6 +2694,13 @@ PHP_FUNCTION(mb_strtolower)
}
/* }}} */

static const mbfl_encoding **duplicate_elist(const mbfl_encoding **elist, size_t size)
{
const mbfl_encoding **new_elist = safe_emalloc(size, sizeof(mbfl_encoding*), 0);
memcpy(ZEND_VOIDP(new_elist), elist, size * sizeof(mbfl_encoding*));
return new_elist;
}

/* {{{ Encodings of the given string is returned (as a string) */
PHP_FUNCTION(mb_detect_encoding)
{
Expand All @@ -2707,7 +2714,6 @@ PHP_FUNCTION(mb_detect_encoding)
const mbfl_encoding *ret;
const mbfl_encoding **elist;
size_t size;
bool free_elist;

ZEND_PARSE_PARAMETERS_START(1, 3)
Z_PARAM_STRING(str, str_len)
Expand All @@ -2721,16 +2727,13 @@ PHP_FUNCTION(mb_detect_encoding)
if (FAILURE == php_mb_parse_encoding_array(encoding_ht, &elist, &size, 2)) {
RETURN_THROWS();
}
free_elist = 1;
} else if (encoding_str) {
if (FAILURE == php_mb_parse_encoding_list(ZSTR_VAL(encoding_str), ZSTR_LEN(encoding_str), &elist, &size, /* persistent */ 0, /* arg_num */ 2, /* allow_pass_encoding */ 0)) {
RETURN_THROWS();
}
free_elist = 1;
} else {
elist = MBSTRG(current_detect_order_list);
elist = duplicate_elist(MBSTRG(current_detect_order_list), MBSTRG(current_detect_order_list_size));
size = MBSTRG(current_detect_order_list_size);
free_elist = 0;
}

if (size == 0) {
Expand All @@ -2739,12 +2742,10 @@ PHP_FUNCTION(mb_detect_encoding)
RETURN_THROWS();
}

if (free_elist) {
remove_non_encodings_from_elist(elist, &size);
if (size == 0) {
efree(ZEND_VOIDP(elist));
RETURN_FALSE;
}
remove_non_encodings_from_elist(elist, &size);
if (size == 0) {
efree(ZEND_VOIDP(elist));
RETURN_FALSE;
}

if (ZEND_NUM_ARGS() < 3) {
Expand All @@ -2761,9 +2762,7 @@ PHP_FUNCTION(mb_detect_encoding)
ret = mbfl_identify_encoding(&string, elist, size, strict);
}

if (free_elist) {
efree(ZEND_VOIDP(elist));
}
efree(ZEND_VOIDP(elist));

if (ret == NULL) {
RETURN_FALSE;
Expand Down
24 changes: 24 additions & 0 deletions ext/mbstring/tests/gh9008.phpt
@@ -0,0 +1,24 @@
--TEST--
GH-9008 (mb_detect_encoding(): wrong results with null $encodings)
--EXTENSIONS--
mbstring
--FILE--
<?php
$string = "<?php
function test()
{
}
";

mb_detect_order(["ASCII", "UUENCODE"]);

var_dump(
mb_detect_encoding($string, null, true),
mb_detect_encoding($string, mb_detect_order(), true),
);
?>
--EXPECT--
string(5) "ASCII"
string(5) "ASCII"

0 comments on commit c2bdaa4

Please sign in to comment.