Commit f0ecdd04 authored by Steve Holme's avatar Steve Holme
Browse files

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
parent 2f5c70b2
Loading
Loading
Loading
Loading
+14 −8
Original line number Diff line number Diff line
@@ -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 */