From 8fe771a9e352ed3e2b0c9a72d85a70aaf3f7d951 Mon Sep 17 00:00:00 2001 From: Marc Blank Date: Fri, 14 Sep 2012 11:38:31 -0700 Subject: [PATCH] Prevent infinite loops (ugh); fix list parsing * We weren't accounting for string literals in list parsing * We didn't account for a null result in bodystructure parse Bug: 7162595 Change-Id: Idf0ae135dcfb968c722ab9fb56d5d253e74bd623 --- .../android/email/imap2/Imap2SyncService.java | 114 ++++++++++-------- src/com/android/email/imap2/Parser.java | 19 ++- 2 files changed, 74 insertions(+), 59 deletions(-) diff --git a/src/com/android/email/imap2/Imap2SyncService.java b/src/com/android/email/imap2/Imap2SyncService.java index 400354543..97a125810 100644 --- a/src/com/android/email/imap2/Imap2SyncService.java +++ b/src/com/android/email/imap2/Imap2SyncService.java @@ -26,6 +26,7 @@ import android.database.Cursor; import android.net.TrafficStats; import android.net.Uri; import android.os.Bundle; +import android.os.Debug; import android.os.RemoteException; import android.util.Base64; import android.util.Log; @@ -465,7 +466,6 @@ public class Imap2SyncService extends AbstractSyncService { Parser p = new Parser(str, str.indexOf('(') + 1); Date date = null; String subject = null; - String sender = null; boolean read = false; int flag = 0; String flags = null; @@ -490,7 +490,7 @@ public class Imap2SyncService extends AbstractSyncService { //date = parseDate(ep.parseString()); ep.parseString(); subject = ep.parseString(); - sender = parseRecipients(ep, msg); + parseRecipients(ep, msg); } else if (atm.equalsIgnoreCase("FLAGS")) { flags = p.parseList().toLowerCase(); if (flags.indexOf("\\seen") >=0) @@ -506,11 +506,9 @@ public class Imap2SyncService extends AbstractSyncService { } catch (Exception e) { // Parsing error here. We've got one known one from EON // in which BODYSTRUCTURE is ( "MIXED" (....) ) - if (sender == null) - sender = "Unknown sender"; - if (subject == null) - subject = "No subject"; e.printStackTrace(); + // We'll skip the message + return null; } if (subject != null && subject.startsWith("=?")) @@ -1075,56 +1073,64 @@ public class Imap2SyncService extends AbstractSyncService { while (c.moveToNext()) { // Parse the message's bodystructure Message msg = new Message(); - msg.restore(c); - ArrayList viewables = new ArrayList(); - ArrayList attachments = new ArrayList(); - parseBodystructure(msg, new Parser(msg.mSyncData), "", 1, viewables, - attachments); - ContentValues values = new ContentValues(); - values.put(MessageColumns.FLAG_LOADED, Message.FLAG_LOADED_COMPLETE); - // Save the attachments... - for (Attachment att: attachments) { - att.mAccountKey = mAccountId; - att.mMessageKey = msg.mId; - att.save(mContext); - } - // Whether or not we have attachments - values.put(MessageColumns.FLAG_ATTACHMENT, !attachments.isEmpty()); - // Get the viewables - Attachment textViewable = null; - for (Attachment viewable: viewables) { - String mimeType = viewable.mMimeType; - if ("text/html".equalsIgnoreCase(mimeType)) { - textViewable = viewable; - } else if ("text/plain".equalsIgnoreCase(mimeType) && - textViewable == null) { - textViewable = viewable; + try { + msg.restore(c); + ArrayList viewables = new ArrayList(); + ArrayList attachments = new ArrayList(); + parseBodystructure(msg, new Parser(msg.mSyncData), "", 1, viewables, + attachments); + ContentValues values = new ContentValues(); + values.put(MessageColumns.FLAG_LOADED, Message.FLAG_LOADED_COMPLETE); + // Save the attachments... + for (Attachment att: attachments) { + att.mAccountKey = mAccountId; + att.mMessageKey = msg.mId; + att.save(mContext); } - } - if (textViewable != null) { - // For now, just get single viewable - String tag = writeCommand(conn.writer, - "uid fetch " + msg.mServerId + " body.peek[" + - textViewable.mLocation + "]<0.200000>"); - String text = readTextPart(conn.reader, tag, textViewable, true); - userLog("Viewable " + textViewable.mMimeType + ", len = " + text.length()); - // Save it away - Body body = new Body(); - if (textViewable.mMimeType.equalsIgnoreCase("text/html")) { - body.mHtmlContent = text; + // Whether or not we have attachments + values.put(MessageColumns.FLAG_ATTACHMENT, !attachments.isEmpty()); + // Get the viewables + Attachment textViewable = null; + for (Attachment viewable: viewables) { + String mimeType = viewable.mMimeType; + if ("text/html".equalsIgnoreCase(mimeType)) { + textViewable = viewable; + } else if ("text/plain".equalsIgnoreCase(mimeType) && + textViewable == null) { + textViewable = viewable; + } + } + if (textViewable != null) { + // For now, just get single viewable + String tag = writeCommand(conn.writer, + "uid fetch " + msg.mServerId + " body.peek[" + + textViewable.mLocation + "]<0.200000>"); + String text = readTextPart(conn.reader, tag, textViewable, true); + userLog("Viewable " + textViewable.mMimeType + ", len = " + + text.length()); + // Save it away + Body body = new Body(); + if (textViewable.mMimeType.equalsIgnoreCase("text/html")) { + body.mHtmlContent = text; + } else { + body.mTextContent = text; + } + body.mMessageKey = msg.mId; + body.save(mContext); + values.put(MessageColumns.SNIPPET, + TextUtilities.makeSnippetFromHtmlText(text)); } else { - body.mTextContent = text; + userLog("No viewable?"); + values.putNull(MessageColumns.SNIPPET); } - body.mMessageKey = msg.mId; - body.save(mContext); - values.put(MessageColumns.SNIPPET, - TextUtilities.makeSnippetFromHtmlText(text)); - } else { - userLog("No viewable?"); - values.putNull(MessageColumns.SNIPPET); + mResolver.update(ContentUris.withAppendedId( + Message.CONTENT_URI, msg.mId), values, null, null); + } catch (Exception e) { + // We can't let the loop continue; log this with stack trace + userLog("Message can't be parsed; skipping...", e); + mResolver.delete(ContentUris.withAppendedId(Message.CONTENT_URI, msg.mId), + null, null); } - mResolver.update(ContentUris.withAppendedId( - Message.CONTENT_URI, msg.mId), values, null, null); } } finally { if (c != null) { @@ -2009,7 +2015,9 @@ public class Imap2SyncService extends AbstractSyncService { // Create message and store for (int j = 0; j < tcnt; j++) { Message msg = createMessage(mImapResponse.get(j), mailboxId); - tmsgList.add(msg); + if (msg != null) { + tmsgList.add(msg); + } } saveNewMessages(tmsgList); } diff --git a/src/com/android/email/imap2/Parser.java b/src/com/android/email/imap2/Parser.java index 239298ede..c98811870 100644 --- a/src/com/android/email/imap2/Parser.java +++ b/src/com/android/email/imap2/Parser.java @@ -138,17 +138,24 @@ public class Parser { boolean string = false; while (true) { char c = nextChar(); - if (c == 0) + if (c == 0) { return null; - else if (quote) + } else if (quote) { quote = false; - else if (c == '\\' && string) + } else if (c == '\\' && string) { quote = true; - else if (c == '\"') + } else if (c == '\"') { string = !string; - else if (c == '(' && !string) + } else if (c == '(' && !string) { level++; - else if (c == ')' && !string) { + } else if (c == '{' && !string) { + // Check for string literal + Parser p = new Parser(str, pos); + int cnt = p.parseInteger(); + if (cnt > 0 && p.nextChar() == '}') { + pos = p.pos + 2 + cnt; + } + } else if (c == ')' && !string) { if (level-- == 0) break; }