diff options
author | Eric Wong <normalperson@yhbt.net> | 2010-04-26 19:18:10 -0700 |
---|---|---|
committer | Eric Wong <normalperson@yhbt.net> | 2010-04-26 19:18:10 -0700 |
commit | 356435e60da0ffc92b4c7a9eb801255f094b4610 (patch) | |
tree | 43f40fca2d768c4ad3f3e6a2b6548143eb300c9b | |
parent | 31bd370baef622aaa5dd14084f27baf2fabf506c (diff) | |
download | kcar-356435e60da0ffc92b4c7a9eb801255f094b4610.tar.gz |
-rw-r--r-- | ext/kcar/kcar.rl | 24 |
1 files changed, 20 insertions, 4 deletions
diff --git a/ext/kcar/kcar.rl b/ext/kcar/kcar.rl index d2c8f6c..5acaa49 100644 --- a/ext/kcar/kcar.rl +++ b/ext/kcar/kcar.rl @@ -38,6 +38,7 @@ DEF_MAX_LENGTH(REASON, 256); #define UH_FL_CHUNKED 0x1 #define UH_FL_HASBODY 0x2 #define UH_FL_INBODY 0x4 +#define UH_FL_HASTRAILER 0x8 #define UH_FL_INTRAILER 0x10 #define UH_FL_INCHUNK 0x20 #define UH_FL_KEEPALIVE 0x40 @@ -74,6 +75,12 @@ struct http_parser { #define HP_FL_UNSET(hp,fl) ((hp)->flags &= ~(UH_FL_##fl)) #define HP_FL_ALL(hp,fl) (HP_FL_TEST(hp, fl) == (UH_FL_##fl)) +static void finalize_header(struct http_parser *hp) +{ + if ((HP_FL_TEST(hp, HASTRAILER) && ! HP_FL_TEST(hp, CHUNKED))) + rb_raise(eParserError, "trailer but not chunked"); +} + /* * handles values of the "Connection:" header, keepalive is implied * for HTTP/1.1 but needs to be explicitly enabled with HTTP/1.0 @@ -188,7 +195,10 @@ static void write_value(VALUE hdr, struct http_parser *hp, hp_keepalive_connection(hp, v); } else if (STR_CSTR_CASE_EQ(f, "content-length")) { if (! HP_FL_TEST(hp, HASBODY)) - rb_raise(eParserError, "Content-Length with no body"); + rb_raise(eParserError, "Content-Length with no body expected"); + if (HP_FL_TEST(hp, CHUNKED)) + rb_raise(eParserError, + "Content-Length when chunked Transfer-Encoding is set"); hp->len.content = parse_length(vptr, vlen); if (hp->len.content < 0) @@ -198,15 +208,20 @@ static void write_value(VALUE hdr, struct http_parser *hp, } else if (STR_CSTR_CASE_EQ(f, "transfer-encoding")) { if (STR_CSTR_CASE_EQ(v, "chunked")) { if (! HP_FL_TEST(hp, HASBODY)) - rb_raise(eParserError, "chunked Transfer-Encoding with no body"); + rb_raise(eParserError, + "chunked Transfer-Encoding with no body expected"); + if (hp->len.content >= 0) + rb_raise(eParserError, + "chunked Transfer-Encoding when Content-Length is set"); hp->len.chunk = 0; HP_FL_SET(hp, CHUNKED); } invalid_if_trailer(hp); } else if (STR_CSTR_CASE_EQ(f, "trailer")) { - if (! HP_FL_TEST(hp, HASBODY)) - rb_raise(eParserError, "trailer with no body"); + if (! HP_FL_TEST(hp, HASBODY)) + rb_raise(eParserError, "trailer with no body"); + HP_FL_SET(hp, HASTRAILER); invalid_if_trailer(hp); } @@ -261,6 +276,7 @@ static void write_value(VALUE hdr, struct http_parser *hp, rb_raise(eParserError, "invalid chunk size"); } action header_done { + finalize_header(hp); cs = http_parser_first_final; if (HP_FL_TEST(hp, CHUNKED)) |