Remove internal ws from multiline http headers correctly

According to RFC2616:

   All linear white space, including folding, has the same semantics
   as SP. A recipient MAY replace any linear white space with a single
   SP before interpreting the field value or forwarding the message
   downstream.
This commit is contained in:
Nick Mathewson 2012-11-16 11:38:53 -05:00
parent ac42519769
commit c6ff381270
2 changed files with 28 additions and 4 deletions

13
http.c
View File

@ -1870,7 +1870,7 @@ evhttp_parse_firstline_(struct evhttp_request *req, struct evbuffer *buffer)
}
static int
evhttp_append_to_last_header(struct evkeyvalq *headers, const char *line)
evhttp_append_to_last_header(struct evkeyvalq *headers, char *line)
{
struct evkeyval *header = TAILQ_LAST(headers, evkeyvalq);
char *newval;
@ -1880,13 +1880,20 @@ evhttp_append_to_last_header(struct evkeyvalq *headers, const char *line)
return (-1);
old_len = strlen(header->value);
/* Strip space from start and end of line. */
while (*line == ' ' || *line == '\t')
++line;
evutil_rtrim_lws_(line);
line_len = strlen(line);
newval = mm_realloc(header->value, old_len + line_len + 1);
newval = mm_realloc(header->value, old_len + line_len + 2);
if (newval == NULL)
return (-1);
memcpy(newval + old_len, line, line_len + 1);
newval[old_len] = ' ';
memcpy(newval + old_len + 1, line, line_len + 1);
header->value = newval;
return (0);

View File

@ -256,6 +256,9 @@ http_errorcb(struct bufferevent *bev, short what, void *arg)
event_base_loopexit(arg, NULL);
}
static int found_multi = 0;
static int found_multi2 = 0;
static void
http_basic_cb(struct evhttp_request *req, void *arg)
{
@ -267,14 +270,23 @@ http_basic_cb(struct evhttp_request *req, void *arg)
/* For multi-line headers test */
{
const char *multi =
evhttp_find_header(evhttp_request_get_input_headers(req),"X-multi");
evhttp_find_header(evhttp_request_get_input_headers(req),"X-Multi");
if (multi) {
found_multi = !strcmp(multi,"aaaaaaaa a END");
if (strcmp("END", multi + strlen(multi) - 3) == 0)
test_ok++;
if (evhttp_find_header(evhttp_request_get_input_headers(req), "X-Last"))
test_ok++;
}
}
{
const char *multi2 =
evhttp_find_header(evhttp_request_get_input_headers(req),"X-Multi-Extra-WS");
if (multi2) {
found_multi2 = !strcmp(multi2,"libevent 2.1");
}
}
/* injecting a bad content-length */
if (evhttp_find_header(evhttp_request_get_input_headers(req), "X-Negative"))
@ -3276,6 +3288,8 @@ http_multi_line_header_test(void *arg)
"GET /test HTTP/1.1\r\n"
"Host: somehost\r\n"
"Connection: close\r\n"
"X-Multi-Extra-WS: libevent \r\n"
"\t\t\t2.1 \r\n"
"X-Multi: aaaaaaaa\r\n"
" a\r\n"
"\tEND\r\n"
@ -3283,9 +3297,12 @@ http_multi_line_header_test(void *arg)
"\r\n";
bufferevent_write(bev, http_start_request, strlen(http_start_request));
found_multi = found_multi2 = 0;
event_base_dispatch(data->base);
tt_int_op(found_multi, ==, 1);
tt_int_op(found_multi2, ==, 1);
tt_int_op(test_ok, ==, 4);
end:
if (bev)