about summary refs log tree commit homepage
diff options
context:
space:
mode:
authorEric Wong <e@yhbt.net>2020-03-17 06:56:51 +0000
committerEric Wong <e@yhbt.net>2020-03-19 02:35:57 +0000
commit5ba9c3ef8a90a64ff34dc069d4ed89f91d38606a (patch)
tree43a81cee34c0dd1cb809929489c9f16bb580721c
parent63a57fee9e75c6fad2b146a125ac8f029773a36b (diff)
downloadcmogstored-5ba9c3ef8a90a64ff34dc069d4ed89f91d38606a.tar.gz
RFC 7230 3.3.3, point 3 states:
> If a Transfer-Encoding header field
> is present in a request and the chunked transfer coding is not
> the final encoding, the message body length cannot be determined
> reliably; the server MUST respond with the 400 (Bad Request)
> status code and then close the connection.

And no MogileFS client is known to send "gzip", "deflate", or
"compress" as part of the Transfer-Encoding, so we'll only
accept "chunked".
-rw-r--r--http_parser.rl6
-rw-r--r--test/http-parser-1.c9
-rw-r--r--test/http_put.rb11
3 files changed, 25 insertions, 1 deletions
diff --git a/http_parser.rl b/http_parser.rl
index 9f848b0..0685d27 100644
--- a/http_parser.rl
+++ b/http_parser.rl
@@ -112,7 +112,11 @@ static char *skip_header(struct mog_http *http, char *buf, const char *pe)
                 }
                 eor @ { http->_p.has_range = 1; };
         transfer_encoding_chunked = "Transfer-Encoding:"i sep
-                "chunked"i eor > { http->_p.chunked = 1; };
+                # XXX we don't know how to deal with "gzip", "deflate", or
+                # "compress" as described in RFC 7230, so reject them, here.
+                "chunked"i
+                $! { errno = EINVAL; fbreak; }
+                eor @ { http->_p.chunked = 1; };
         trailer = "Trailer:"i sep
                 (("Content-MD5"i @ { http->_p.has_md5 = 1; })
                  | header_name | ',')
diff --git a/test/http-parser-1.c b/test/http-parser-1.c
index c6ff819..ac20dd3 100644
--- a/test/http-parser-1.c
+++ b/test/http-parser-1.c
@@ -149,6 +149,15 @@ int main(void)
                        && "buffer repositioned to body start");
                 assert(!http->_p.usage_txt && "not a usage request");
         }
+        if ("HTTP/1.1 PUT Transfer-Encoding: bogus header") {
+                buf_set("PUT /foo HTTP/1.1\r\n"
+                        "Host: 127.6.6.6\r\n"
+                        "Transfer-Encoding: bogus\r\n"
+                        "\r\n"
+                        "16\r\npartial...");
+                state = mog_http_parse(http, buf, len);
+                assert(state == MOG_PARSER_ERROR && "parser not errored");
+        }
 
         if ("HTTP/1.1 PUT with Content-Range") {
                 buf_set("PUT /foo HTTP/1.1\r\n"
diff --git a/test/http_put.rb b/test/http_put.rb
index 21d65c7..0479629 100644
--- a/test/http_put.rb
+++ b/test/http_put.rb
@@ -160,6 +160,17 @@ class TestHTTPPut < Test::Unit::TestCase
     assert( ! File.exist?("#@tmpdir/dev666/foo") )
   end
 
+  def test_put_bogus
+    max = 0xffffffff << 64
+    req = "PUT /dev666/foo HTTP/1.1\r\n" \
+          "Transfer-Encoding: bogus\r\n" \
+          "\r\n"
+    @client.write(req)
+    resp = @client.read
+    assert_match(%r{\AHTTP/1\.1 400 Bad Request\r\n}, resp)
+    assert( ! File.exist?("#@tmpdir/dev666/foo") )
+  end
+
   def test_put_range_beg_overflow
     max = 0xffffffff << 64
     req = "PUT /dev666/foo HTTP/1.1\r\n" \