diff options
author | Eric Wong <normalperson@yhbt.net> | 2012-01-31 19:36:50 -0800 |
---|---|---|
committer | Eric Wong <normalperson@yhbt.net> | 2012-01-31 19:43:47 -0800 |
commit | 97ecfeb02dac5721db0b651336fddd2810d916f0 (patch) | |
tree | 7a8605692b385fff2a0ef478794fa1d809db51d8 /http_parser.rl | |
parent | d0686790881292dcefe4d8d4d9922866d4955a04 (diff) | |
download | cmogstored-97ecfeb02dac5721db0b651336fddd2810d916f0.tar.gz |
This means we can move towards avoid needing to buffer data for many common cases.
Diffstat (limited to 'http_parser.rl')
-rw-r--r-- | http_parser.rl | 43 |
1 files changed, 36 insertions, 7 deletions
diff --git a/http_parser.rl b/http_parser.rl index 17df0a1..5cd1586 100644 --- a/http_parser.rl +++ b/http_parser.rl @@ -5,6 +5,22 @@ #include "cmogstored.h" #include "http_util.h" +static bool length_incr(off_t *len, unsigned c) +{ + off_t prev = *len; + + *len *= 10; + *len += c - '0'; + + if (*len >= prev) + return true; + + errno = ERANGE; + *len = -1; + + return false; +} + %%{ machine http_parser; include http_common "http_common.rl"; @@ -28,13 +44,25 @@ ('0'|'1'> { http->persistent = 1; }) '\r'LF; content_length = "Content-Length:"i sep - (digit+) > { http->tmp_tip = to_u16(fpc - buf); } - eor > { http->content_len = http_digit(http, buf, fpc); }; + (digit+) $ { + if (!length_incr(&http->content_len, fc)) + fbreak; + } + $! { errno = EINVAL; fbreak; } + eor; content_range = "Content-Range:"i sep "bytes"LWS+ - (digit+) > { http->tmp_tip = to_u16(fpc - buf); } - "-" > { http->range_beg = http_digit(http, buf, fpc); } - (digit+) > { http->tmp_tip = to_u16(fpc - buf); } - "/*" > { http->range_end = http_digit(http, buf, fpc); } + (digit+) $ { + if (!length_incr(&http->range_beg, fc)) + fbreak; + } + $! { errno = EINVAL; fbreak; } + "-" + (digit+) $ { + if (!length_incr(&http->range_end, fc)) + fbreak; + } + $! { errno = EINVAL; fbreak; } + "/*" eor > { http->has_content_range = 1; }; transfer_encoding_chunked = "Transfer-Encoding:"i sep "chunked"i eor > { http->chunked = 1; }; @@ -102,6 +130,7 @@ mog_http_parse(struct mog_http *http, char *buf, size_t len) assert((void *)(pe - p) == (void *)(len - off) && "pointers aren't same distance"); + errno = 0; %% write exec; if (really_done) @@ -110,7 +139,7 @@ mog_http_parse(struct mog_http *http, char *buf, size_t len) http->cs = cs; http->offset = p - buf; - if (cs == http_parser_error) + if (cs == http_parser_error || errno) return MOG_PARSER_ERROR; assert(p <= pe && "buffer overflow after http parse"); |