From 5f9956397f6183d93ff0eb8121b2d20868cd1a29 Mon Sep 17 00:00:00 2001 From: Adam Harvey Date: Thu, 30 Sep 2010 11:04:21 +0000 Subject: [PATCH] Fixed bug #52941 (The 'iconv_mime_decode_headers' function is skipping headers). --- NEWS | 2 ++ ext/iconv/iconv.c | 39 ++++++++++++++++++++++++++++----- ext/iconv/tests/bug52941.phpt | 41 +++++++++++++++++++++++++++++++++++ 3 files changed, 76 insertions(+), 6 deletions(-) create mode 100644 ext/iconv/tests/bug52941.phpt diff --git a/NEWS b/NEWS index 930b4a09ff..99f84cf407 100644 --- a/NEWS +++ b/NEWS @@ -26,6 +26,8 @@ used). (Felipe) - Fixed bug #52944 (Invalid write on second and subsequent reads with an inflate filter fed invalid data). (Gustavo) +- Fixed bug #52941 (The 'iconv_mime_decode_headers' function is skipping + headers). (Adam) - Fixed bug #52931 (strripos not overloaded with function overloading enabled). (Felipe) - Fixed bug #52929 (Segfault in filter_var with FILTER_VALIDATE_EMAIL with diff --git a/ext/iconv/iconv.c b/ext/iconv/iconv.c index 0b9c60fa17..b1a9c0dd0e 100644 --- a/ext/iconv/iconv.c +++ b/ext/iconv/iconv.c @@ -1457,16 +1457,43 @@ static php_iconv_err_t _php_iconv_mime_decode(smart_str *pretval, const char *st if (cd == (iconv_t)(-1)) { if ((mode & PHP_ICONV_MIME_DECODE_CONTINUE_ON_ERROR)) { + /* Bad character set, but the user wants us to + * press on. In this case, we'll just insert the + * undecoded encoded word, since there isn't really + * a more sensible behaviour available; the only + * other options are to swallow the encoded word + * entirely or decode it with an arbitrarily chosen + * single byte encoding, both of which seem to have + * a higher WTF factor than leaving it undecoded. + * + * Given this approach, we need to skip ahead to + * the end of the encoded word. */ + int qmarks = 2; + while (qmarks > 0 && str_left > 1) { + if (*(++p1) == '?') { + --qmarks; + } + --str_left; + } + + /* Look ahead to check for the terminating = that + * should be there as well; if it's there, we'll + * also include that. If it's not, there isn't much + * we can do at this point. */ + if (*(p1 + 1) == '=') { + ++p1; + --str_left; + } + err = _php_iconv_appendl(pretval, encoded_word, (size_t)((p1 + 1) - encoded_word), cd_pl); if (err != PHP_ICONV_ERR_SUCCESS) { goto out; } - encoded_word = NULL; - if ((mode & PHP_ICONV_MIME_DECODE_STRICT)) { - scan_stat = 12; - } else { - scan_stat = 0; - } + + /* Let's go back and see if there are further + * encoded words or bare content, and hope they + * might actually have a valid character set. */ + scan_stat = 12; break; } else { #if ICONV_SUPPORTS_ERRNO diff --git a/ext/iconv/tests/bug52941.phpt b/ext/iconv/tests/bug52941.phpt new file mode 100644 index 0000000000..753c9ada14 --- /dev/null +++ b/ext/iconv/tests/bug52941.phpt @@ -0,0 +1,41 @@ +--TEST-- +Bug #52941 (The 'iconv_mime_decode_headers' function is skipping headers) +--SKIPIF-- + +--FILE-- + +HEADERS; + +$decoded = iconv_mime_decode_headers($headers, ICONV_MIME_DECODE_CONTINUE_ON_ERROR, 'UTF-8'); + +var_dump($decoded['From']); +var_dump($decoded['Subject']); +var_dump($decoded['X-Foo']); +var_dump($decoded['X-Bar']); +var_dump($decoded['To']); + +$decoded = iconv_mime_decode_headers($headers, ICONV_MIME_DECODE_CONTINUE_ON_ERROR | ICONV_MIME_DECODE_STRICT, 'UTF-8'); + +var_dump($decoded['From']); +var_dump($decoded['Subject']); +var_dump($decoded['X-Foo']); +var_dump($decoded['X-Bar']); +var_dump($decoded['To']); +?> +--EXPECT-- +string(17) "" +string(29) "=?ks_c_5601-1987?B?UkU6odk=?=" +string(33) "=?ks_c_5601-1987?B?UkU6odk=?= Foo" +string(32) "=?ks_c_5601-1987?B?UkU6odk=?=Foo" +string(18) "" +string(17) "" +string(29) "=?ks_c_5601-1987?B?UkU6odk=?=" +string(33) "=?ks_c_5601-1987?B?UkU6odk=?= Foo" +string(32) "=?ks_c_5601-1987?B?UkU6odk=?=Foo" +string(18) "" -- 2.50.1