Fix bug: parse error while buffer realloced

Signed-off-by: zhaojh329 <zhaojh329@gmail.com>
main
zhaojh329 2020-09-07 16:47:45 +08:00
parent 96ef9bcda0
commit 17f7ccf2c9
2 changed files with 50 additions and 25 deletions

View File

@ -173,13 +173,19 @@ static const char *conn_get_method_str(struct uh_connection *conn)
return http_method_str(conn->parser.method); return http_method_str(conn->parser.method);
} }
/* offset of the request field */
#define ROF(c, a) (a - (const char *)c->rb.data)
/* data of the request field */
#define O2D(c, o) ((const char *)c->rb.data + o)
static struct uh_str conn_get_path(struct uh_connection *conn) static struct uh_str conn_get_path(struct uh_connection *conn)
{ {
struct http_parser_url *u = &conn->url_parser; struct http_parser_url *u = &conn->url_parser;
struct uh_request *req = &conn->req; struct uh_request *req = &conn->req;
struct uh_str path; struct uh_str path;
path.p = req->url.p + u->field_data[UF_PATH].off; path.p = O2D(conn, u->field_data[UF_PATH].off) + req->url.offset;
path.len = u->field_data[UF_PATH].len; path.len = u->field_data[UF_PATH].len;
return path; return path;
@ -194,7 +200,7 @@ static struct uh_str conn_get_query(struct uh_connection *conn)
if (!(u->field_set & (1 << UF_QUERY))) if (!(u->field_set & (1 << UF_QUERY)))
return query; return query;
query.p = req->url.p + u->field_data[UF_QUERY].off; query.p = O2D(conn, u->field_data[UF_QUERY].off) + req->url.offset;
query.len = u->field_data[UF_QUERY].len; query.len = u->field_data[UF_QUERY].len;
return query; return query;
@ -204,18 +210,19 @@ static struct uh_str conn_get_header(struct uh_connection *conn, const char *nam
{ {
struct uh_request *req = &conn->req; struct uh_request *req = &conn->req;
int name_len = strlen(name); int name_len = strlen(name);
struct uh_str *field;
struct uh_str value = {}; struct uh_str value = {};
int i; int i;
for (i = 0; i < UHTTPD_MAX_HEADER_NUM; i++) { for (i = 0; i < UHTTPD_MAX_HEADER_NUM; i++) {
field = &req->headers[i].field; if (req->headers[i].field.offset == 0)
if (!field->p)
return value; return value;
if (name_len == field->len && !strncasecmp(field->p, name, name_len)) { if (req->headers[i].field.length != name_len)
value.p = req->headers[i].value.p; continue;
value.len = req->headers[i].value.len;
if (!strncasecmp(O2D(conn, req->headers[i].field.offset), name, name_len)) {
value.p = O2D(conn, req->headers[i].value.offset);
value.len = req->headers[i].value.length;
} }
} }
@ -224,7 +231,13 @@ static struct uh_str conn_get_header(struct uh_connection *conn, const char *nam
static struct uh_str conn_get_body(struct uh_connection *conn) static struct uh_str conn_get_body(struct uh_connection *conn)
{ {
return conn->req.body; struct uh_request *req = &conn->req;
struct uh_str body;
body.p = O2D(conn, req->body.offset);
body.len = req->body.length;
return body;
} }
static int on_message_begin_cb(struct http_parser *parser) static int on_message_begin_cb(struct http_parser *parser)
@ -242,11 +255,11 @@ static int on_message_begin_cb(struct http_parser *parser)
static int on_url_cb(struct http_parser *parser, const char *at, size_t length) static int on_url_cb(struct http_parser *parser, const char *at, size_t length)
{ {
struct uh_connection *conn = (struct uh_connection *)parser->data; struct uh_connection *conn = (struct uh_connection *)parser->data;
struct uh_str *url = &conn->req.url; struct uh_request *req = &conn->req;
if (!url->p) if (req->url.offset == 0)
url->p = at; req->url.offset = ROF(conn, at);
url->len += length; req->url.length += length;
return 0; return 0;
} }
@ -265,10 +278,10 @@ static int on_header_field_cb(struct http_parser *parser, const char *at, size_t
return 1; return 1;
} }
req->headers[req->header_num - 1].field.p = at; req->headers[req->header_num - 1].field.offset = ROF(conn, at);
} }
req->headers[req->header_num - 1].field.len += length; req->headers[req->header_num - 1].field.length += length;
return 0; return 0;
} }
@ -280,10 +293,10 @@ static int on_header_value_cb(struct http_parser *parser, const char *at, size_t
if (!req->last_was_header_value) { if (!req->last_was_header_value) {
req->last_was_header_value = true; req->last_was_header_value = true;
req->headers[req->header_num - 1].value.p = at; req->headers[req->header_num - 1].value.offset = ROF(conn, at);
} }
req->headers[req->header_num - 1].value.len += length; req->headers[req->header_num - 1].value.length += length;
return 0; return 0;
} }
@ -293,9 +306,9 @@ static int on_body_cb(struct http_parser *parser, const char *at, size_t length)
struct uh_connection *conn = (struct uh_connection *)parser->data; struct uh_connection *conn = (struct uh_connection *)parser->data;
struct uh_request *req = &conn->req; struct uh_request *req = &conn->req;
if (!req->body.p) if (req->body.offset == 0)
req->body.p = at; req->body.offset = ROF(conn, at);
req->body.len += length; req->body.length += length;
return 0; return 0;
} }
@ -320,7 +333,7 @@ static int on_message_complete_cb(struct http_parser *parser)
struct uh_connection *conn = (struct uh_connection *)parser->data; struct uh_connection *conn = (struct uh_connection *)parser->data;
struct uh_request *req = &conn->req; struct uh_request *req = &conn->req;
http_parser_parse_url(req->url.p, req->url.len, false, &conn->url_parser); http_parser_parse_url(O2D(conn, req->url.offset), req->url.length, false, &conn->url_parser);
if (!run_plugins(conn)) { if (!run_plugins(conn)) {
if (conn->srv->on_request) if (conn->srv->on_request)

View File

@ -47,16 +47,28 @@ struct uh_str {
}; };
struct uh_request { struct uh_request {
struct uh_str url; struct {
ssize_t offset;
size_t length;
} url;
int header_num; int header_num;
bool last_was_header_value; bool last_was_header_value;
struct { struct {
struct uh_str field; struct {
struct uh_str value; ssize_t offset;
size_t length;
} field;
struct {
ssize_t offset;
size_t length;
} value;
} headers[UHTTPD_MAX_HEADER_NUM]; } headers[UHTTPD_MAX_HEADER_NUM];
struct uh_str body; struct {
ssize_t offset;
size_t length;
} body;
}; };
struct uh_connection { struct uh_connection {