Skip to content

Commit bcd4138

Browse files
committed
Merge branch 'PHP-8.3'
* PHP-8.3: Fix segfault caused by use of 'pass' encoding when mbstring converts multipart form POST data
2 parents ea3c541 + 67051eb commit bcd4138

File tree

2 files changed

+43
-13
lines changed

2 files changed

+43
-13
lines changed

ext/mbstring/mbstring.c

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -299,8 +299,7 @@ static size_t count_commas(const char *p, const char *end) {
299299
* Emits a ValueError in function context and a warning in INI context, in INI context arg_num must be 0.
300300
*/
301301
static zend_result php_mb_parse_encoding_list(const char *value, size_t value_length,
302-
const mbfl_encoding ***return_list, size_t *return_size, bool persistent, uint32_t arg_num,
303-
bool allow_pass_encoding)
302+
const mbfl_encoding ***return_list, size_t *return_size, bool persistent, uint32_t arg_num)
304303
{
305304
if (value == NULL || value_length == 0) {
306305
*return_list = NULL;
@@ -351,8 +350,7 @@ static zend_result php_mb_parse_encoding_list(const char *value, size_t value_le
351350
}
352351
}
353352
} else {
354-
const mbfl_encoding *encoding =
355-
allow_pass_encoding ? php_mb_get_encoding_or_pass_ex(p1, p1_length) : mbfl_name2encoding_ex(p1, p1_length);
353+
const mbfl_encoding *encoding = mbfl_name2encoding_ex(p1, p1_length);
356354
if (!encoding) {
357355
/* Called from an INI setting modification */
358356
if (arg_num == 0) {
@@ -456,8 +454,12 @@ static const zend_encoding *php_mb_zend_encoding_detector(const unsigned char *a
456454
list = (const zend_encoding**)MBSTRG(current_detect_order_list);
457455
list_size = MBSTRG(current_detect_order_list_size);
458456
}
459-
460-
return (const zend_encoding*)mb_guess_encoding((unsigned char*)arg_string, arg_length, (const mbfl_encoding **)list, list_size, false, false);
457+
if (list_size == 1 && ((mbfl_encoding*)*list) == &mbfl_encoding_pass) {
458+
/* Emulate behavior of previous implementation; it would never return "pass"
459+
* from an encoding auto-detection operation */
460+
return NULL;
461+
}
462+
return (const zend_encoding*)mb_guess_encoding((unsigned char*)arg_string, arg_length, (const mbfl_encoding**)list, list_size, false, false);
461463
}
462464

463465
static size_t php_mb_zend_encoding_converter(unsigned char **to, size_t *to_length, const unsigned char *from, size_t from_length, const zend_encoding *encoding_to, const zend_encoding *encoding_from)
@@ -478,7 +480,7 @@ static zend_result php_mb_zend_encoding_list_parser(const char *encoding_list, s
478480
return php_mb_parse_encoding_list(
479481
encoding_list, encoding_list_len,
480482
(const mbfl_encoding ***)return_list, return_size,
481-
persistent, /* arg_num */ 0, /* allow_pass_encoding */ 0);
483+
persistent, /* arg_num */ 0);
482484
}
483485

484486
static const zend_encoding *php_mb_zend_internal_encoding_getter(void)
@@ -716,7 +718,7 @@ static PHP_INI_MH(OnUpdate_mbstring_detect_order)
716718
return SUCCESS;
717719
}
718720

