about summary refs log tree commit diff
diff options
context:
space:
mode:
authorLeah Neukirchen <leah@vuxu.org>2020-11-12 15:24:20 +0100
committerLeah Neukirchen <leah@vuxu.org>2020-11-12 15:28:49 +0100
commit5167bbfe39c4e87c6aeeafce4546ca19878b4fef (patch)
treec2d0bbe991eda7daff70996df98295792844dc8f
parent5e6151e3bf8aa13a3849997ed49953362887ff5a (diff)
downloadmblaze-5167bbfe39c4e87c6aeeafce4546ca19878b4fef.tar.gz
mblaze-5167bbfe39c4e87c6aeeafce4546ca19878b4fef.tar.xz
mblaze-5167bbfe39c4e87c6aeeafce4546ca19878b4fef.zip
rfc2045: ensure mime boundaries end with a newline or -
-rw-r--r--rfc2045.c24
-rwxr-xr-xt/1700-mshow.t41
2 files changed, 63 insertions, 2 deletions
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 <<EOF >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'