Skip to content
This repository was archived by the owner on Dec 9, 2020. It is now read-only.

Commit 714cbb2

Browse files
committed
Fix ABI breakage
Fix ABI breakage introduced in commit 7d5c99d ("Support multi-coding Transfer-Encoding") by undoing the change in `sizeof(http_parser)`. Restore the size of the `flags` field and shrink the `index` field from 7 to 5 bits. It track strings up to `strlen("Transfer-Encoding")` bytes so 2^5 == 32 is wide enough. Fixes: nodejs/http-parser#502 PR-URL: nodejs/http-parser#503 Reviewed-By: Fedor Indutny <fedor.indutny@gmail.com> Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Sam Roberts <vieuxtech@gmail.com>
1 parent 1c02cb9 commit 714cbb2

File tree

3 files changed

+15
-10
lines changed

3 files changed

+15
-10
lines changed

http_parser.c

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -731,6 +731,7 @@ size_t http_parser_execute (http_parser *parser,
731731
if (ch == CR || ch == LF)
732732
break;
733733
parser->flags = 0;
734+
parser->extra_flags = 0;
734735
parser->content_length = ULLONG_MAX;
735736

736737
if (ch == 'H') {
@@ -768,6 +769,7 @@ size_t http_parser_execute (http_parser *parser,
768769
if (ch == CR || ch == LF)
769770
break;
770771
parser->flags = 0;
772+
parser->extra_flags = 0;
771773
parser->content_length = ULLONG_MAX;
772774

773775
if (ch == 'H') {
@@ -925,6 +927,7 @@ size_t http_parser_execute (http_parser *parser,
925927
if (ch == CR || ch == LF)
926928
break;
927929
parser->flags = 0;
930+
parser->extra_flags = 0;
928931
parser->content_length = ULLONG_MAX;
929932

930933
if (UNLIKELY(!IS_ALPHA(ch))) {
@@ -1338,7 +1341,7 @@ size_t http_parser_execute (http_parser *parser,
13381341
parser->header_state = h_general;
13391342
} else if (parser->index == sizeof(TRANSFER_ENCODING)-2) {
13401343
parser->header_state = h_transfer_encoding;
1341-
parser->flags |= F_TRANSFER_ENCODING;
1344+
parser->extra_flags |= F_TRANSFER_ENCODING >> 8;
13421345
}
13431346
break;
13441347

@@ -1800,7 +1803,7 @@ size_t http_parser_execute (http_parser *parser,
18001803

18011804
/* Cannot us transfer-encoding and a content-length header together
18021805
per the HTTP specification. (RFC 7230 Section 3.3.3) */
1803-
if ((parser->flags & F_TRANSFER_ENCODING) &&
1806+
if ((parser->extra_flags & (F_TRANSFER_ENCODING >> 8)) &&
18041807
(parser->flags & F_CONTENTLENGTH)) {
18051808
/* Allow it for lenient parsing as long as `Transfer-Encoding` is
18061809
* not `chunked`
@@ -1886,7 +1889,7 @@ size_t http_parser_execute (http_parser *parser,
18861889
/* chunked encoding - ignore Content-Length header,
18871890
* prepare for a chunk */
18881891
UPDATE_STATE(s_chunk_size_start);
1889-
} else if (parser->flags & F_TRANSFER_ENCODING) {
1892+
} else if (parser->extra_flags & (F_TRANSFER_ENCODING >> 8)) {
18901893
if (parser->type == HTTP_REQUEST && !lenient) {
18911894
/* RFC 7230 3.3.3 */
18921895

@@ -2162,7 +2165,7 @@ http_message_needs_eof (const http_parser *parser)
21622165
}
21632166

21642167
/* RFC 7230 3.3.3, see `s_headers_almost_done` */
2165-
if ((parser->flags & F_TRANSFER_ENCODING) &&
2168+
if ((parser->extra_flags & (F_TRANSFER_ENCODING >> 8)) &&
21662169
(parser->flags & F_CHUNKED) == 0) {
21672170
return 1;
21682171
}

http_parser.h

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,7 @@ enum flags
225225
, F_UPGRADE = 1 << 5
226226
, F_SKIPBODY = 1 << 6
227227
, F_CONTENTLENGTH = 1 << 7
228-
, F_TRANSFER_ENCODING = 1 << 8
228+
, F_TRANSFER_ENCODING = 1 << 8 /* Never set in http_parser.flags */
229229
};
230230

231231

@@ -272,13 +272,13 @@ enum flags
272272
"unexpected content-length header") \
273273
XX(INVALID_CHUNK_SIZE, \
274274
"invalid character in chunk size header") \
275-
XX(INVALID_TRANSFER_ENCODING, \
276-
"request has invalid transfer-encoding") \
277275
XX(INVALID_CONSTANT, "invalid constant string") \
278276
XX(INVALID_INTERNAL_STATE, "encountered unexpected internal state")\
279277
XX(STRICT, "strict mode assertion failed") \
280278
XX(PAUSED, "parser is paused") \
281-
XX(UNKNOWN, "an unknown error occurred")
279+
XX(UNKNOWN, "an unknown error occurred") \
280+
XX(INVALID_TRANSFER_ENCODING, \
281+
"request has invalid transfer-encoding") \
282282

283283

284284
/* Define HPE_* values for each errno value above */
@@ -296,11 +296,12 @@ enum http_errno {
296296
struct http_parser {
297297
/** PRIVATE **/
298298
unsigned int type : 2; /* enum http_parser_type */
299+
unsigned int flags : 8; /* F_* values from 'flags' enum; semi-public */
299300
unsigned int state : 7; /* enum state from http_parser.c */
300301
unsigned int header_state : 7; /* enum header_state from http_parser.c */
301-
unsigned int index : 7; /* index into current matcher */
302+
unsigned int index : 5; /* index into current matcher */
303+
unsigned int extra_flags : 2;
302304
unsigned int lenient_http_headers : 1;
303-
unsigned int flags : 16; /* F_* values from 'flags' enum; semi-public */
304305

305306
uint32_t nread; /* # bytes read in various scenarios */
306307
uint64_t content_length; /* # bytes in body (0 if no Content-Length header) */

test.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4221,6 +4221,7 @@ main (void)
42214221
printf("http_parser v%u.%u.%u (0x%06lx)\n", major, minor, patch, version);
42224222

42234223
printf("sizeof(http_parser) = %u\n", (unsigned int)sizeof(http_parser));
4224+
assert(sizeof(http_parser) == 4 + 4 + 8 + 2 + 2 + 4 + sizeof(void *));
42244225

42254226
//// API
42264227
test_preserve_data();

0 commit comments

Comments
 (0)