about summary refs log tree commit homepage
path: root/http_parser.rl
diff options
context:
space:
mode:
Diffstat (limited to 'http_parser.rl')
-rw-r--r--http_parser.rl56
1 files changed, 37 insertions, 19 deletions
diff --git a/http_parser.rl b/http_parser.rl
index 8e82828..5683b7d 100644
--- a/http_parser.rl
+++ b/http_parser.rl
@@ -21,6 +21,18 @@ static bool length_incr(off_t *len, unsigned c)
         return false;
 }
 
+static char *skip_header(struct mog_http *http, char *buf, const char *pe)
+{
+        char *p;
+
+        assert(http->_p.line_end > 0 && "no previous request/header line");
+        assert(buf[http->_p.line_end] == '\n' && "bad http->_p.line_end");
+        p = buf + http->_p.line_end + 1;
+        assert(p <= pe && "overflow");
+
+        return p;
+}
+
 %%{
         machine http_parser;
         include http_common "http_common.rl";
@@ -69,20 +81,31 @@ static bool length_incr(off_t *len, unsigned c)
                         "bytes=" > {
                                 http->_p.range_beg = http->_p.range_end = -1;
                         }
-                        (digit*) $ {
-                                if (http->_p.range_beg < 0)
-                                        http->_p.range_beg = 0;
-                                if (!length_incr(&http->_p.range_beg, fc))
-                                        fbreak;
-                        }
-                        '-'
-                        (digit*) $ {
-                                if (http->_p.range_end < 0)
-                                        http->_p.range_end = 0;
-                                if (!length_incr(&http->_p.range_end, fc))
-                                        fbreak;
+                        (
+                                (digit*) $ {
+                                        if (http->_p.range_beg < 0)
+                                                http->_p.range_beg = 0;
+                                        if (!length_incr(&http->_p.range_beg,
+                                                         fc))
+                                                fbreak;
+                                }
+                                '-'
+                                (digit*) $ {
+                                        if (http->_p.range_end < 0)
+                                                http->_p.range_end = 0;
+                                        if (!length_incr(&http->_p.range_end,
+                                                         fc))
+                                                fbreak;
+                                }
+                        ) $! {
+                                http->_p.bad_range = 1;
+                                p = skip_header(http, buf, pe);
+                                fgoto ignored_header;
                         }
-                ) $! { errno = EINVAL; fbreak; }
+                ) $! {
+                        p = skip_header(http, buf, pe);
+                        fgoto ignored_header;
+                }
                 eor @ { http->_p.has_range = 1; };
         transfer_encoding_chunked = "Transfer-Encoding:"i sep
                 "chunked"i eor > { http->_p.chunked = 1; };
@@ -102,12 +125,7 @@ static bool length_incr(off_t *len, unsigned c)
                   content_md5 |
                   connection ) $!
                 {
-                        assert(http->_p.line_end > 0 &&
-                               "no previous request/header line");
-                        assert(buf[http->_p.line_end] == '\n' &&
-                               "bad http->_p.line_end");
-                        p = buf + http->_p.line_end + 1;
-                        assert(p <= pe && "overflow");
+                        p = skip_header(http, buf, pe);
                         fgoto ignored_header;
                 };
         headers = header_line* '\r''\n' > { really_done = 1; fbreak; };