From: Christoph M. Becker Date: Sun, 12 Aug 2018 13:03:47 +0000 (+0200) Subject: Fix #53891: iconv_mime_encode() fails to Q-encode UTF-8 string X-Git-Tag: php-7.3.0beta3~7 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=eb03290754105dbefeb5a3d75c20e504cd82715b;p=php Fix #53891: iconv_mime_encode() fails to Q-encode UTF-8 string The minimum length of an encoded-word is actually the pure encoding overhead plus the length of the `output-charset` plus the minimum unit of encoded text, which is 4 for B-encoding and (for simplicity) 3 for Q-encoding. We also cater to the possibility that we need further encoded words, which would be split by the `line-break-chars` followed by a space character. Obviously, the former `out_charset_len + 12` is too simplistic and wrong in the given case (where the magic number would be 13). These simplifications are somewhat wasteful, but iconv_mime_encode() with Q-encoding is wasteful anyway (see bug 66828[1]), and the proper solution to convert the whole input to the desired output charset upfront, and applying the encoding afterwards appears too much a change for the stable releases. [1] --- diff --git a/NEWS b/NEWS index bf8fe5b9af..c61eff8523 100644 --- a/NEWS +++ b/NEWS @@ -16,6 +16,9 @@ PHP NEWS . Fixed bug #76285 (DOMDocument::formatOutput attribute sometimes ignored). (Andrew Nester, Laruence, Anatol) +- iconv: + . Fixed bug #53891 (iconv_mime_encode() fails to Q-encode UTF-8 string). (cmb) + - libxml: . Fixed bug #76777 ("public id" parameter of libxml_set_external_entity_loader callback undefined). (Ville Hukkamäki) diff --git a/ext/iconv/iconv.c b/ext/iconv/iconv.c index 2915e97be7..6f05e47bad 100644 --- a/ext/iconv/iconv.c +++ b/ext/iconv/iconv.c @@ -1224,8 +1224,9 @@ static php_iconv_err_t _php_iconv_mime_encode(smart_str *pretval, const char *fn do { size_t prev_in_left; size_t out_size; + size_t encoded_word_min_len = sizeof("=??X??=")-1 + out_charset_len + (enc_scheme == PHP_ICONV_ENC_SCHEME_BASE64 ? 4 : 3); - if (char_cnt < (out_charset_len + 12)) { + if (char_cnt < encoded_word_min_len + lfchars_len + 1) { /* lfchars must be encoded in ASCII here*/ smart_str_appendl(pretval, lfchars, lfchars_len); smart_str_appendc(pretval, ' '); diff --git a/ext/iconv/tests/bug53891.phpt b/ext/iconv/tests/bug53891.phpt new file mode 100644 index 0000000000..86ae9a9149 --- /dev/null +++ b/ext/iconv/tests/bug53891.phpt @@ -0,0 +1,22 @@ +--TEST-- +Bug #53891 (iconv_mime_encode() fails to Q-encode UTF-8 string) +--SKIPIF-- + +--FILE-- + 'Q', + 'input-charset' => 'utf-8', + 'output-charset' => 'utf-8', + 'line-length' => 74, + 'line-break-chars' => "\r\n", +); +var_dump(iconv_mime_encode('subject', "d obeybiubrsfqllpdtpge…", $preferences)); +?> +===DONE=== +--EXPECT-- +string(81) "subject: =?utf-8?Q?d=20obeybiubrsfqllp?==?utf-8?Q?dtpge?= + =?utf-8?Q?=E2=80=A6?=" +===DONE===