Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 37 additions & 33 deletions ext/iconv/iconv.c
Original file line number Diff line number Diff line change
Expand Up @@ -1030,7 +1030,7 @@ static php_iconv_err_t _php_iconv_mime_encode(smart_str *pretval, const char *fn

if (out_size <= out_reserved) {
err = PHP_ICONV_ERR_TOO_BIG;
goto out;
goto out_try;
}

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

case EILSEQ:
err = PHP_ICONV_ERR_ILLEGAL_SEQ;
goto out;
goto out_try;

case E2BIG:
if (prev_in_left == in_left) {
err = PHP_ICONV_ERR_TOO_BIG;
goto out;
goto out_try;
}
break;

default:
err = PHP_ICONV_ERR_UNKNOWN;
goto out;
goto out_try;
}
}

Expand All @@ -1063,15 +1063,15 @@ static php_iconv_err_t _php_iconv_mime_encode(smart_str *pretval, const char *fn
if (iconv(cd, NULL, NULL, (char **) &out_p, &out_left) == (size_t)-1) {
if (errno != E2BIG) {
err = PHP_ICONV_ERR_UNKNOWN;
goto out;
goto out_try;
}
} else {
break;
}

if (iconv(cd, NULL, NULL, NULL, NULL) == (size_t)-1) {
err = PHP_ICONV_ERR_UNKNOWN;
goto out;
goto out_try;
}

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

smart_str_appendl(pretval, ZSTR_VAL(encoded), ZSTR_LEN(encoded));
Expand Down Expand Up @@ -1123,28 +1123,28 @@ static php_iconv_err_t _php_iconv_mime_encode(smart_str *pretval, const char *fn
switch (errno) {
case EINVAL:
err = PHP_ICONV_ERR_ILLEGAL_CHAR;
goto out;
goto out_try;

case EILSEQ:
err = PHP_ICONV_ERR_ILLEGAL_SEQ;
goto out;
goto out_try;

case E2BIG:
if (prev_in_left == in_left) {
err = PHP_ICONV_ERR_UNKNOWN;
goto out;
goto out_try;
}
break;

default:
err = PHP_ICONV_ERR_UNKNOWN;
goto out;
goto out_try;
}
}
if (iconv(cd, NULL, NULL, (char **) &out_p, &out_left) == (size_t)-1) {
if (errno != E2BIG) {
err = PHP_ICONV_ERR_UNKNOWN;
goto out;
goto out_try;
}
}

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

if (iconv(cd, NULL, NULL, NULL, NULL) == (size_t)-1) {
err = PHP_ICONV_ERR_UNKNOWN;
goto out;
goto out_try;
}

} break; /* case PHP_ICONV_ENC_SCHEME_QPRINT: */
}
} while (in_left > 0);

smart_str_0(pretval);

