Skip to content

Commit 0dd75c8

Browse files
committed
Merge branch 'PHP-8.4' into PHP-8.5
* PHP-8.4: Fix GH-21664: iconv_mime_decode/iconv_mime_encode bailout corrupts EG(bailout).
2 parents d04b03b + 1f4b169 commit 0dd75c8

File tree

2 files changed

+58
-33
lines changed

2 files changed

+58
-33
lines changed

ext/iconv/iconv.c

Lines changed: 37 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1030,7 +1030,7 @@ static php_iconv_err_t _php_iconv_mime_encode(smart_str *pretval, const char *fn
10301030

10311031
if (out_size <= out_reserved) {
10321032
err = PHP_ICONV_ERR_TOO_BIG;
1033-
goto out;
1033+
goto out_try;
10341034
}
10351035

10361036
out_left = out_size - out_reserved;
@@ -1039,22 +1039,22 @@ static php_iconv_err_t _php_iconv_mime_encode(smart_str *pretval, const char *fn
10391039
switch (errno) {
10401040
case EINVAL:
10411041
err = PHP_ICONV_ERR_ILLEGAL_CHAR;
1042-
goto out;
1042+
goto out_try;
10431043

10441044
case EILSEQ:
10451045
err = PHP_ICONV_ERR_ILLEGAL_SEQ;
1046-
goto out;
1046+
goto out_try;
10471047

10481048
case E2BIG:
10491049
if (prev_in_left == in_left) {
10501050
err = PHP_ICONV_ERR_TOO_BIG;
1051-
goto out;
1051+
goto out_try;
10521052
}
10531053
break;
10541054

10551055
default:
10561056
err = PHP_ICONV_ERR_UNKNOWN;
1057-
goto out;
1057+
goto out_try;
10581058
}
10591059
}
10601060

@@ -1063,15 +1063,15 @@ static php_iconv_err_t _php_iconv_mime_encode(smart_str *pretval, const char *fn
10631063
if (iconv(cd, NULL, NULL, (char **) &out_p, &out_left) == (size_t)-1) {
10641064
if (errno != E2BIG) {
10651065
err = PHP_ICONV_ERR_UNKNOWN;
1066-
goto out;
1066+
goto out_try;
10671067
}
10681068
} else {
10691069
break;
10701070
}
10711071

10721072
if (iconv(cd, NULL, NULL, NULL, NULL) == (size_t)-1) {
10731073
err = PHP_ICONV_ERR_UNKNOWN;
1074-
goto out;
1074+
goto out_try;
10751075
}
10761076

10771077
out_reserved += 4;
@@ -1086,7 +1086,7 @@ static php_iconv_err_t _php_iconv_mime_encode(smart_str *pretval, const char *fn
10861086
if (char_cnt < ZSTR_LEN(encoded)) {
10871087
/* something went wrong! */
10881088
err = PHP_ICONV_ERR_UNKNOWN;
1089-
goto out;
1089+
goto out_try;
10901090
}
10911091

10921092
smart_str_appendl(pretval, ZSTR_VAL(encoded), ZSTR_LEN(encoded));
@@ -1123,28 +1123,28 @@ static php_iconv_err_t _php_iconv_mime_encode(smart_str *pretval, const char *fn
11231123
switch (errno) {
11241124
case EINVAL:
11251125
err = PHP_ICONV_ERR_ILLEGAL_CHAR;
1126-
goto out;
1126+
goto out_try;
11271127

11281128
case EILSEQ:
11291129
err = PHP_ICONV_ERR_ILLEGAL_SEQ;
1130-
goto out;
1130+
goto out_try;
11311131

11321132
case E2BIG:
11331133
if (prev_in_left == in_left) {
11341134
err = PHP_ICONV_ERR_UNKNOWN;
1135-
goto out;
1135+
goto out_try;
11361136
}
11371137
break;
11381138

11391139
default:
11401140
err = PHP_ICONV_ERR_UNKNOWN;
1141-
goto out;
1141+
goto out_try;
11421142
}
11431143
}
11441144
if (iconv(cd, NULL, NULL, (char **) &out_p, &out_left) == (size_t)-1) {
11451145
if (errno != E2BIG) {
11461146
err = PHP_ICONV_ERR_UNKNOWN;
1147-
goto out;
1147+
goto out_try;
11481148
}
11491149
}
11501150

@@ -1179,14 +1179,16 @@ static php_iconv_err_t _php_iconv_mime_encode(smart_str *pretval, const char *fn
11791179

11801180
if (iconv(cd, NULL, NULL, NULL, NULL) == (size_t)-1) {
11811181
err = PHP_ICONV_ERR_UNKNOWN;
1182-
goto out;
1182+
goto out_try;
11831183
}
11841184

11851185
} break; /* case PHP_ICONV_ENC_SCHEME_QPRINT: */
11861186
}
11871187
} while (in_left > 0);
11881188

11891189
smart_str_0(pretval);
1190+
1191+
out_try: ;
11901192
} zend_catch {
11911193
bailout = true;
11921194
} zend_end_try();
@@ -1278,7 +1280,7 @@ static php_iconv_err_t _php_iconv_mime_decode(smart_str *pretval, const char *st
12781280
if (mode & PHP_ICONV_MIME_DECODE_CONTINUE_ON_ERROR) {
12791281
err = PHP_ICONV_ERR_SUCCESS;
12801282
} else {
1281-
goto out;
1283+
goto out_try;
12821284
}
12831285
}
12841286
encoded_word = NULL;
@@ -1296,7 +1298,7 @@ static php_iconv_err_t _php_iconv_mime_decode(smart_str *pretval, const char *st
12961298
}
12971299
err = _php_iconv_appendl(pretval, encoded_word, (size_t)((p1 + 1) - encoded_word), cd_pl);
12981300
if (err != PHP_ICONV_ERR_SUCCESS) {
1299-
goto out;
1301+
goto out_try;
13001302
}
13011303
encoded_word = NULL;
13021304
if ((mode & PHP_ICONV_MIME_DECODE_STRICT)) {
@@ -1326,7 +1328,7 @@ static php_iconv_err_t _php_iconv_mime_decode(smart_str *pretval, const char *st
13261328
_php_iconv_appendc(pretval, '?', cd_pl);
13271329
err = _php_iconv_appendl(pretval, csname, (size_t)((p1 + 1) - csname), cd_pl);
13281330
if (err != PHP_ICONV_ERR_SUCCESS) {
1329-
goto out;
1331+
goto out_try;
13301332
}
13311333
csname = NULL;
13321334
if ((mode & PHP_ICONV_MIME_DECODE_STRICT)) {
@@ -1342,7 +1344,7 @@ static php_iconv_err_t _php_iconv_mime_decode(smart_str *pretval, const char *st
13421344

13431345
if (csname == NULL) {
13441346
err = PHP_ICONV_ERR_MALFORMED;
1345-
goto out;
1347+
goto out_try;
13461348
}
13471349

13481350
csname_len = (size_t)(p1 - csname);
@@ -1351,7 +1353,7 @@ static php_iconv_err_t _php_iconv_mime_decode(smart_str *pretval, const char *st
13511353
if ((mode & PHP_ICONV_MIME_DECODE_CONTINUE_ON_ERROR)) {
13521354
err = _php_iconv_appendl(pretval, encoded_word, (size_t)((p1 + 1) - encoded_word), cd_pl);
13531355
if (err != PHP_ICONV_ERR_SUCCESS) {
1354-
goto out;
1356+
goto out_try;
13551357
}
13561358
encoded_word = NULL;
13571359
if ((mode & PHP_ICONV_MIME_DECODE_STRICT)) {
@@ -1362,7 +1364,7 @@ static php_iconv_err_t _php_iconv_mime_decode(smart_str *pretval, const char *st
13621364
break;
13631365
} else {
13641366
err = PHP_ICONV_ERR_MALFORMED;
1365-
goto out;
1367+
goto out_try;
13661368
}
13671369
}
13681370

@@ -1409,7 +1411,7 @@ static php_iconv_err_t _php_iconv_mime_decode(smart_str *pretval, const char *st
14091411

14101412
err = _php_iconv_appendl(pretval, encoded_word, (size_t)((p1 + 1) - encoded_word), cd_pl);
14111413
if (err != PHP_ICONV_ERR_SUCCESS) {
1412-
goto out;
1414+
goto out_try;
14131415
}
14141416

14151417
/* Let's go back and see if there are further
@@ -1423,7 +1425,7 @@ static php_iconv_err_t _php_iconv_mime_decode(smart_str *pretval, const char *st
14231425
} else {
14241426
err = PHP_ICONV_ERR_CONVERTER;
14251427
}
1426-
goto out;
1428+
goto out_try;
14271429
}
14281430
}
14291431
}
@@ -1447,7 +1449,7 @@ static php_iconv_err_t _php_iconv_mime_decode(smart_str *pretval, const char *st
14471449
if ((mode & PHP_ICONV_MIME_DECODE_CONTINUE_ON_ERROR)) {
14481450
err = _php_iconv_appendl(pretval, encoded_word, (size_t)((p1 + 1) - encoded_word), cd_pl);
14491451
if (err != PHP_ICONV_ERR_SUCCESS) {
1450-
goto out;
1452+
goto out_try;
14511453
}
14521454
encoded_word = NULL;
14531455
if ((mode & PHP_ICONV_MIME_DECODE_STRICT)) {
@@ -1458,7 +1460,7 @@ static php_iconv_err_t _php_iconv_mime_decode(smart_str *pretval, const char *st
14581460
break;
14591461
} else {
14601462
err = PHP_ICONV_ERR_MALFORMED;
1461-
goto out;
1463+
goto out_try;
14621464
}
14631465
}
14641466
break;
@@ -1469,7 +1471,7 @@ static php_iconv_err_t _php_iconv_mime_decode(smart_str *pretval, const char *st
14691471
/* pass the entire chunk through the converter */
14701472
err = _php_iconv_appendl(pretval, encoded_word, (size_t)((p1 + 1) - encoded_word), cd_pl);
14711473
if (err != PHP_ICONV_ERR_SUCCESS) {
1472-
goto out;
1474+
goto out_try;
14731475
}
14741476
encoded_word = NULL;
14751477
if ((mode & PHP_ICONV_MIME_DECODE_STRICT)) {
@@ -1480,7 +1482,7 @@ static php_iconv_err_t _php_iconv_mime_decode(smart_str *pretval, const char *st
14801482
break;
14811483
} else {
14821484
err = PHP_ICONV_ERR_MALFORMED;
1483-
goto out;
1485+
goto out_try;
14841486
}
14851487
}
14861488
encoded_text = p1 + 1;
@@ -1525,7 +1527,7 @@ static php_iconv_err_t _php_iconv_mime_decode(smart_str *pretval, const char *st
15251527
/* pass the entire chunk through the converter */
15261528
err = _php_iconv_appendl(pretval, encoded_word, (size_t)((p1 + 1) - encoded_word), cd_pl);
15271529
if (err != PHP_ICONV_ERR_SUCCESS) {
1528-
goto out;
1530+
goto out_try;
15291531
}
15301532
encoded_word = NULL;
15311533
if ((mode & PHP_ICONV_MIME_DECODE_STRICT)) {
@@ -1536,7 +1538,7 @@ static php_iconv_err_t _php_iconv_mime_decode(smart_str *pretval, const char *st
15361538
break;
15371539
} else {
15381540
err = PHP_ICONV_ERR_MALFORMED;
1539-
goto out;
1541+
goto out_try;
15401542
}
15411543
}
15421544
scan_stat = 9;
@@ -1564,7 +1566,7 @@ static php_iconv_err_t _php_iconv_mime_decode(smart_str *pretval, const char *st
15641566
/* pass the entire chunk through the converter */
15651567
err = _php_iconv_appendl(pretval, encoded_word, (size_t)((p1 + 1) - encoded_word), cd_pl);
15661568
if (err != PHP_ICONV_ERR_SUCCESS) {
1567-
goto out;
1569+
goto out_try;
15681570
}
15691571
scan_stat = 12;
15701572
break;
@@ -1593,7 +1595,7 @@ static php_iconv_err_t _php_iconv_mime_decode(smart_str *pretval, const char *st
15931595
/* pass the entire chunk through the converter */
15941596
err = _php_iconv_appendl(pretval, encoded_word, (size_t)((p1 + 1) - encoded_word), cd_pl);
15951597
if (err != PHP_ICONV_ERR_SUCCESS) {
1596-
goto out;
1598+
goto out_try;
15971599
}
15981600
encoded_word = NULL;
15991601
if ((mode & PHP_ICONV_MIME_DECODE_STRICT)) {
@@ -1604,7 +1606,7 @@ static php_iconv_err_t _php_iconv_mime_decode(smart_str *pretval, const char *st
16041606
break;
16051607
} else {
16061608
err = PHP_ICONV_ERR_UNKNOWN;
1607-
goto out;
1609+
goto out_try;
16081610
}
16091611
}
16101612

@@ -1623,7 +1625,7 @@ static php_iconv_err_t _php_iconv_mime_decode(smart_str *pretval, const char *st
16231625
break;
16241626
}
16251627
} else {
1626-
goto out;
1628+
goto out_try;
16271629
}
16281630
}
16291631

@@ -1744,7 +1746,7 @@ static php_iconv_err_t _php_iconv_mime_decode(smart_str *pretval, const char *st
17441746
err = PHP_ICONV_ERR_SUCCESS;
17451747
} else {
17461748
err = PHP_ICONV_ERR_MALFORMED;
1747-
goto out;
1749+
goto out_try;
17481750
}
17491751
}
17501752

@@ -1753,6 +1755,8 @@ static php_iconv_err_t _php_iconv_mime_decode(smart_str *pretval, const char *st
17531755
}
17541756

17551757
smart_str_0(pretval);
1758+
1759+
out_try: ;
17561760
} zend_catch {
17571761
bailout = true;
17581762
} zend_end_try();

ext/iconv/tests/gh21664.phpt

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
--TEST--
2+
GH-21664 (iconv_mime_decode/iconv_mime_encode bailout corruption)
3+
--EXTENSIONS--
4+
iconv
5+
--FILE--
6+
<?php
7+
$r = iconv_mime_decode("=?utf-8?Q?" . chr(0xA1) . "?= .");
8+
var_dump($r);
9+
10+
$r = iconv_mime_encode("Subject", "\x80", ["input-charset" => "UTF-8", "output-charset" => "UTF-8"]);
11+
var_dump($r);
12+
13+
echo "Done\n";
14+
?>
15+
--EXPECTF--
16+
Notice: iconv_mime_decode(): Detected an illegal character in input string in %s on line %d
17+
bool(false)
18+
19+
Notice: iconv_mime_encode(): Detected an illegal character in input string in %s on line %d
20+
bool(false)
21+
Done

0 commit comments

Comments
 (0)