diff --git a/COPYING b/COPYING index a17412d..d0ec9b0 100644 --- a/COPYING +++ b/COPYING @@ -6,4 +6,5 @@ has waived all copyright and related or neighboring rights to this work. http://creativecommons.org/publicdomain/zero/1.0/ -The file mystrverscmp.c is MIT-licensed and based on code by Rich Felker. +The files mystrverscmp.c and mymemmem.c +are MIT-licensed and were written by Rich Felker. diff --git a/Makefile b/Makefile index d853891..c9e6678 100644 --- a/Makefile +++ b/Makefile @@ -4,19 +4,19 @@ ALL = maddr mdeliver mdirs mflag mhdr minc mlist mmime mscan mseq mshow msort mt all: $(ALL) -maddr: maddr.o blaze822.o seq.o rfc2047.o -mdeliver: mdeliver.o blaze822.o +maddr: maddr.o blaze822.o seq.o rfc2047.o mymemmem.o +mdeliver: mdeliver.o blaze822.o mymemmem.o mdirs: mdirs.o -mflag: mflag.o blaze822.o seq.o -mhdr: mhdr.o blaze822.o seq.o rfc2047.o +mflag: mflag.o blaze822.o seq.o mymemmem.o +mhdr: mhdr.o blaze822.o seq.o rfc2047.o mymemmem.o minc: minc.o mlist: mlist.o mmime: mmime.o -mscan: mscan.o blaze822.o seq.o rfc2047.o +mscan: mscan.o blaze822.o seq.o rfc2047.o mymemmem.o mseq: mseq.o seq.o -mshow: mshow.o blaze822.o seq.o rfc2045.o rfc2047.c -msort: msort.o blaze822.o seq.o mystrverscmp.c -mthread: mthread.o blaze822.o seq.o +mshow: mshow.o blaze822.o seq.o rfc2045.o rfc2047.c mymemmem.o +msort: msort.o blaze822.o seq.o mystrverscmp.c mymemmem.o +mthread: mthread.o blaze822.o seq.o mymemmem.o README: man/mintro.7 mandoc -Tutf8 $< | col -bx >$@ diff --git a/blaze822.c b/blaze822.c index 4feddfc..373ec90 100644 --- a/blaze822.c +++ b/blaze822.c @@ -1,6 +1,3 @@ -// memmem -#define _GNU_SOURCE - #include #include #include @@ -343,11 +340,11 @@ blaze822(char *file) return 0; } - if ((end = memmem(buf-overlap+used, rd+overlap, "\n\n", 2))) { + if ((end = mymemmem(buf-overlap+used, rd+overlap, "\n\n", 2))) { end++; break; } - if ((end = memmem(buf-overlap+used, rd+overlap, "\r\n\r\n", 4))) { + if ((end = mymemmem(buf-overlap+used, rd+overlap, "\r\n\r\n", 4))) { end++; end++; break; @@ -378,9 +375,9 @@ blaze822_mem(char *src, size_t len) if (!mesg) return 0; - if ((end = memmem(src, len, "\n\n", 2))) { + if ((end = mymemmem(src, len, "\n\n", 2))) { mesg->body = end+2; - } else if ((end = memmem(src, len, "\r\n\r\n", 4))) { + } else if ((end = mymemmem(src, len, "\r\n\r\n", 4))) { mesg->body = end+4; } else { end = src + len; @@ -435,7 +432,7 @@ blaze822_hdr_(struct message *mesg, const char *hdr, size_t hdrlen) if (memcmp(mesg->msg, hdr+1, hdrlen-1) == 0) v = mesg->msg; else - v = memmem(mesg->msg, mesg->end - mesg->msg, hdr, hdrlen); + v = mymemmem(mesg->msg, mesg->end - mesg->msg, hdr, hdrlen); if (!v) return 0; v += hdrlen; @@ -512,9 +509,9 @@ blaze822_mmap(char *file) close(fd); char *end; - if ((end = memmem(buf, len, "\n\n", 2))) { + if ((end = mymemmem(buf, len, "\n\n", 2))) { mesg->body = end+2; - } else if ((end = memmem(buf, len, "\r\n\r\n", 4))) { + } else if ((end = mymemmem(buf, len, "\r\n\r\n", 4))) { mesg->body = end+4; } else { end = buf + len; diff --git a/blaze822_priv.h b/blaze822_priv.h index 1da4d96..bf895d3 100644 --- a/blaze822_priv.h +++ b/blaze822_priv.h @@ -13,3 +13,5 @@ struct message { // ASCII lowercase without alpha check (wrong for "@[\]^_") #define lc(c) ((c) | 0x20) + +void *mymemmem(const void *h0, size_t k, const void *n0, size_t l); diff --git a/mscan.c b/mscan.c index 4cc59b6..7882cb6 100644 --- a/mscan.c +++ b/mscan.c @@ -1,5 +1,3 @@ -#define _GNU_SOURCE - #include #include #include diff --git a/mymemmem.c b/mymemmem.c new file mode 100644 index 0000000..9637c98 --- /dev/null +++ b/mymemmem.c @@ -0,0 +1,173 @@ +// taken straight from musl@c718f9fc + +/* +Copyright © 2005-2014 Rich Felker, et al. + +Permission is hereby granted, free of charge, to any person obtaining +a copy of this software and associated documentation files (the +"Software"), to deal in the Software without restriction, including +without limitation the rights to use, copy, modify, merge, publish, +distribute, sublicense, and/or sell copies of the Software, and to +permit persons to whom the Software is furnished to do so, subject to +the following conditions: + +The above copyright notice and this permission notice shall be +included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ + +#include +#include + +static char *twobyte_memmem(const unsigned char *h, size_t k, const unsigned char *n) +{ + uint16_t nw = n[0]<<8 | n[1], hw = h[0]<<8 | h[1]; + for (h++, k--; k; k--, hw = hw<<8 | *++h) + if (hw == nw) return (char *)h-1; + return 0; +} + +static char *threebyte_memmem(const unsigned char *h, size_t k, const unsigned char *n) +{ + uint32_t nw = n[0]<<24 | n[1]<<16 | n[2]<<8; + uint32_t hw = h[0]<<24 | h[1]<<16 | h[2]<<8; + for (h+=2, k-=2; k; k--, hw = (hw|*++h)<<8) + if (hw == nw) return (char *)h-2; + return 0; +} + +static char *fourbyte_memmem(const unsigned char *h, size_t k, const unsigned char *n) +{ + uint32_t nw = n[0]<<24 | n[1]<<16 | n[2]<<8 | n[3]; + uint32_t hw = h[0]<<24 | h[1]<<16 | h[2]<<8 | h[3]; + for (h+=3, k-=3; k; k--, hw = hw<<8 | *++h) + if (hw == nw) return (char *)h-3; + return 0; +} + +#define MAX(a,b) ((a)>(b)?(a):(b)) +#define MIN(a,b) ((a)<(b)?(a):(b)) + +#define BITOP(a,b,op) \ + ((a)[(size_t)(b)/(8*sizeof *(a))] op (size_t)1<<((size_t)(b)%(8*sizeof *(a)))) + +static char *twoway_memmem(const unsigned char *h, const unsigned char *z, const unsigned char *n, size_t l) +{ + size_t i, ip, jp, k, p, ms, p0, mem, mem0; + size_t byteset[32 / sizeof(size_t)] = { 0 }; + size_t shift[256]; + + /* Computing length of needle and fill shift table */ + for (i=0; i n[jp+k]) { + jp += k; + k = 1; + p = jp - ip; + } else { + ip = jp++; + k = p = 1; + } + } + ms = ip; + p0 = p; + + /* And with the opposite comparison */ + ip = -1; jp = 0; k = p = 1; + while (jp+k ms+1) ms = ip; + else p = p0; + + /* Periodic needle? */ + if (memcmp(n, n+p, ms+1)) { + mem0 = 0; + p = MAX(ms, l-ms-1) + 1; + } else mem0 = l-p; + mem = 0; + + /* Search loop */ + for (;;) { + /* If remainder of haystack is shorter than needle, done */ + if ((size_t)(z-h) < l) return 0; + + /* Check last byte first; advance by shift on mismatch */ + if (BITOP(byteset, h[l-1], &)) { + k = l-shift[h[l-1]]; + if (k) { + if (mem0 && mem && k < p) k = l-p; + h += k; + mem = 0; + continue; + } + } else { + h += l; + mem = 0; + continue; + } + + /* Compare right half */ + for (k=MAX(ms+1,mem); kmem && n[k-1] == h[k-1]; k--); + if (k <= mem) return (char *)h; + h += p; + mem = mem0; + } +} + +void *mymemmem(const void *h0, size_t k, const void *n0, size_t l) +{ + const unsigned char *h = h0, *n = n0; + + /* Return immediately on empty needle */ + if (!l) return (void *)h; + + /* Return immediately when needle is longer than haystack */ + if (k #include @@ -134,7 +132,7 @@ blaze822_multipart(struct message *msg, struct message **imsg) else prevpart = msg->body; - char *part = memmem(prevpart, msg->bodyend - prevpart, mboundary, boundarylen); + char *part = mymemmem(prevpart, msg->bodyend - prevpart, mboundary, boundarylen); if (!part) return 0; /// XXX access to stuff before first boundary? @@ -148,7 +146,7 @@ blaze822_multipart(struct message *msg, struct message **imsg) else return 0; // XXX error condition? - char *nextpart = memmem(part, msg->bodyend - part, mboundary, boundarylen); + char *nextpart = mymemmem(part, msg->bodyend - part, mboundary, boundarylen); if (!nextpart) return 0; // XXX error condition