From 4be6e0ce91c0690d3cbf58bd7b76144e01fe2be7 Mon Sep 17 00:00:00 2001 From: Leah Neukirchen Date: Mon, 30 Aug 2021 18:11:51 +0200 Subject: [PATCH 1/2] blaze822: remove blaze822_mmap, never used. --- blaze822.c | 49 ------------------------------------------------- blaze822.h | 1 - 2 files changed, 50 deletions(-) diff --git a/blaze822.c b/blaze822.c index d3e17f0..e55ae49 100644 --- a/blaze822.c +++ b/blaze822.c @@ -664,55 +664,6 @@ blaze822_file(char *file) return 0; } -struct message * -blaze822_mmap(char *file) -{ - int fd = open(file, O_RDONLY); - if (fd < 0) - return 0; - - struct stat st; - if (fstat(fd, &st) < 0) - goto error; - - size_t len = st.st_size; - - struct message *mesg = malloc(sizeof (struct message)); - if (!mesg) - goto error; - - char *buf = mmap(0, len+1, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0); - if (buf == MAP_FAILED) { - free(mesg); - perror("mmap"); - goto error; - } - close(fd); - - char *end; - if ((end = mymemmem(buf, len, "\n\n", 2))) { - mesg->body = end+2; - } else if ((end = mymemmem(buf, len, "\r\n\r\n", 4))) { - mesg->body = end+4; - } else { - end = buf + len; - mesg->body = end; - } - - unfold_hdr(buf, end); - - mesg->msg = mesg->bodychunk = buf; - mesg->end = end; - mesg->bodyend = buf + len; - mesg->orig_header = 0; - - return mesg; - -error: - close(fd); - return 0; -} - size_t blaze822_headerlen(struct message *mesg) { diff --git a/blaze822.h b/blaze822.h index 9aae8a5..ad5cc76 100644 --- a/blaze822.h +++ b/blaze822.h @@ -14,7 +14,6 @@ struct message; struct message *blaze822(char *file); // just header struct message *blaze822_file(char *file); // header + body (read(2)) -struct message *blaze822_mmap(char *file); // header + body (mmap(2)) struct message *blaze822_mem(char *buf, size_t len); // header + body char *blaze822_hdr_(struct message *mesg, const char *hdr, size_t len); From 41bd429452f45cb43110ec4699871a2cbd9c0a5e Mon Sep 17 00:00:00 2001 From: Leah Neukirchen Date: Mon, 30 Aug 2021 17:49:32 +0200 Subject: [PATCH 2/2] blaze822: blaze822/blaze822_mem: detect line ending before scanning end of header A mail using CRLF which contained (for some reason) a LFLF pair would be misparsed as the header was read until the LFLF. Instead, scan for the first LF, check if it's preceded by CR, and then search for the proper header terminator only. Closes #212. --- blaze822.c | 43 ++++++++++++++++++++++++++++++------------ t/1701-mshow-regress.t | 29 ++++++++++++++++++++++++++++ 2 files changed, 60 insertions(+), 12 deletions(-) create mode 100755 t/1701-mshow-regress.t diff --git a/blaze822.c b/blaze822.c index e55ae49..9262f6f 100644 --- a/blaze822.c +++ b/blaze822.c @@ -420,10 +420,19 @@ unfold_hdr(char *buf, char *end) compress_hdr(l, end); } +static int +is_crlf(char *s, size_t len) +{ + char *firsteol = memchr(s, '\n', len); + + return firsteol && firsteol > s && firsteol[-1] == '\r'; +} + struct message * blaze822(char *file) { int fd; + int crlf; ssize_t rd; char *buf; ssize_t bufalloc; @@ -466,15 +475,21 @@ blaze822(char *file) close(fd); return 0; } - - if ((end = mymemmem(buf-overlap+used, rd+overlap, "\n\n", 2))) { - end++; - break; + if (used == 0) { + crlf = is_crlf(buf, rd); } - if ((end = mymemmem(buf-overlap+used, rd+overlap, "\r\n\r\n", 4))) { - end++; - end++; - break; + + if (crlf) { + if ((end = mymemmem(buf-overlap+used, rd+overlap, "\r\n\r\n", 4))) { + end++; + end++; + break; + } + } else { + if ((end = mymemmem(buf-overlap+used, rd+overlap, "\n\n", 2))) { + end++; + break; + } } used += rd; @@ -502,11 +517,15 @@ blaze822_mem(char *src, size_t len) if (!mesg) return 0; - if ((end = mymemmem(src, len, "\n\n", 2))) { - mesg->body = end+2; - } else if ((end = mymemmem(src, len, "\r\n\r\n", 4))) { - mesg->body = end+4; + if (is_crlf(src, len)) { + if ((end = mymemmem(src, len, "\r\n\r\n", 4))) + mesg->body = end+4; } else { + if ((end = mymemmem(src, len, "\n\n", 2))) + mesg->body = end+2; + } + + if (!end) { end = src + len; mesg->body = end; mesg->bodyend = end; diff --git a/t/1701-mshow-regress.t b/t/1701-mshow-regress.t new file mode 100755 index 0000000..ffb676d --- /dev/null +++ b/t/1701-mshow-regress.t @@ -0,0 +1,29 @@ +#!/bin/sh -e +cd ${0%/*} +. ./lib.sh +plan 2 + +# Mail with \n\n and \r\n\r\n +cr=$(printf '\r') +cat <tmp +Content-Type: multipart/form-data; boundary=------------------------55a586f81559face$cr +$cr +--------------------------55a586f81559face$cr +Content-Disposition: form-data; name="a"; filename="foo"$cr +Content-Type: application/octet-stream$cr +$cr +foo$cr + +previously there are two NL$cr +$cr +--------------------------55a586f81559face$cr +Content-Disposition: form-data; name="a"; filename="bar"$cr +Content-Type: application/octet-stream$cr +$cr +bar$cr +$cr +--------------------------55a586f81559face--$cr +EOF + +check 'mail has 3 attachments' 'mshow -t ./tmp | wc -l | grep 4' +check 'mail attachment foo has size 35' 'mshow -t ./tmp | grep size=35.*name=\"foo\"'