aharvey Thu, 30 Sep 2010 11:04:21 +0000 Revision: http://svn.php.net/viewvc?view=revision&revision=303890
Log: Fixed bug #52941 (The 'iconv_mime_decode_headers' function is skipping headers). Bug: http://bugs.php.net/52941 (Assigned) The 'iconv_mime_decode_headers' function is skipping headers Changed paths: U php/php-src/branches/PHP_5_3/NEWS U php/php-src/branches/PHP_5_3/ext/iconv/iconv.c A php/php-src/branches/PHP_5_3/ext/iconv/tests/bug52941.phpt U php/php-src/trunk/ext/iconv/iconv.c A php/php-src/trunk/ext/iconv/tests/bug52941.phpt Modified: php/php-src/branches/PHP_5_3/NEWS =================================================================== --- php/php-src/branches/PHP_5_3/NEWS 2010-09-30 09:21:50 UTC (rev 303889) +++ php/php-src/branches/PHP_5_3/NEWS 2010-09-30 11:04:21 UTC (rev 303890) @@ -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 Modified: php/php-src/branches/PHP_5_3/ext/iconv/iconv.c =================================================================== --- php/php-src/branches/PHP_5_3/ext/iconv/iconv.c 2010-09-30 09:21:50 UTC (rev 303889) +++ php/php-src/branches/PHP_5_3/ext/iconv/iconv.c 2010-09-30 11:04:21 UTC (rev 303890) @@ -1457,16 +1457,43 @@ 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 Added: php/php-src/branches/PHP_5_3/ext/iconv/tests/bug52941.phpt =================================================================== --- php/php-src/branches/PHP_5_3/ext/iconv/tests/bug52941.phpt (rev 0) +++ php/php-src/branches/PHP_5_3/ext/iconv/tests/bug52941.phpt 2010-09-30 11:04:21 UTC (rev 303890) @@ -0,0 +1,41 @@ +--TEST-- +Bug #52941 (The 'iconv_mime_decode_headers' function is skipping headers) +--SKIPIF-- +<?php extension_loaded('iconv') or die('skip iconv extension is not available'); ?> +--FILE-- +<?php +$headers = <<<HEADERS +From: =?UTF-8?B?PGZvb0BleGFtcGxlLmNvbT4=?= +Subject: =?ks_c_5601-1987?B?UkU6odk=?= +X-Foo: =?ks_c_5601-1987?B?UkU6odk=?= Foo +X-Bar: =?ks_c_5601-1987?B?UkU6odk=?= =?UTF-8?Q?Foo?= +To: <t...@example.com> +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) "<f...@example.com>" +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) "<t...@example.com>" +string(17) "<f...@example.com>" +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) "<t...@example.com>" Modified: php/php-src/trunk/ext/iconv/iconv.c =================================================================== --- php/php-src/trunk/ext/iconv/iconv.c 2010-09-30 09:21:50 UTC (rev 303889) +++ php/php-src/trunk/ext/iconv/iconv.c 2010-09-30 11:04:21 UTC (rev 303890) @@ -1521,16 +1521,43 @@ 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 Added: php/php-src/trunk/ext/iconv/tests/bug52941.phpt =================================================================== --- php/php-src/trunk/ext/iconv/tests/bug52941.phpt (rev 0) +++ php/php-src/trunk/ext/iconv/tests/bug52941.phpt 2010-09-30 11:04:21 UTC (rev 303890) @@ -0,0 +1,41 @@ +--TEST-- +Bug #52941 (The 'iconv_mime_decode_headers' function is skipping headers) +--SKIPIF-- +<?php extension_loaded('iconv') or die('skip iconv extension is not available'); ?> +--FILE-- +<?php +$headers = <<<HEADERS +From: =?UTF-8?B?PGZvb0BleGFtcGxlLmNvbT4=?= +Subject: =?ks_c_5601-1987?B?UkU6odk=?= +X-Foo: =?ks_c_5601-1987?B?UkU6odk=?= Foo +X-Bar: =?ks_c_5601-1987?B?UkU6odk=?= =?UTF-8?Q?Foo?= +To: <t...@example.com> +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) "<f...@example.com>" +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) "<t...@example.com>" +string(17) "<f...@example.com>" +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) "<t...@example.com>"
-- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php