719-
if (FAILURE == php_mb_parse_encoding_list(ZSTR_VAL(new_value), ZSTR_LEN(new_value), &list, &size, /* persistent */ 1, /* arg_num */ 0, /* allow_pass_encoding */ 0) || size == 0) {
721+
if (FAILURE == php_mb_parse_encoding_list(ZSTR_VAL(new_value), ZSTR_LEN(new_value), &list, &size, /* persistent */ 1, /* arg_num */ 0) || size == 0) {
720722
return FAILURE;
721723
}
722724

@@ -732,7 +734,11 @@ static PHP_INI_MH(OnUpdate_mbstring_detect_order)
732734
static zend_result _php_mb_ini_mbstring_http_input_set(const char *new_value, size_t new_value_length) {
733735
const mbfl_encoding **list;
734736
size_t size;
735-
if (FAILURE == php_mb_parse_encoding_list(new_value, new_value_length, &list, &size, /* persistent */ 1, /* arg_num */ 0, /* allow_pass_encoding */ 1) || size == 0) {
737+
if (new_value_length == 4 && strncmp(new_value, "pass", 4) == 0) {
738+
list = (const mbfl_encoding**)pecalloc(1, sizeof(mbfl_encoding*), 1);
739+
*list = &mbfl_encoding_pass;
740+
size = 1;
741+
} else if (FAILURE == php_mb_parse_encoding_list(new_value, new_value_length, &list, &size, /* persistent */ 1, /* arg_num */ 0) || size == 0) {
736742
return FAILURE;
737743
}
738744
if (MBSTRG(http_input_list)) {
@@ -1390,7 +1396,7 @@ PHP_FUNCTION(mb_detect_order)
13901396
RETURN_THROWS();
13911397
}
13921398
} else {
1393-
if (FAILURE == php_mb_parse_encoding_list(ZSTR_VAL(order_str), ZSTR_LEN(order_str), &list, &size, /* persistent */ 0, /* arg_num */ 1, /* allow_pass_encoding */ 0)) {
1399+
if (FAILURE == php_mb_parse_encoding_list(ZSTR_VAL(order_str), ZSTR_LEN(order_str), &list, &size, /* persistent */ 0, /* arg_num */ 1)) {
13941400
RETURN_THROWS();
13951401
}
13961402
}
@@ -2848,7 +2854,7 @@ PHP_FUNCTION(mb_convert_encoding)
28482854
} else if (from_encodings_str) {
28492855
if (php_mb_parse_encoding_list(ZSTR_VAL(from_encodings_str), ZSTR_LEN(from_encodings_str),
28502856
&from_encodings, &num_from_encodings,
2851-
/* persistent */ 0, /* arg_num */ 3, /* allow_pass_encoding */ 0) == FAILURE) {
2857+
/* persistent */ 0, /* arg_num */ 3) == FAILURE) {
28522858
RETURN_THROWS();
28532859
}
28542860
free_from_encodings = true;
@@ -3377,7 +3383,7 @@ PHP_FUNCTION(mb_detect_encoding)
33773383
RETURN_THROWS();
33783384
}
33793385
} else if (encoding_str) {
3380-
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)) {
3386+
if (FAILURE == php_mb_parse_encoding_list(ZSTR_VAL(encoding_str), ZSTR_LEN(encoding_str), &elist, &size, /* persistent */ 0, /* arg_num */ 2)) {
33813387
RETURN_THROWS();
33823388
}
33833389
} else {
@@ -3778,7 +3784,7 @@ PHP_FUNCTION(mb_convert_variables)
37783784
RETURN_THROWS();
37793785
}
37803786
} else {
3781-
if (php_mb_parse_encoding_list(ZSTR_VAL(from_enc_str), ZSTR_LEN(from_enc_str), &elist, &elistsz, /* persistent */ 0, /* arg_num */ 2, /* allow_pass_encoding */ 0) == FAILURE) {
3787+
if (php_mb_parse_encoding_list(ZSTR_VAL(from_enc_str), ZSTR_LEN(from_enc_str), &elist, &elistsz, /* persistent */ 0, /* arg_num */ 2) == FAILURE) {
37823788
RETURN_THROWS();
37833789
}
37843790
}

ext/mbstring/tests/gh13123.phpt

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
--TEST--
2+
Segfault in mb_fast_convert() when mbstring.encoding_translation is enabled (GH-13123)
3+
--EXTENSIONS--
4+
mbstring
5+
--POST_RAW--
6+
Content-Type: multipart/form-data, boundary=Blah
7+
8+
--Blah
9+
Content-Disposition: form-data; name="file"; filename="file.txt"
10+
Content-Type: text/plain
11+
12+
foo
13+
--Blah
14+
15+
--INI--
16+
error_reporting=E_ALL&~E_DEPRECATED
17+
mbstring.encoding_translation=On
18+
mbstring.http_input=pass
19+
--FILE--
20+
<?php
21+
print "Done!\n";
22+
?>
23+
--EXPECT--
24+
Done!

0 commit comments

Comments
 (0)