diff --git a/http_parser.c b/http_parser.c index ba1374e9..0b9c83e0 100644 --- a/http_parser.c +++ b/http_parser.c @@ -1424,12 +1424,6 @@ size_t http_parser_execute (http_parser *parser, goto error; } - if (parser->flags & F_CONTENTLENGTH) { - SET_ERRNO(HPE_UNEXPECTED_CONTENT_LENGTH); - goto error; - } - - parser->flags |= F_CONTENTLENGTH; parser->content_length = ch - '0'; parser->header_state = h_content_length_num; break; @@ -1695,6 +1689,21 @@ size_t http_parser_execute (http_parser *parser, case h_connection_upgrade: parser->flags |= F_CONNECTION_UPGRADE; break; + case h_content_length_num: + case h_content_length_ws: + if (parser->flags & F_CONTENTLENGTH) { + /* content length sent multiple times, + * check if value is the same */ + if (parser->initial_content_length != parser->content_length) { + SET_ERRNO(HPE_UNEXPECTED_CONTENT_LENGTH); + goto error; + } + } else { + /* set content length flag */ + parser->flags |= F_CONTENTLENGTH; + parser->initial_content_length = parser->content_length; + } + break; default: break; } diff --git a/http_parser.h b/http_parser.h index e894d7ce..684befad 100644 --- a/http_parser.h +++ b/http_parser.h @@ -301,6 +301,7 @@ struct http_parser { uint32_t nread; /* # bytes read in various scenarios */ uint64_t content_length; /* # bytes in body (0 if no Content-Length header) */ + uint64_t initial_content_length; /* # used to verify same value if Content-Length header occurs multiple times */ /** READ-ONLY **/ unsigned short http_major;