From 48a4364fdd940f2173084e6be3d46e213d836646 Mon Sep 17 00:00:00 2001 From: Peter Griess Date: Thu, 8 Sep 2011 08:13:31 -0500 Subject: [PATCH] Remove some chars from tokens[] per RFC. - Treat ' ' specially, as apparently IIS6.0 can send this in headers. Allow this character through if we're not in strict mode. - Move some test code around so that test indices don't break when HTTP_PARSER_STRICT changes. Fixes #13. --- http_parser.c | 9 ++-- test.c | 147 +++++++++++++++++++++++++------------------------- 2 files changed, 79 insertions(+), 77 deletions(-) diff --git a/http_parser.c b/http_parser.c index 5e135f7..f87dd17 100644 --- a/http_parser.c +++ b/http_parser.c @@ -133,9 +133,9 @@ static const char tokens[256] = { /* 24 can 25 em 26 sub 27 esc 28 fs 29 gs 30 rs 31 us */ 0, 0, 0, 0, 0, 0, 0, 0, /* 32 sp 33 ! 34 " 35 # 36 $ 37 % 38 & 39 ' */ - ' ', '!', '"', '#', '$', '%', '&', '\'', + 0, '!', 0, '#', '$', '%', '&', '\'', /* 40 ( 41 ) 42 * 43 + 44 , 45 - 46 . 47 / */ - 0, 0, '*', '+', 0, '-', '.', '/', + 0, 0, '*', '+', 0, '-', '.', 0, /* 48 0 49 1 50 2 51 3 52 4 53 5 54 6 55 7 */ '0', '1', '2', '3', '4', '5', '6', '7', /* 56 8 57 9 58 : 59 ; 60 < 61 = 62 > 63 ? */ @@ -155,7 +155,7 @@ static const char tokens[256] = { /* 112 p 113 q 114 r 115 s 116 t 117 u 118 v 119 w */ 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', /* 120 x 121 y 122 z 123 { 124 | 125 } 126 ~ 127 del */ - 'x', 'y', 'z', 0, '|', '}', '~', 0 }; + 'x', 'y', 'z', 0, '|', 0, '~', 0 }; static const int8_t unhex[256] = @@ -311,15 +311,16 @@ enum header_states #define CR '\r' #define LF '\n' #define LOWER(c) (unsigned char)(c | 0x20) -#define TOKEN(c) (tokens[(unsigned char)c]) #define IS_ALPHA(c) (LOWER(c) >= 'a' && LOWER(c) <= 'z') #define IS_NUM(c) ((c) >= '0' && (c) <= '9') #define IS_ALPHANUM(c) (IS_ALPHA(c) || IS_NUM(c)) #if HTTP_PARSER_STRICT +#define TOKEN(c) (tokens[(unsigned char)c]) #define IS_URL_CHAR(c) (normal_url_char[(unsigned char) (c)]) #define IS_HOST_CHAR(c) (IS_ALPHANUM(c) || (c) == '.' || (c) == '-') #else +#define TOKEN(c) ((c == ' ') ? ' ' : tokens[(unsigned char)c]) #define IS_URL_CHAR(c) \ (normal_url_char[(unsigned char) (c)] || ((c) & 0x80)) #define IS_HOST_CHAR(c) \ diff --git a/test.c b/test.c index be633eb..3810283 100644 --- a/test.c +++ b/test.c @@ -593,29 +593,35 @@ const struct message requests[] = ,.body= "" } -#if !HTTP_PARSER_STRICT -#define UTF8_PATH_REQ 24 -, {.name= "utf-8 path request" +#define PATCH_REQ 24 +, {.name = "PATCH request" ,.type= HTTP_REQUEST - ,.raw= "GET /δ¶/δt/pope?q=1#narf HTTP/1.1\r\n" - "Host: github.com\r\n" + ,.raw= "PATCH /file.txt HTTP/1.1\r\n" + "Host: www.example.com\r\n" + "Content-Type: application/example\r\n" + "If-Match: \"e0023aa4e\"\r\n" + "Content-Length: 10\r\n" "\r\n" + "cccccccccc" ,.should_keep_alive= TRUE ,.message_complete_on_eof= FALSE ,.http_major= 1 ,.http_minor= 1 - ,.method= HTTP_GET - ,.request_url= "/δ¶/δt/pope?q=1#narf" - ,.num_headers= 1 - ,.headers= { {"Host", "github.com" } + ,.method= HTTP_PATCH + ,.request_url= "/file.txt" + ,.num_headers= 4 + ,.headers= { { "Host", "www.example.com" } + , { "Content-Type", "application/example" } + , { "If-Match", "\"e0023aa4e\"" } + , { "Content-Length", "10" } } - ,.body= "" + ,.body= "cccccccccc" } -#define HOSTNAME_UNDERSCORE 25 -, {.name = "hostname underscore" +#define CONNECT_CAPS_REQUEST 25 +, {.name = "connect caps request" ,.type= HTTP_REQUEST - ,.raw= "CONNECT home_0.netscape.com:443 HTTP/1.0\r\n" + ,.raw= "CONNECT HOME0.NETSCAPE.COM:443 HTTP/1.0\r\n" "User-agent: Mozilla/1.1N\r\n" "Proxy-authorization: basic aGVsbG86d29ybGQ=\r\n" "\r\n" @@ -624,7 +630,7 @@ const struct message requests[] = ,.http_major= 1 ,.http_minor= 0 ,.method= HTTP_CONNECT - ,.request_url= "home_0.netscape.com:443" + ,.request_url= "HOME0.NETSCAPE.COM:443" ,.num_headers= 2 ,.upgrade="" ,.headers= { { "User-agent", "Mozilla/1.1N" } @@ -632,37 +638,30 @@ const struct message requests[] = } ,.body= "" } -#endif /* !HTTP_PARSER_STRICT */ -#define PATCH_REQ 26 -, {.name = "PATCH request" +#if !HTTP_PARSER_STRICT +#define UTF8_PATH_REQ 26 +, {.name= "utf-8 path request" ,.type= HTTP_REQUEST - ,.raw= "PATCH /file.txt HTTP/1.1\r\n" - "Host: www.example.com\r\n" - "Content-Type: application/example\r\n" - "If-Match: \"e0023aa4e\"\r\n" - "Content-Length: 10\r\n" + ,.raw= "GET /δ¶/δt/pope?q=1#narf HTTP/1.1\r\n" + "Host: github.com\r\n" "\r\n" - "cccccccccc" ,.should_keep_alive= TRUE ,.message_complete_on_eof= FALSE ,.http_major= 1 ,.http_minor= 1 - ,.method= HTTP_PATCH - ,.request_url= "/file.txt" - ,.num_headers= 4 - ,.headers= { { "Host", "www.example.com" } - , { "Content-Type", "application/example" } - , { "If-Match", "\"e0023aa4e\"" } - , { "Content-Length", "10" } + ,.method= HTTP_GET + ,.request_url= "/δ¶/δt/pope?q=1#narf" + ,.num_headers= 1 + ,.headers= { {"Host", "github.com" } } - ,.body= "cccccccccc" + ,.body= "" } -#define CONNECT_CAPS_REQUEST 27 -, {.name = "connect caps request" +#define HOSTNAME_UNDERSCORE 27 +, {.name = "hostname underscore" ,.type= HTTP_REQUEST - ,.raw= "CONNECT HOME0.NETSCAPE.COM:443 HTTP/1.0\r\n" + ,.raw= "CONNECT home_0.netscape.com:443 HTTP/1.0\r\n" "User-agent: Mozilla/1.1N\r\n" "Proxy-authorization: basic aGVsbG86d29ybGQ=\r\n" "\r\n" @@ -671,7 +670,7 @@ const struct message requests[] = ,.http_major= 1 ,.http_minor= 0 ,.method= HTTP_CONNECT - ,.request_url= "HOME0.NETSCAPE.COM:443" + ,.request_url= "home_0.netscape.com:443" ,.num_headers= 2 ,.upgrade="" ,.headers= { { "User-agent", "Mozilla/1.1N" } @@ -679,6 +678,7 @@ const struct message requests[] = } ,.body= "" } +#endif /* !HTTP_PARSER_STRICT */ , {.name= NULL } /* sentinel */ }; @@ -945,40 +945,7 @@ const struct message responses[] = ,.body= "" } -#define SPACE_IN_FIELD_RES 9 -/* Should handle spaces in header fields */ -, {.name= "field space" - ,.type= HTTP_RESPONSE - ,.raw= "HTTP/1.1 200 OK\r\n" - "Server: Microsoft-IIS/6.0\r\n" - "X-Powered-By: ASP.NET\r\n" - "en-US Content-Type: text/xml\r\n" /* this is the problem */ - "Content-Type: text/xml\r\n" - "Content-Length: 16\r\n" - "Date: Fri, 23 Jul 2010 18:45:38 GMT\r\n" - "Connection: keep-alive\r\n" - "\r\n" - "hello" /* fake body */ - ,.should_keep_alive= TRUE - ,.message_complete_on_eof= FALSE - ,.http_major= 1 - ,.http_minor= 1 - ,.status_code= 200 - ,.num_headers= 7 - ,.headers= - { { "Server", "Microsoft-IIS/6.0" } - , { "X-Powered-By", "ASP.NET" } - , { "en-US Content-Type", "text/xml" } - , { "Content-Type", "text/xml" } - , { "Content-Length", "16" } - , { "Date", "Fri, 23 Jul 2010 18:45:38 GMT" } - , { "Connection", "keep-alive" } - } - ,.body= "hello" - } - - -#define RES_FIELD_UNDERSCORE 10 +#define RES_FIELD_UNDERSCORE 9 /* Should handle spaces in header fields */ , {.name= "field underscore" ,.type= HTTP_RESPONSE @@ -1018,7 +985,7 @@ const struct message responses[] = ,.body= "" } -#define NON_ASCII_IN_STATUS_LINE 11 +#define NON_ASCII_IN_STATUS_LINE 10 /* Should handle non-ASCII in status line */ , {.name= "non-ASCII in status line" ,.type= HTTP_RESPONSE @@ -1041,7 +1008,7 @@ const struct message responses[] = ,.body= "" } -#define HTTP_VERSION_0_9 12 +#define HTTP_VERSION_0_9 11 /* Should handle HTTP/0.9 */ , {.name= "http version 0.9" ,.type= HTTP_RESPONSE @@ -1058,7 +1025,7 @@ const struct message responses[] = ,.body= "" } -#define NO_CONTENT_LENGTH_NO_TRANSFER_ENCODING_RESPONSE 13 +#define NO_CONTENT_LENGTH_NO_TRANSFER_ENCODING_RESPONSE 12 /* The client should wait for the server's EOF. That is, when neither * content-length nor transfer-encoding is specified, the end of body * is specified by the EOF. @@ -1081,7 +1048,7 @@ const struct message responses[] = ,.body= "hello world" } -#define NO_HEADERS_NO_BODY_204 14 +#define NO_HEADERS_NO_BODY_204 13 , {.name= "204 no headers no body" ,.type= HTTP_RESPONSE ,.raw= "HTTP/1.1 204 No Content\r\n\r\n" @@ -1096,6 +1063,40 @@ const struct message responses[] = ,.body= "" } +#if !HTTP_PARSER_STRICT +#define SPACE_IN_FIELD_RES 14 +/* Should handle spaces in header fields */ +, {.name= "field space" + ,.type= HTTP_RESPONSE + ,.raw= "HTTP/1.1 200 OK\r\n" + "Server: Microsoft-IIS/6.0\r\n" + "X-Powered-By: ASP.NET\r\n" + "en-US Content-Type: text/xml\r\n" /* this is the problem */ + "Content-Type: text/xml\r\n" + "Content-Length: 16\r\n" + "Date: Fri, 23 Jul 2010 18:45:38 GMT\r\n" + "Connection: keep-alive\r\n" + "\r\n" + "hello" /* fake body */ + ,.should_keep_alive= TRUE + ,.message_complete_on_eof= FALSE + ,.http_major= 1 + ,.http_minor= 1 + ,.status_code= 200 + ,.num_headers= 7 + ,.headers= + { { "Server", "Microsoft-IIS/6.0" } + , { "X-Powered-By", "ASP.NET" } + , { "en-US Content-Type", "text/xml" } + , { "Content-Type", "text/xml" } + , { "Content-Length", "16" } + , { "Date", "Fri, 23 Jul 2010 18:45:38 GMT" } + , { "Connection", "keep-alive" } + } + ,.body= "hello" + } +#endif /* !HTTP_PARSER_STRICT */ + , {.name= NULL } /* sentinel */ };