]> granicus.if.org Git - libevent/commitdiff
Remove internal ws from multiline http headers correctly
authorNick Mathewson <nickm@torproject.org>
Fri, 16 Nov 2012 16:38:53 +0000 (11:38 -0500)
committerNick Mathewson <nickm@torproject.org>
Fri, 16 Nov 2012 16:38:53 +0000 (11:38 -0500)
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.

http.c
test/regress_http.c

diff --git a/http.c b/http.c
index 42a44f71f37b040a899721fdca46829be56668f4..c4c72f6e8b099cc038918ceb749f19ef6fe63e6f 100644 (file)
--- a/http.c
+++ b/http.c
@@ -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);
index cc755de2afce472d343e263cdbd3058998017481..adc78ab5cbcaec8ac8c549c4e74ba96b97ec3642 100644 (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)