From c9955b14469e6475f545d405edeb5dbe56368c47 Mon Sep 17 00:00:00 2001 From: Fredrik Tolf Date: Tue, 16 Dec 2008 05:45:23 +0100 Subject: [PATCH] Fixed header reading and a request parser memory leak. --- src/htparser.c | 86 ++++++++++++++++++++++++++++++++-------------------------- 1 file changed, 48 insertions(+), 38 deletions(-) diff --git a/src/htparser.c b/src/htparser.c index a8705fe..1a45ea1 100644 --- a/src/htparser.c +++ b/src/htparser.c @@ -116,41 +116,48 @@ static int listensock6(int port) return(fd); } -static char *slowreadhead(int fd) +static size_t readhead(int fd, struct charbuf *buf) { - int ret; - struct charbuf buf; int nl; - char last; + size_t off; - bufinit(buf); - nl = 0; - while(1) { - sizebuf(buf, buf.d + 1); - ret = recv(fd, buf.b + buf.d, 1, MSG_DONTWAIT); - if(ret <= 0) { - if((ret < 0) && (errno == EAGAIN)) { - block(fd, EV_READ); - continue; + int get1(void) + { + int ret; + + while(!(off < buf->d)) { + sizebuf(*buf, buf->d + 1024); + ret = recv(fd, buf->b + buf->d, buf->s - buf->d, MSG_DONTWAIT); + if(ret <= 0) { + if((ret < 0) && (errno == EAGAIN)) { + block(fd, EV_READ); + continue; + } + return(-1); } - goto err; + buf->d += ret; } - last = buf.b[buf.d++]; - if(last == '\n') { + return(buf->b[off++]); + } + + nl = 0; + off = 0; + while(1) { + switch(get1()) { + case '\n': if(nl) - break; + return(off); nl = 1; - } else if(last == '\r') { - } else { + break; + case '\r': + break; + case -1: + return(-1); + default: nl = 0; + break; } } - bufadd(buf, 0); - return(buf.b); - -err: - buffree(buf); - return(NULL); } #define SKIPNL(ptr) ({ \ @@ -192,45 +199,48 @@ static struct htreq *parseraw(char *buf) while(1) { if(SKIPNL(p)) { if(*p) - return(NULL); + goto fail; break; } if((nl = strchr(p, '\n')) == NULL) - return(NULL); + goto fail; if(((p2 = strchr(p, ':')) == NULL) || (p2 > nl)) - return(NULL); + goto fail; *(p2++) = 0; for(; (*p2 == ' ') || (*p2 == '\t'); p2++); for(nl = p2; (*nl != '\r') && (*nl != '\n'); nl++); if(!SKIPNL(nl)) - return(NULL); + goto fail; reqappheader(req, p, p2); p = nl; } return(req); + +fail: + freereq(req); + return(NULL); } static void serve(struct muth *muth, va_list args) { vavar(int, fd); - char *hb; + struct charbuf buf; struct htreq *req; + size_t headoff; - hb = NULL; + bufinit(buf); while(1) { - if((hb = slowreadhead(fd)) == NULL) + buf.d = 0; + if((headoff = readhead(fd, &buf)) < 0) goto out; - if((req = parseraw(hb)) == NULL) + if((req = parseraw(buf.b)) == NULL) goto out; - free(hb); - hb = NULL; - printf("\"%s\", \"%s\", \"%s\"\n", req->method, req->url, req->ver); + printf("\"%s\", \"%s\", \"%s\", \"%s\"\n", req->method, req->url, req->ver, getheader(req, "host")); freereq(req); } out: - if(hb != NULL) - free(hb); + buffree(buf); close(fd); } -- 2.11.0