From f0ecdd04d3cd3c8814a296c3a9d2211086b7abd8 Mon Sep 17 00:00:00 2001 From: Steve Holme Date: Fri, 12 Dec 2014 18:37:06 +0000 Subject: [PATCH] smtp: Fixed dot stuffing when EOL characters were at end of input buffers Fixed a problem with the CRLF. detection when multiple buffers were used to upload an email to libcurl and the line ending character(s) appeared at the end of each buffer. This meant any lines which started with . would not be escaped into .. and could be interpreted as the end of transmission string instead. This only affected libcurl based applications that used a read function and wasn't reproducible with the curl command-line tool. Bug: http://curl.haxx.se/bug/view.cgi?id=1456 Assisted-by: Patrick Monnerat --- lib/smtp.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/lib/smtp.c b/lib/smtp.c index d57e62723..5c0b0a495 100644 --- a/lib/smtp.c +++ b/lib/smtp.c @@ -2322,6 +2322,7 @@ CURLcode Curl_smtp_escape_eob(struct connectdata *conn, const ssize_t nread) struct SMTP *smtp = data->req.protop; char *scratch = data->state.scratch; char *oldscratch = NULL; + size_t eob_sent; /* Do we need to allocate a scratch buffer? */ if(!scratch || data->set.crlf) { @@ -2335,6 +2336,9 @@ CURLcode Curl_smtp_escape_eob(struct connectdata *conn, const ssize_t nread) } } + /* Have we already sent part of the EOB? */ + eob_sent = smtp->eob; + /* 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++) { @@ -2349,8 +2353,8 @@ CURLcode Curl_smtp_escape_eob(struct connectdata *conn, const ssize_t nread) } else if(smtp->eob) { /* A previous substring matched so output that first */ - memcpy(&scratch[si], SMTP_EOB, smtp->eob); - si += smtp->eob; + memcpy(&scratch[si], SMTP_EOB + eob_sent, smtp->eob - eob_sent); + si += smtp->eob - eob_sent; /* Then compare the first byte */ if(SMTP_EOB[0] == data->req.upload_fromhere[i]) @@ -2358,6 +2362,8 @@ CURLcode Curl_smtp_escape_eob(struct connectdata *conn, const ssize_t nread) else smtp->eob = 0; + eob_sent = 0; + /* Reset the trailing CRLF flag as there was more data */ smtp->trailing_crlf = FALSE; } @@ -2365,19 +2371,19 @@ CURLcode Curl_smtp_escape_eob(struct connectdata *conn, const ssize_t nread) /* Do we have a match for CRLF. as per RFC-5321, sect. 4.5.2 */ if(SMTP_EOB_FIND_LEN == smtp->eob) { /* Copy the replacement data to the target buffer */ - memcpy(&scratch[si], SMTP_EOB_REPL, SMTP_EOB_REPL_LEN); - si += SMTP_EOB_REPL_LEN; + memcpy(&scratch[si], SMTP_EOB_REPL + eob_sent, SMTP_EOB_REPL_LEN - eob_sent); + si += SMTP_EOB_REPL_LEN - eob_sent; smtp->eob = 0; + eob_sent = 0; } else if(!smtp->eob) scratch[si++] = data->req.upload_fromhere[i]; } - if(smtp->eob) { + if(smtp->eob - eob_sent) { /* A substring matched before processing ended so output that now */ - memcpy(&scratch[si], SMTP_EOB, smtp->eob); - si += smtp->eob; - smtp->eob = 0; + memcpy(&scratch[si], SMTP_EOB + eob_sent, smtp->eob - eob_sent); + si += smtp->eob - eob_sent; } /* Only use the new buffer if we replaced something */