From 2621dd42a4d3e510e68f7d6a31ba325634d87ee6 Mon Sep 17 00:00:00 2001
From: Daniel Stenberg <daniel@haxx.se>
Date: Thu, 20 Oct 2011 00:13:09 +0200
Subject: [PATCH] Curl_smtp_escape_eob: fix EOB escaping

As the EOB string can come byte by byte over a series of writes we must
match byte-wise.

Bug: http://curl.haxx.se/mail/lib-2011-10/0172.html
---
 lib/smtp.c |   51 ++++++++++++++++++++++++++-------------------------
 1 files changed, 26 insertions(+), 25 deletions(-)

diff --git a/lib/smtp.c b/lib/smtp.c
index 141b04a..9a34a05 100644
--- a/lib/smtp.c
+++ b/lib/smtp.c
@@ -1661,35 +1661,36 @@ CURLcode Curl_smtp_escape_eob(struct connectdata *conn, ssize_t nread)
   }
   /* This loop can be improved by some kind of Boyer-Moore style of
      approach but that is saved for later... */
-  for(i = 0, si = 0; i < nread; i++, si++) {
-    ssize_t left = nread - i;
+  for(i = 0, si = 0; i < nread; i++) {
 
-    if(left >= (ssize_t)(SMTP_EOB_LEN - smtpc->eob)) {
-      if(!memcmp(SMTP_EOB + smtpc->eob, &data->req.upload_fromhere[i],
-                 SMTP_EOB_LEN - smtpc->eob)) {
-        /* It matched, copy the replacement data to the target buffer
-           instead. Note that the replacement does not contain the
-           trailing CRLF but we instead continue to match on that one
-           to deal with repeated sequences. Like CRLF.CRLF.CRLF etc
-        */
-        memcpy(&data->state.scratch[si], SMTP_EOB_REPL,
-               SMTP_EOB_REPL_LEN);
-        si += SMTP_EOB_REPL_LEN - 1; /* minus one since the for() increments
-                                        it */
-        i += SMTP_EOB_LEN - smtpc->eob - 1 - 2;
-        smtpc->eob = 0; /* start over */
-        continue;
-      }
+    if(SMTP_EOB[smtpc->eob] == data->req.upload_fromhere[i])
+      smtpc->eob++;
+    else if(smtpc->eob) {
+      /* previously a substring matched, output that first */
+      memcpy(&data->state.scratch[si], SMTP_EOB, smtpc->eob);
+      si += smtpc->eob;
+
+      /* then compare the first byte */
+      if(SMTP_EOB[smtpc->eob] == data->req.upload_fromhere[i])
+        smtpc->eob=1;
+      else
+        smtpc->eob = 0;
     }
-    else if(!memcmp(SMTP_EOB + smtpc->eob, &data->req.upload_fromhere[i],
-                    left)) {
-      /* the last piece of the data matches the EOB so we can't send that
-         until we know the rest of it */
-      smtpc->eob += left;
-      break;
+
+    if(SMTP_EOB_LEN == smtpc->eob) {
+      /* It matched, copy the replacement data to the target buffer
+         instead. Note that the replacement does not contain the
+         trailing CRLF but we instead continue to match on that one
+         to deal with repeated sequences. Like CRLF.CRLF.CRLF etc
+      */
+      memcpy(&data->state.scratch[si], SMTP_EOB_REPL,
+             SMTP_EOB_REPL_LEN);
+      si += SMTP_EOB_REPL_LEN;
+      smtpc->eob = 2; /* start over at two bytes */
     }
+    else if(!smtpc->eob)
+      data->state.scratch[si++] = data->req.upload_fromhere[i];
 
-    data->state.scratch[si] = data->req.upload_fromhere[i];
   } /* for() */
 
   if(si != nread) {
-- 
1.7.7

