From 5167bbfe39c4e87c6aeeafce4546ca19878b4fef Mon Sep 17 00:00:00 2001 From: Leah Neukirchen Date: Thu, 12 Nov 2020 15:24:20 +0100 Subject: rfc2045: ensure mime boundaries end with a newline or - --- rfc2045.c | 24 ++++++++++++++++++++++-- t/1700-mshow.t | 41 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+), 2 deletions(-) create mode 100755 t/1700-mshow.t diff --git a/rfc2045.c b/rfc2045.c index df48d57..2e29175 100644 --- a/rfc2045.c +++ b/rfc2045.c @@ -114,6 +114,26 @@ blaze822_mime_parameter(char *s, char *name, char **starto, char **stopo) return 1; } +// like mymemmem but check the match is followed by \r, \n or -. +static char * +mymemmemnl(const char *h0, size_t k, const char *n0, size_t l) +{ + char *r; + + while (k && (r = mymemmem(h0, k, n0, l))) { + if (r - h0 < (long)(k - l) && // check if r[l] safe to access + (r[l] == '\r' || r[l] == '\n' || r[l] == '-')) + return r; + else { + // skip over this match + k -= (r - h0) + 1; + h0 = r + 1; + } + } + + return 0; +} + int blaze822_multipart(struct message *msg, struct message **imsg) { @@ -144,7 +164,7 @@ blaze822_multipart(struct message *msg, struct message **imsg) else prevpart = msg->body; - char *part = mymemmem(prevpart, msg->bodyend - prevpart, mboundary, boundarylen); + char *part = mymemmemnl(prevpart, msg->bodyend - prevpart, mboundary, boundarylen); if (!part) return 0; @@ -158,7 +178,7 @@ blaze822_multipart(struct message *msg, struct message **imsg) else return 0; // XXX error condition? - char *nextpart = mymemmem(part, msg->bodyend - part, mboundary, boundarylen); + char *nextpart = mymemmemnl(part, msg->bodyend - part, mboundary, boundarylen); if (!nextpart) return 0; // XXX error condition if (nextpart == part) // invalid empty MIME part diff --git a/t/1700-mshow.t b/t/1700-mshow.t new file mode 100755 index 0000000..f974026 --- /dev/null +++ b/t/1700-mshow.t @@ -0,0 +1,41 @@ +#!/bin/sh -e +cd ${0%/*} +. ./lib.sh +plan 2 + +# Nested MIME where the outer boundary is a prefix of the inner boundary +cat <tmp +MIME-Version: 1.0 +Content-type: multipart/mixed; charset=iso-8859-1; + boundary="_xec5AqfRYxfhARmklHx" + + +--_xec5AqfRYxfhARmklHx +Content-type: Multipart/alternative; charset=iso-8859-1; + boundary="_xec5AqfRYxfhARmklHx8" + + +--_xec5AqfRYxfhARmklHx8 +Content-type: text/plain; charset=iso-8859-1 +Content-Transfer-Encoding: 7bit +Content-Disposition: inline + +foo +--_xec5AqfRYxfhARmklHx8 +Content-type: text/html; charset=iso-8859-1 +Content-Transfer-Encoding: Quoted-printable +Content-Disposition: inline + +bar +--_xec5AqfRYxfhARmklHx8-- + +--_xec5AqfRYxfhARmklHx +Content-Type: application/zip +Content-Transfer-Encoding: Base64 + +quux +--_xec5AqfRYxfhARmklHx-- +EOF + +check 'nested mail has 5 attachments' 'mshow -t ./tmp | wc -l | grep 6' +check 'nested mail has text/html attachment' 'mshow -t ./tmp | grep text/html' -- cgit 1.4.1