From f16ae76b46b7d98b8a0be2024ed3330505e98054 Mon Sep 17 00:00:00 2001
From: =?utf-8?q?Stefan=20B=C3=BChler?= <stbuehler@web.de>
Date: Fri, 15 Feb 2008 11:53:58 +0100
Subject: [PATCH] Fix #1555: HTTP Request/Response only accept complete headers, i.e. ended with double CRLF.
---
src/http_req.c | 7 +++++++
src/http_resp.c | 34 ++++++++++++++++++++++++----------
src/lempar.c | 2 +-
3 files changed, 32 insertions(+), 11 deletions(-)
diff --git a/src/http_req.c b/src/http_req.c
index ea9447a..42b900b 100644
|
a
|
b
|
|
| 263 | 263 | t.last_token_id = token_id; |
| 264 | 264 | } |
| 265 | 265 | |
| | 266 | // Tokenizer failed |
| | 267 | if (parser_ret == PARSER_ERROR) { |
| | 268 | ret = PARSE_ERROR; |
| | 269 | } |
| | 270 | |
| 266 | 271 | /* oops, the parser failed */ |
| 267 | 272 | if (context.ok == 0) { |
| 268 | 273 | ret = PARSE_ERROR; |
| … |
… |
|
| 300 | 305 | if (ret == PARSE_UNSET) { |
| 301 | 306 | ret = buffer_is_empty(context.errmsg) ? PARSE_NEED_MORE : PARSE_ERROR; |
| 302 | 307 | } |
| | 308 | } else if (parser_ret == PARSER_EOF) { // didn't see CRLF CRLF, no other error till now |
| | 309 | ret = PARSE_NEED_MORE; |
| 303 | 310 | } else { |
| 304 | 311 | chunk *c; |
| 305 | 312 | |
diff --git a/src/http_resp.c b/src/http_resp.c
index e3a4a8b..0a4461e 100644
|
a
|
b
|
|
| 94 | 94 | return 0; |
| 95 | 95 | } |
| 96 | 96 | |
| 97 | | |
| 98 | | static int http_resp_tokenizer( |
| | 97 | typedef enum { |
| | 98 | PARSER_UNSET, |
| | 99 | PARSER_OK, |
| | 100 | PARSER_ERROR, |
| | 101 | PARSER_EOF |
| | 102 | } http_resp_parser_t; |
| | 103 | |
| | 104 | static http_resp_parser_t http_resp_tokenizer( |
| 99 | 105 | http_resp_tokenizer_t *t, |
| 100 | 106 | int *token_id, |
| 101 | 107 | buffer *token |
| … |
… |
|
| 130 | 136 | t->is_statusline = 0; |
| 131 | 137 | t->is_key = 1; |
| 132 | 138 | } else { |
| 133 | | fprintf(stderr, "%s.%d: CR with out LF\r\n", __FILE__, __LINE__); |
| 134 | | return -1; |
| | 139 | ERROR("CR with out LF at pos: %zu", t->offset); |
| | 140 | return PARSER_ERROR; |
| 135 | 141 | } |
| 136 | 142 | break; |
| 137 | 143 | case '\n': |
| … |
… |
|
| 151 | 157 | if (c == ':') break; /* the : is the splitter between key and value */ |
| 152 | 158 | } |
| 153 | 159 | } |
| 154 | | if (0 != http_resp_lookup_next_char(t, &c)) return -1; |
| | 160 | if (0 != http_resp_lookup_next_char(t, &c)) return PARSER_EOF; |
| 155 | 161 | } |
| 156 | 162 | |
| 157 | 163 | if (t->c == t->lookup_c && |
| 158 | 164 | t->offset == t->lookup_offset + 1) { |
| 159 | 165 | |
| 160 | | fprintf(stderr, "%s.%d: invalid char in string\n", __FILE__, __LINE__); |
| 161 | | return -1; |
| | 166 | ERROR("invalid char (%d) at pos: %zu", c, t->offset); |
| | 167 | return PARSER_ERROR; |
| 162 | 168 | } |
| 163 | 169 | |
| 164 | 170 | tid = TK_STRING; |
| … |
… |
|
| 192 | 198 | if (tid) { |
| 193 | 199 | *token_id = tid; |
| 194 | 200 | |
| 195 | | return 1; |
| | 201 | return PARSER_OK; |
| 196 | 202 | } |
| 197 | 203 | |
| 198 | | return -1; |
| | 204 | return PARSER_EOF; |
| 199 | 205 | } |
| 200 | 206 | |
| 201 | 207 | parse_status_t http_response_parse_cq(chunkqueue *cq, http_resp *resp) { |
| … |
… |
|
| 205 | 211 | buffer *token = NULL; |
| 206 | 212 | http_resp_ctx_t context; |
| 207 | 213 | parse_status_t ret = PARSE_UNSET; |
| | 214 | http_resp_parser_t parser_ret; |
| 208 | 215 | int last_token_id = 0; |
| 209 | 216 | |
| 210 | 217 | if(!cq->first) return PARSE_NEED_MORE; |
| … |
… |
|
| 227 | 234 | http_resp_parserTrace(stderr, "http-response: "); |
| 228 | 235 | #endif |
| 229 | 236 | |
| 230 | | while((1 == http_resp_tokenizer(&t, &token_id, token)) && context.ok) { |
| | 237 | while((PARSER_OK == (parser_ret = http_resp_tokenizer(&t, &token_id, token))) && context.ok) { |
| 231 | 238 | http_resp_parser(pParser, token_id, token, &context); |
| 232 | 239 | |
| 233 | 240 | token = buffer_pool_get(context.unused_buffers); |
| … |
… |
|
| 239 | 246 | last_token_id = token_id; |
| 240 | 247 | } |
| 241 | 248 | |
| | 249 | // Tokenizer failed |
| | 250 | if (parser_ret == PARSER_ERROR) { |
| | 251 | ret = PARSE_ERROR; |
| | 252 | } |
| | 253 | |
| 242 | 254 | /* oops, the parser failed */ |
| 243 | 255 | if (context.ok == 0) { |
| 244 | 256 | ret = PARSE_ERROR; |
| … |
… |
|
| 266 | 278 | if (ret == PARSE_UNSET) { |
| 267 | 279 | ret = buffer_is_empty(context.errmsg) ? PARSE_NEED_MORE : PARSE_ERROR; |
| 268 | 280 | } |
| | 281 | } else if (parser_ret == PARSER_EOF) { // didn't see CRLF CRLF, no other error till now |
| | 282 | ret = PARSE_NEED_MORE; |
| 269 | 283 | } else { |
| 270 | 284 | chunk *c; |
| 271 | 285 | |
diff --git a/src/lempar.c b/src/lempar.c
index 0af8e8c..cebc849 100644
|
a
|
b
|
|
| 572 | 572 | /* (re)initialize the parser, if necessary */ |
| 573 | 573 | yypParser = (yyParser*)yyp; |
| 574 | 574 | if( yypParser->yyidx<0 ){ |
| 575 | | if( yymajor==0 ) return; |
| | 575 | if( yymajor==0 ) return; /* Accept empty input */ |
| 576 | 576 | yypParser->yyidx = 0; |
| 577 | 577 | yypParser->yyerrcnt = -1; |
| 578 | 578 | yypParser->yystack[0].stateno = 0; |