dovecot-2.2: http: Improved HTTP header parser state machine and...
dovecot at dovecot.org
dovecot at dovecot.org
Fri Jan 10 22:00:54 EET 2014
details: http://hg.dovecot.org/dovecot-2.2/rev/012d6d22aa67
changeset: 17095:012d6d22aa67
user: Stephan Bosch <stephan at rename-it.nl>
date: Fri Jan 10 15:00:39 2014 -0500
description:
http: Improved HTTP header parser state machine and error messages.
diffstat:
src/lib-http/http-header-parser.c | 62 +++++++++++++++++++-------------------
1 files changed, 31 insertions(+), 31 deletions(-)
diffs (114 lines):
diff -r 4650bfc057fb -r 012d6d22aa67 src/lib-http/http-header-parser.c
--- a/src/lib-http/http-header-parser.c Fri Jan 10 15:00:28 2014 -0500
+++ b/src/lib-http/http-header-parser.c Fri Jan 10 15:00:39 2014 -0500
@@ -19,7 +19,6 @@
HTTP_HEADER_PARSE_STATE_CR,
HTTP_HEADER_PARSE_STATE_LF,
HTTP_HEADER_PARSE_STATE_NEW_LINE,
- HTTP_HEADER_PARSE_STATE_LAST_LINE,
HTTP_HEADER_PARSE_STATE_EOH
};
@@ -172,16 +171,24 @@
case HTTP_HEADER_PARSE_STATE_INIT:
buffer_set_used_size(parser->value_buf, 0);
str_truncate(parser->name, 0);
+ if (*parser->cur == '\r') {
+ /* last CRLF */
+ parser->cur++;
+ parser->state = HTTP_HEADER_PARSE_STATE_EOH;
+ if (parser->cur == parser->end)
+ return 0;
+ break;
+ } else if (*parser->cur == '\n') {
+ /* last LF */
+ parser->state = HTTP_HEADER_PARSE_STATE_EOH;
+ break;
+ }
+ /* next line */
parser->state = HTTP_HEADER_PARSE_STATE_NAME;
/* fall through */
case HTTP_HEADER_PARSE_STATE_NAME:
- if (http_char_is_token(*parser->cur)) {
- if ((ret=http_header_parse_name(parser)) <= 0)
- return ret;
- } else if (*parser->cur != ':' && str_len(parser->name) == 0) {
- parser->state = HTTP_HEADER_PARSE_STATE_LAST_LINE;
- break;
- }
+ if ((ret=http_header_parse_name(parser)) <= 0)
+ return ret;
parser->state = HTTP_HEADER_PARSE_STATE_COLON;
/* fall through */
case HTTP_HEADER_PARSE_STATE_COLON:
@@ -216,6 +223,12 @@
case HTTP_HEADER_PARSE_STATE_CR:
if (*parser->cur == '\r') {
parser->cur++;
+ } else if (*parser->cur != '\n') {
+ parser->error = t_strdup_printf
+ ("Invalid character %s in content of header field '%s'",
+ _chr_sanitize(*parser->cur),
+ str_sanitize(str_c(parser->name),64));
+ return -1;
}
parser->state = HTTP_HEADER_PARSE_STATE_LF;
if (parser->cur == parser->end)
@@ -224,7 +237,7 @@
case HTTP_HEADER_PARSE_STATE_LF:
if (*parser->cur != '\n') {
parser->error = t_strdup_printf
- ("Expected line end after header field '%s', but found %s",
+ ("Expected LF after CR at end of header field '%s', but found %s",
str_sanitize(str_c(parser->name),64),
_chr_sanitize(*parser->cur));
return -1;
@@ -240,31 +253,14 @@
buffer_append_c(parser->value_buf, ' ');
parser->state = HTTP_HEADER_PARSE_STATE_OWS;
break;
- }
+ }
+ /* next header line */
parser->state = HTTP_HEADER_PARSE_STATE_INIT;
return 1;
- case HTTP_HEADER_PARSE_STATE_LAST_LINE:
- if (*parser->cur == '\r') {
- /* last CRLF */
- parser->cur++;
- parser->state = HTTP_HEADER_PARSE_STATE_EOH;
- if (parser->cur == parser->end)
- return 0;
- break;
- } else if (*parser->cur == '\n') {
- /* header fully parsed */
- parser->cur++;
- parser->state = HTTP_HEADER_PARSE_STATE_EOH;
- return 1;
- }
- parser->error = t_strdup_printf
- ("Expected CRLF or header field name, but found %s",
- _chr_sanitize(*parser->cur));
- return -1;
case HTTP_HEADER_PARSE_STATE_EOH:
if (*parser->cur != '\n') {
parser->error = t_strdup_printf
- ("Expected LF after CR at end of header, but found %s",
+ ("Encountered stray CR at beginning of header line, followed by %s",
_chr_sanitize(*parser->cur));
return -1;
}
@@ -350,7 +346,11 @@
}
i_assert(ret != -2);
- if (ret < 0)
- *error_r = "Stream error";
+ if (ret < 0) {
+ if (i_stream_is_eof(parser->input))
+ *error_r = "Premature end of input";
+ else
+ *error_r = "Stream error";
+ }
return ret;
}
More information about the dovecot-cvs
mailing list