out_try: ;
} zend_catch {
bailout = true;
} zend_end_try();
Expand Down Expand Up @@ -1278,7 +1280,7 @@ static php_iconv_err_t _php_iconv_mime_decode(smart_str *pretval, const char *st
if (mode & PHP_ICONV_MIME_DECODE_CONTINUE_ON_ERROR) {
err = PHP_ICONV_ERR_SUCCESS;
} else {
goto out;
goto out_try;
}
}
encoded_word = NULL;
Expand All @@ -1296,7 +1298,7 @@ static php_iconv_err_t _php_iconv_mime_decode(smart_str *pretval, const char *st
}
err = _php_iconv_appendl(pretval, encoded_word, (size_t)((p1 + 1) - encoded_word), cd_pl);
if (err != PHP_ICONV_ERR_SUCCESS) {
goto out;
goto out_try;
}
encoded_word = NULL;
if ((mode & PHP_ICONV_MIME_DECODE_STRICT)) {
Expand Down Expand Up @@ -1326,7 +1328,7 @@ static php_iconv_err_t _php_iconv_mime_decode(smart_str *pretval, const char *st
_php_iconv_appendc(pretval, '?', cd_pl);
err = _php_iconv_appendl(pretval, csname, (size_t)((p1 + 1) - csname), cd_pl);
if (err != PHP_ICONV_ERR_SUCCESS) {
goto out;
goto out_try;
}
csname = NULL;
if ((mode & PHP_ICONV_MIME_DECODE_STRICT)) {
Expand All @@ -1342,7 +1344,7 @@ static php_iconv_err_t _php_iconv_mime_decode(smart_str *pretval, const char *st

if (csname == NULL) {
err = PHP_ICONV_ERR_MALFORMED;
goto out;
goto out_try;
}

csname_len = (size_t)(p1 - csname);
Expand All @@ -1351,7 +1353,7 @@ static php_iconv_err_t _php_iconv_mime_decode(smart_str *pretval, const char *st
if ((mode & PHP_ICONV_MIME_DECODE_CONTINUE_ON_ERROR)) {
err = _php_iconv_appendl(pretval, encoded_word, (size_t)((p1 + 1) - encoded_word), cd_pl);
if (err != PHP_ICONV_ERR_SUCCESS) {
goto out;
goto out_try;
}
encoded_word = NULL;
if ((mode & PHP_ICONV_MIME_DECODE_STRICT)) {
Expand All @@ -1362,7 +1364,7 @@ static php_iconv_err_t _php_iconv_mime_decode(smart_str *pretval, const char *st
break;
} else {
err = PHP_ICONV_ERR_MALFORMED;
goto out;
goto out_try;
}
}

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

err = _php_iconv_appendl(pretval, encoded_word, (size_t)((p1 + 1) - encoded_word), cd_pl);
if (err != PHP_ICONV_ERR_SUCCESS) {
goto out;
goto out_try;
}

/* Let's go back and see if there are further
Expand All @@ -1423,7 +1425,7 @@ static php_iconv_err_t _php_iconv_mime_decode(smart_str *pretval, const char *st
} else {
err = PHP_ICONV_ERR_CONVERTER;
}
goto out;
goto out_try;
}
}
}
Expand All @@ -1447,7 +1449,7 @@ static php_iconv_err_t _php_iconv_mime_decode(smart_str *pretval, const char *st
if ((mode & PHP_ICONV_MIME_DECODE_CONTINUE_ON_ERROR)) {
err = _php_iconv_appendl(pretval, encoded_word, (size_t)((p1 + 1) - encoded_word), cd_pl);
if (err != PHP_ICONV_ERR_SUCCESS) {
goto out;
goto out_try;
}
encoded_word = NULL;
if ((mode & PHP_ICONV_MIME_DECODE_STRICT)) {
Expand All @@ -1458,7 +1460,7 @@ static php_iconv_err_t _php_iconv_mime_decode(smart_str *pretval, const char *st
break;
} else {
err = PHP_ICONV_ERR_MALFORMED;
goto out;
goto out_try;
}
}
break;
Expand All @@ -1469,7 +1471,7 @@ static php_iconv_err_t _php_iconv_mime_decode(smart_str *pretval, const char *st
/* pass the entire chunk through the converter */
err = _php_iconv_appendl(pretval, encoded_word, (size_t)((p1 + 1) - encoded_word), cd_pl);
if (err != PHP_ICONV_ERR_SUCCESS) {
goto out;
goto out_try;
}
encoded_word = NULL;
if ((mode & PHP_ICONV_MIME_DECODE_STRICT)) {
Expand All @@ -1480,7 +1482,7 @@ static php_iconv_err_t _php_iconv_mime_decode(smart_str *pretval, const char *st
break;
} else {
err = PHP_ICONV_ERR_MALFORMED;
goto out;
goto out_try;
}
}
encoded_text = p1 + 1;
Expand Down Expand Up @@ -1525,7 +1527,7 @@ static php_iconv_err_t _php_iconv_mime_decode(smart_str *pretval, const char *st
/* pass the entire chunk through the converter */
err = _php_iconv_appendl(pretval, encoded_word, (size_t)((p1 + 1) - encoded_word), cd_pl);
if (err != PHP_ICONV_ERR_SUCCESS) {
goto out;
goto out_try;
}
encoded_word = NULL;
if ((mode & PHP_ICONV_MIME_DECODE_STRICT)) {
Expand All @@ -1536,7 +1538,7 @@ static php_iconv_err_t _php_iconv_mime_decode(smart_str *pretval, const char *st
break;
} else {
err = PHP_ICONV_ERR_MALFORMED;
goto out;
goto out_try;
}
}
scan_stat = 9;
Expand Down Expand Up @@ -1564,7 +1566,7 @@ static php_iconv_err_t _php_iconv_mime_decode(smart_str *pretval, const char *st
/* pass the entire chunk through the converter */
err = _php_iconv_appendl(pretval, encoded_word, (size_t)((p1 + 1) - encoded_word), cd_pl);
if (err != PHP_ICONV_ERR_SUCCESS) {
goto out;
goto out_try;
}
scan_stat = 12;
break;
Expand Down Expand Up @@ -1593,7 +1595,7 @@ static php_iconv_err_t _php_iconv_mime_decode(smart_str *pretval, const char *st
/* pass the entire chunk through the converter */
err = _php_iconv_appendl(pretval, encoded_word, (size_t)((p1 + 1) - encoded_word), cd_pl);
if (err != PHP_ICONV_ERR_SUCCESS) {
goto out;
goto out_try;
}
encoded_word = NULL;
if ((mode & PHP_ICONV_MIME_DECODE_STRICT)) {
Expand All @@ -1604,7 +1606,7 @@ static php_iconv_err_t _php_iconv_mime_decode(smart_str *pretval, const char *st
break;
} else {
err = PHP_ICONV_ERR_UNKNOWN;
goto out;
goto out_try;
}
}

Expand All @@ -1623,7 +1625,7 @@ static php_iconv_err_t _php_iconv_mime_decode(smart_str *pretval, const char *st
break;
}
} else {
goto out;
goto out_try;
}
}

Expand Down Expand Up @@ -1744,7 +1746,7 @@ static php_iconv_err_t _php_iconv_mime_decode(smart_str *pretval, const char *st
err = PHP_ICONV_ERR_SUCCESS;
} else {
err = PHP_ICONV_ERR_MALFORMED;
goto out;
goto out_try;
}
}

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

smart_str_0(pretval);

out_try: ;
} zend_catch {
bailout = true;
} zend_end_try();
Expand Down
21 changes: 21 additions & 0 deletions ext/iconv/tests/gh21664.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
--TEST--
GH-21664 (iconv_mime_decode/iconv_mime_encode bailout corruption)
--EXTENSIONS--
iconv
--FILE--
<?php
$r = iconv_mime_decode("=?utf-8?Q?" . chr(0xA1) . "?= .");
var_dump($r);

$r = iconv_mime_encode("Subject", "\x80", ["input-charset" => "UTF-8", "output-charset" => "UTF-8"]);
var_dump($r);

echo "Done\n";
?>
--EXPECTF--
Notice: iconv_mime_decode(): Detected an illegal character in input string in %s on line %d
bool(false)

Notice: iconv_mime_encode(): Detected an illegal character in input string in %s on line %d
bool(false)
Done
Loading