@@ -653,6 +653,8 @@ size_t http_parser_execute (http_parser *parser,
653
653
const char * status_mark = 0 ;
654
654
enum state p_state = (enum state ) parser -> state ;
655
655
const unsigned int lenient = parser -> lenient_http_headers ;
656
+ const unsigned int allow_chunked_length = parser -> allow_chunked_length ;
657
+
656
658
uint32_t nread = parser -> nread ;
657
659
658
660
/* We're in an error state. Don't bother doing anything. */
@@ -731,6 +733,7 @@ size_t http_parser_execute (http_parser *parser,
731
733
if (ch == CR || ch == LF )
732
734
break ;
733
735
parser -> flags = 0 ;
736
+ parser -> uses_transfer_encoding = 0 ;
734
737
parser -> content_length = ULLONG_MAX ;
735
738
736
739
if (ch == 'H' ) {
@@ -768,6 +771,7 @@ size_t http_parser_execute (http_parser *parser,
768
771
if (ch == CR || ch == LF )
769
772
break ;
770
773
parser -> flags = 0 ;
774
+ parser -> uses_transfer_encoding = 0 ;
771
775
parser -> content_length = ULLONG_MAX ;
772
776
773
777
if (ch == 'H' ) {
@@ -925,6 +929,7 @@ size_t http_parser_execute (http_parser *parser,
925
929
if (ch == CR || ch == LF )
926
930
break ;
927
931
parser -> flags = 0 ;
932
+ parser -> uses_transfer_encoding = 0 ;
928
933
parser -> content_length = ULLONG_MAX ;
929
934
930
935
if (UNLIKELY (!IS_ALPHA (ch ))) {
@@ -1338,7 +1343,7 @@ size_t http_parser_execute (http_parser *parser,
1338
1343
parser -> header_state = h_general ;
1339
1344
} else if (parser -> index == sizeof (TRANSFER_ENCODING )- 2 ) {
1340
1345
parser -> header_state = h_transfer_encoding ;
1341
- parser -> flags |= F_TRANSFER_ENCODING ;
1346
+ parser -> uses_transfer_encoding = 1 ;
1342
1347
}
1343
1348
break ;
1344
1349
@@ -1798,14 +1803,19 @@ size_t http_parser_execute (http_parser *parser,
1798
1803
REEXECUTE ();
1799
1804
}
1800
1805
1801
- /* Cannot us transfer-encoding and a content-length header together
1806
+ /* Cannot use transfer-encoding and a content-length header together
1802
1807
per the HTTP specification. (RFC 7230 Section 3.3.3) */
1803
- if ((parser -> flags & F_TRANSFER_ENCODING ) &&
1808
+ if ((parser -> uses_transfer_encoding == 1 ) &&
1804
1809
(parser -> flags & F_CONTENTLENGTH )) {
1805
1810
/* Allow it for lenient parsing as long as `Transfer-Encoding` is
1806
- * not `chunked`
1811
+ * not `chunked` or allow_length_with_encoding is set
1807
1812
*/
1808
- if (!lenient || (parser -> flags & F_CHUNKED )) {
1813
+ if (parser -> flags & F_CHUNKED ) {
1814
+ if (!allow_chunked_length ) {
1815
+ SET_ERRNO (HPE_UNEXPECTED_CONTENT_LENGTH );
1816
+ goto error ;
1817
+ }
1818
+ } else if (!lenient ) {
1809
1819
SET_ERRNO (HPE_UNEXPECTED_CONTENT_LENGTH );
1810
1820
goto error ;
1811
1821
}
@@ -1886,7 +1896,7 @@ size_t http_parser_execute (http_parser *parser,
1886
1896
/* chunked encoding - ignore Content-Length header,
1887
1897
* prepare for a chunk */
1888
1898
UPDATE_STATE (s_chunk_size_start );
1889
- } else if (parser -> flags & F_TRANSFER_ENCODING ) {
1899
+ } else if (parser -> uses_transfer_encoding == 1 ) {
1890
1900
if (parser -> type == HTTP_REQUEST && !lenient ) {
1891
1901
/* RFC 7230 3.3.3 */
1892
1902
@@ -2162,7 +2172,7 @@ http_message_needs_eof (const http_parser *parser)
2162
2172
}
2163
2173
2164
2174
/* RFC 7230 3.3.3, see `s_headers_almost_done` */
2165
- if ((parser -> flags & F_TRANSFER_ENCODING ) &&
2175
+ if ((parser -> uses_transfer_encoding == 1 ) &&
2166
2176
(parser -> flags & F_CHUNKED ) == 0 ) {
2167
2177
return 1 ;
2168
2178
}
@@ -2514,7 +2524,7 @@ http_parser_parse_url(const char *buf, size_t buflen, int is_connect,
2514
2524
end = buf + off + len ;
2515
2525
2516
2526
/* NOTE: The characters are already validated and are in the [0-9] range */
2517
- assert (off + len <= buflen && "Port number overflow" );
2527
+ assert (( size_t ) ( off + len ) <= buflen && "Port number overflow" );
2518
2528
v = 0 ;
2519
2529
for (p = buf + off ; p < end ; p ++ ) {
2520
2530
v *= 10 ;
0 commit comments