1
0
mirror of https://github.com/moparisthebest/k-9 synced 2024-11-27 11:42:16 -05:00

Skip IMAP folders with names that are not correctly encoded.

Configure the CharsetDecoder to throw an exception if malformed input
is encountered. Not doing this can cause an endless loop that
allocates memory until the application dies with an OutOfMemory error.
Until we have support for both a folder display name and a raw folder
name we simply ignore folders with names that aren't correctly encoded
with the modified UTF-7 variant.

Fixes issue 3268

Credits: Bernhard Redl (aatdark) analysed the problem and wrote the
initial version of the fix.
This commit is contained in:
cketti 2011-04-28 04:46:01 +02:00
parent 037b0ff64d
commit b7a6dbd973

View File

@ -18,7 +18,10 @@ import java.net.URISyntaxException;
import java.net.URLDecoder; import java.net.URLDecoder;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.CharBuffer; import java.nio.CharBuffer;
import java.nio.charset.CharacterCodingException;
import java.nio.charset.Charset; import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CodingErrorAction;
import java.security.GeneralSecurityException; import java.security.GeneralSecurityException;
import java.security.SecureRandom; import java.security.SecureRandom;
import java.security.Security; import java.security.Security;
@ -373,7 +376,20 @@ public class ImapStore extends Store {
for (ImapResponse response : responses) { for (ImapResponse response : responses) {
if (ImapResponseParser.equalsIgnoreCase(response.get(0), commandResponse)) { if (ImapResponseParser.equalsIgnoreCase(response.get(0), commandResponse)) {
boolean includeFolder = true; boolean includeFolder = true;
String folder = decodeFolderName(response.getString(3));
String folder;
try {
folder = decodeFolderName(response.getString(3));
} catch (CharacterCodingException e) {
Log.w(K9.LOG_TAG, "Folder name not correctly encoded with the UTF-7 variant " +
"as defined by RFC 3501: " + response.getString(3), e);
//TODO: Use the raw name returned by the server for all commands that require
// a folder name. Use the decoded name only for showing it to the user.
// We currently just skip folders with malformed names.
continue;
}
if (mPathDelimeter == null) { if (mPathDelimeter == null) {
mPathDelimeter = response.getString(2); mPathDelimeter = response.getString(2);
@ -395,7 +411,7 @@ public class ImapStore extends Store {
if (folder.length() >= getCombinedPrefix().length()) { if (folder.length() >= getCombinedPrefix().length()) {
folder = folder.substring(getCombinedPrefix().length()); folder = folder.substring(getCombinedPrefix().length());
} }
if (!decodeFolderName(response.getString(3)).equalsIgnoreCase(getCombinedPrefix() + folder)) { if (!folder.equalsIgnoreCase(getCombinedPrefix() + folder)) {
includeFolder = false; includeFolder = false;
} }
} }
@ -492,14 +508,15 @@ public class ImapStore extends Store {
} }
} }
private String decodeFolderName(String name) { private String decodeFolderName(String name) throws CharacterCodingException {
/* /*
* Convert the encoded name to US-ASCII, then pass it through the modified UTF-7 * Convert the encoded name to US-ASCII, then pass it through the modified UTF-7
* decoder and return the Unicode String. * decoder and return the Unicode String.
*/ */
try { try {
byte[] encoded = name.getBytes("US-ASCII"); // Make sure the decoder throws an exception if it encounters an invalid encoding.
CharBuffer cb = mModifiedUtf7Charset.decode(ByteBuffer.wrap(encoded)); CharsetDecoder decoder = mModifiedUtf7Charset.newDecoder().onMalformedInput(CodingErrorAction.REPORT);
CharBuffer cb = decoder.decode(ByteBuffer.wrap(name.getBytes("US-ASCII")));
return cb.toString(); return cb.toString();
} catch (UnsupportedEncodingException uee) { } catch (UnsupportedEncodingException uee) {
/* /*