Skip to content

Commit eb03290

Browse files
committed
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] <https://bugs.php.net/66828>
1 parent 692e5d5 commit eb03290

File tree

3 files changed

+27
-1
lines changed

3 files changed

+27
-1
lines changed

NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ PHP NEWS
1616
. Fixed bug #76285 (DOMDocument::formatOutput attribute sometimes ignored).
1717
(Andrew Nester, Laruence, Anatol)
1818

19+
- iconv:
20+
. Fixed bug #53891 (iconv_mime_encode() fails to Q-encode UTF-8 string). (cmb)
21+
1922
- libxml:
2023
. Fixed bug #76777 ("public id" parameter of libxml_set_external_entity_loader
2124
callback undefined). (Ville Hukkamäki)

ext/iconv/iconv.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1224,8 +1224,9 @@ static php_iconv_err_t _php_iconv_mime_encode(smart_str *pretval, const char *fn
12241224
do {
12251225
size_t prev_in_left;
12261226
size_t out_size;
1227+
size_t encoded_word_min_len = sizeof("=??X??=")-1 + out_charset_len + (enc_scheme == PHP_ICONV_ENC_SCHEME_BASE64 ? 4 : 3);
12271228

1228-
if (char_cnt < (out_charset_len + 12)) {
1229+
if (char_cnt < encoded_word_min_len + lfchars_len + 1) {
12291230
/* lfchars must be encoded in ASCII here*/
12301231
smart_str_appendl(pretval, lfchars, lfchars_len);
12311232
smart_str_appendc(pretval, ' ');

ext/iconv/tests/bug53891.phpt

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
--TEST--
2+
Bug #53891 (iconv_mime_encode() fails to Q-encode UTF-8 string)
3+
--SKIPIF--
4+
<?php
5+
if (!extension_loaded('iconv')) die('skip iconv extension not available');
6+
?>
7+
--FILE--
8+
<?php
9+
$preferences = array(
10+
'scheme' => 'Q',
11+
'input-charset' => 'utf-8',
12+
'output-charset' => 'utf-8',
13+
'line-length' => 74,
14+
'line-break-chars' => "\r\n",
15+
);
16+
var_dump(iconv_mime_encode('subject', "d obeybiubrsfqllpdtpge…", $preferences));
17+
?>
18+
===DONE===
19+
--EXPECT--
20+
string(81) "subject: =?utf-8?Q?d=20obeybiubrsfqllp?==?utf-8?Q?dtpge?=
21+
=?utf-8?Q?=E2=80=A6?="
22+
===DONE===

0 commit comments

Comments
 (0)