From 7c0663e0e52361461f525db546d324f40de5c61e Mon Sep 17 00:00:00 2001 From: Christian Neukirchen Date: Wed, 13 Jul 2016 15:22:47 +0200 Subject: blaze822: don't prefix first header with nul bytes Instead, look for the first header as a special case. This allows us to parse a header as-is without shifting in memory. --- blaze822.c | 184 ++++++++++++++++++++++++------------------------------------- 1 file changed, 73 insertions(+), 111 deletions(-) (limited to 'blaze822.c') diff --git a/blaze822.c b/blaze822.c index 31ef844..33caba1 100644 --- a/blaze822.c +++ b/blaze822.c @@ -227,6 +227,52 @@ blaze822_addr(char *s, char **dispo, char **addro) return s; } +static void +unfold_hdr(char *buf, char *end) +{ + char *s = buf; + + while (s < end && *s != ':') { + *s = lc(*s); + s++; + } + + for (; s < end; s++) { + if (*s == 0) // sanitize nul bytes in headers + *s = ' '; + + if (*s == '\r') { + if (*(s+1) == '\n') { + *s++ = '\n'; + } else { + *s = ' '; + } + } + + if (iswsp(*s)) { + // change prior \n to spaces + int j; + for (j = 1; s - j >= buf && *(s-j) == '\n'; j++) + *(s-j) = ' '; + } + + if (*s == '\n') { + s++; + if (iswsp(*s)) { + *(s-1) = ' '; + } else { + *(s-1) = 0; + if (s-2 > buf && *(s-2) == '\n') // ex-crlf + *(s-2) = 0; + while (s < end && *s != ':') { + *s = lc(*s); + s++; + } + } + } + } +} + struct message * blaze822(char *file) { @@ -237,25 +283,27 @@ blaze822(char *file) ssize_t used; char *end; + struct message *mesg = malloc(sizeof (struct message)); + if (!mesg) + return 0; + fd = open(file, O_RDONLY); if (fd < 0) { // perror("open"); return 0; } - buf = malloc(3); - if (!buf) - return 0; - buf[0] = '\n'; - buf[1] = '\n'; - buf[2] = '\n'; - bufalloc = 3; - used = 3; + buf = 0; + bufalloc = 0; + used = 0; while (1) { + int overlap = used > 3 ? 3 : 0; + bufalloc += bufsiz; buf = realloc(buf, bufalloc); if (!buf) { + free(mesg); close(fd); return 0; } @@ -266,13 +314,14 @@ blaze822(char *file) break; } if (rd < 0) { + free(mesg); free(buf); close(fd); return 0; } - if ((end = memmem(buf-1+used, rd+1, "\n\n", 2)) || - (end = memmem(buf-3+used, rd+3, "\r\n\r\n", 4))) { + if ((end = memmem(buf-overlap+used, rd+overlap, "\n\n", 2)) || + (end = memmem(buf-overlap+used, rd+overlap, "\r\n\r\n", 4))) { used += rd; end++; break; @@ -284,51 +333,7 @@ blaze822(char *file) *end = 0; // dereferencing *end is safe - char *s; - for (s = buf; s < end; s++) { - if (*s == 0) // sanitize nul bytes in headers - *s = ' '; - - if (*s == '\r') { - if (*(s+1) == '\n') { - *s++ = '\n'; - } else { - *s = ' '; - } - } - - if (iswsp(*s)) { - // change prior \n to spaces - int j; - for (j = 1; s - j >= buf && *(s-j) == '\n'; j++) - *(s-j) = ' '; - } - - if (*s == '\n') { - s++; - if (iswsp(*s)) { - *(s-1) = ' '; - } else { - *(s-1) = 0; - if (s-2 > buf && *(s-2) == '\n') // ex-crlf - *(s-2) = 0; - while (s < end && *s != ':') { - *s = lc(*s); - s++; - } - } - } - } - - buf[0] = 0; - buf[1] = 0; - buf[2] = 0; - - struct message *mesg = malloc(sizeof (struct message)); - if (!mesg) { - free(buf); - return 0; - } + unfold_hdr(buf, end); mesg->msg = buf; mesg->end = end; @@ -345,12 +350,9 @@ blaze822_mem(char *src, size_t len) char *buf; char *end; - buf = malloc(3); - if (!buf) + struct message *mesg = malloc(sizeof (struct message)); + if (!mesg) return 0; - buf[0] = '\n'; - buf[1] = '\n'; - buf[2] = '\n'; end = memmem(src, len, "\n\n", 2); if (!end) end = memmem(src, len, "\r\n\r\n", 4); @@ -358,59 +360,15 @@ blaze822_mem(char *src, size_t len) len = end - src; - buf = realloc(buf, len+3+1); - memcpy(buf+3, src, len); + buf = malloc(len+1); + if (!buf) + return 0; + memcpy(buf, src, len); - end = buf+3+1+len; + end = buf+len+1; *end = 0; // dereferencing *end is safe - /// XXX merge with below - - char *s; - for (s = buf; s < end; s++) { - if (*s == 0) // sanitize nul bytes in headers - *s = ' '; - - if (*s == '\r') { - if (*(s+1) == '\n') { - *s++ = '\n'; - } else { - *s = ' '; - } - } - - if (iswsp(*s)) { - // change prior \n to spaces - int j; - for (j = 1; s - j >= buf && *(s-j) == '\n'; j++) - *(s-j) = ' '; - } - - if (*s == '\n') { - s++; - if (iswsp(*s)) { - *(s-1) = ' '; - } else { - *(s-1) = 0; - if (s-2 > buf && *(s-2) == '\n') // ex-crlf - *(s-2) = 0; - while (s < end && *s != ':') { - *s = lc(*s); - s++; - } - } - } - } - - buf[0] = 0; - buf[1] = 0; - buf[2] = 0; - - struct message *mesg = malloc(sizeof (struct message)); - if (!mesg) { - free(buf); - return 0; - } + unfold_hdr(buf, end); mesg->msg = buf; mesg->end = end; @@ -440,7 +398,11 @@ blaze822_hdr_(struct message *mesg, const char *hdr, size_t hdrlen) { char *v; - v = memmem(mesg->msg, mesg->end - mesg->msg, hdr, hdrlen); + // special case: first header, no leading nul + if (memcmp(mesg->msg, hdr+1, hdrlen-1) == 0) + v = mesg->msg; + else + v = memmem(mesg->msg, mesg->end - mesg->msg, hdr, hdrlen); if (!v) return 0; v += hdrlen; -- cgit 1.4.1