Browse Source

fix rather nasty reentrance bug

as i first wrote the parser i used static valiables to hold the
state of the currently parsed request.
If a request would spread of multiple reads this would lead
to one reqeust messing up the state of another.
not those states are part of the parser object itself where
they belong.
master
Georg Hopp 14 years ago
parent
commit
6aef05cf7f
  1. 6
      ChangeLog
  2. 4
      include/http/request_parser.h
  3. 46
      src/http/request/parser/parse.c

6
ChangeLog

@ -1,6 +1,10 @@
2012-02-10 06:22:39 +0100 Georg Hopp
* fix rather nasty reentrance bug (HEAD, master)
2012-02-10 05:52:50 +0100 Georg Hopp 2012-02-10 05:52:50 +0100 Georg Hopp
* fix bug that arose in rewrite of header get and results in an ugly memory leak, as well as no headers would be found any more (HEAD, master)
* fix bug that arose in rewrite of header get and results in an ugly memory leak, as well as no headers would be found any more
2012-02-10 00:27:51 +0100 Georg Hopp 2012-02-10 00:27:51 +0100 Georg Hopp

4
include/http/request_parser.h

@ -17,10 +17,14 @@ typedef enum e_HttpRequestState {
CLASS(HttpRequestParser) { CLASS(HttpRequestParser) {
char * buffer; char * buffer;
char * cur_data;
size_t buffer_used; size_t buffer_used;
size_t buffer_size; size_t buffer_size;
HttpRequestQueue request_queue; HttpRequestQueue request_queue;
HttpRequest cur_request;
HttpRequestState state; HttpRequestState state;
}; };

46
src/http/request/parser/parse.c

@ -7,8 +7,8 @@
#include "interface/class.h" #include "interface/class.h"
#define REMAINS(pars,done) \
((pars)->buffer_used - ((done) - (pars)->buffer))
#define REMAINS(pars) \
((pars)->buffer_used - ((pars)->cur_data - (pars)->buffer))
static static
@ -43,34 +43,32 @@ void httpRequestParserGetHeader(HttpRequest, char *);
void void
httpRequestParserParse(HttpRequestParser this) httpRequestParserParse(HttpRequestParser this)
{ {
static HttpRequest request = NULL;
static char * data; // static pointer to unprocessed data
char * line; char * line;
int cont = 1; int cont = 1;
while(cont) { while(cont) {
switch(this->state) { switch(this->state) {
case HTTP_REQUEST_GARBAGE: case HTTP_REQUEST_GARBAGE:
data = this->buffer; // initialize static pointer
httpRequestSkip(&data);
request = new(HttpRequest);
this->cur_data = this->buffer; // initialize static pointer
httpRequestSkip(&(this->cur_data));
this->cur_request = new(HttpRequest);
this->state = HTTP_REQUEST_START; this->state = HTTP_REQUEST_START;
break; break;
case HTTP_REQUEST_START: case HTTP_REQUEST_START:
if (NULL == (line = httpRequestParserGetLine(&data))) {
if (NULL == (line = httpRequestParserGetLine(&(this->cur_data)))) {
cont = 0; cont = 0;
break; break;
} }
httpRequestParserGetRequestLine(request, line);
httpRequestParserGetRequestLine(this->cur_request, line);
this->state = HTTP_REQUEST_REQUEST_LINE_DONE; this->state = HTTP_REQUEST_REQUEST_LINE_DONE;
break; break;
case HTTP_REQUEST_REQUEST_LINE_DONE: case HTTP_REQUEST_REQUEST_LINE_DONE:
if (NULL == (line = httpRequestParserGetLine(&data))) {
if (NULL == (line = httpRequestParserGetLine(&(this->cur_data)))) {
cont = 0; cont = 0;
break; break;
} }
@ -80,19 +78,19 @@ httpRequestParserParse(HttpRequestParser this)
break; break;
} }
httpRequestParserGetHeader(request, line);
httpRequestParserGetHeader(this->cur_request, line);
break; break;
case HTTP_REQUEST_HEADERS_DONE: case HTTP_REQUEST_HEADERS_DONE:
httpHeaderSort(request->header, request->nheader);
httpHeaderSort(this->cur_request->header, this->cur_request->nheader);
{ {
char * nbody; char * nbody;
if (0 == request->nbody) {
if (0 == this->cur_request->nbody) {
nbody = httpHeaderGet( nbody = httpHeaderGet(
request->header,
request->nheader,
this->cur_request->header,
this->cur_request->nheader,
"Content-Length"); "Content-Length");
if (NULL == nbody) { if (NULL == nbody) {
@ -100,14 +98,16 @@ httpRequestParserParse(HttpRequestParser this)
break; break;
} }
else { else {
request->nbody = atoi(nbody);
this->cur_request->nbody = atoi(nbody);
} }
} }
if (REMAINS(this, data) >= request->nbody) {
request->body = calloc(1, request->nbody + 1);
memcpy(request->body, data, request->nbody);
data += request->nbody;
if (REMAINS(this) >= this->cur_request->nbody) {
this->cur_request->body = calloc(1, this->cur_request->nbody + 1);
memcpy(this->cur_request->body,
this->cur_data,
this->cur_request->nbody);
this->cur_data += this->cur_request->nbody;
this->state = HTTP_REQUEST_DONE; this->state = HTTP_REQUEST_DONE;
} }
} }
@ -119,14 +119,14 @@ httpRequestParserParse(HttpRequestParser this)
* enqueue current request * enqueue current request
*/ */
this->request_queue->requests[(this->request_queue->nrequests)++] = this->request_queue->requests[(this->request_queue->nrequests)++] =
request;
this->cur_request;
/** /**
* remove processed stuff from input buffer. * remove processed stuff from input buffer.
*/ */
memmove(this->buffer, data, REMAINS(this, data));
memmove(this->buffer, this->cur_data, REMAINS(this));
this->buffer_used -= data - this->buffer;
this->buffer_used -= this->cur_data - this->buffer;
/** /**
* dont continue loop if input buffer is empty * dont continue loop if input buffer is empty

Loading…
Cancel
Save