]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Compliance: Improved HTTP Range header field validation.
authorAlex Rousskov <rousskov@measurement-factory.com>
Mon, 2 Aug 2010 16:43:03 +0000 (10:43 -0600)
committerAlex Rousskov <rousskov@measurement-factory.com>
Mon, 2 Aug 2010 16:43:03 +0000 (10:43 -0600)
1) Improved HttpHdrRangeSpec::parseInit() to parse syntactically valid
range specs:

  * Suffix ranges with 0 length (i.e. -0) are syntactically valid.

  * Check that last-byte-pos is greater than or equal to first-byte-pos.

After the change, HttpHdrRangeSpec::parseInit() successfully parses suffix
ranges with 0 length. They were rejected before. RFC 2616 section 14.35.1 says
such range specs are syntactically valid but unsatisfiable. Thus, we should
ignore the range spec itself, but not the whole range header. These range
specs will be rejected later, during canonization.

2) In HttpHdrRangeSpec::parseInit(), ignore the whole range header if one of
range specs is syntactically invalid (i.e. range spec parsing fails).

Co-Advisor test case: test_clause/rfc2616/invalidRange

src/HttpHdrRange.cc

index 8139d32e6af221c3289cee02bc188432bc373ef0..401b46c1369d661ad61ef174ad4e48d4c9bbc454 100644 (file)
@@ -98,7 +98,7 @@ HttpHdrRangeSpec::parseInit(const char *field, int flen)
     } else
         /* must have a '-' somewhere in _this_ field */
         if (!((p = strchr(field, '-')) || (p - field >= flen))) {
-            debugs(64, 2, "ignoring invalid (missing '-') range-spec near: '" << field << "'");
+            debugs(64, 2, "invalid (missing '-') range-spec near: '" << field << "'");
             return false;
         } else {
             if (!httpHeaderParseOffset(field, &offset))
@@ -113,18 +113,18 @@ HttpHdrRangeSpec::parseInit(const char *field, int flen)
                 if (!httpHeaderParseOffset(p, &last_pos))
                     return false;
 
+                // RFC 2616 s14.35.1 MUST: last-byte-pos >= first-byte-pos
+                if (last_pos < offset) {
+                    debugs(64, 2, "invalid (last-byte-pos < first-byte-pos) range-spec near: " << field);
+                    return false;
+                }
+
                 HttpHdrRangeSpec::HttpRange aSpec (offset, last_pos + 1);
 
                 length = aSpec.size();
             }
         }
 
-    /* we managed to parse, check if the result makes sence */
-    if (length == 0) {
-        debugs(64, 2, "ignoring invalid (zero length) range-spec near: '" << field << "'");
-        return false;
-    }
-
     return true;
 }
 
@@ -248,7 +248,6 @@ HttpHdrRange::parseInit(const String * range_spec)
     const char *item;
     const char *pos = NULL;
     int ilen;
-    int count = 0;
     assert(this && range_spec);
     ++ParsedCount;
     debugs(64, 8, "parsing range field: '" << range_spec << "'");
@@ -264,19 +263,21 @@ HttpHdrRange::parseInit(const String * range_spec)
     while (strListGetItem(range_spec, ',', &item, &ilen, &pos)) {
         HttpHdrRangeSpec *spec = HttpHdrRangeSpec::Create(item, ilen);
         /*
-         * HTTP/1.1 draft says we must ignore the whole header field if one spec
-         * is invalid. However, RFC 2068 just says that we must ignore that spec.
+         * RFC 2616 section 14.35.1: MUST ignore Range with
+         * at least one syntactically invalid byte-range-specs.
          */
+        if (!spec) {
+            while (!specs.empty())
+                delete specs.pop_back();
+            debugs(64, 2, "ignoring invalid range field: '" << range_spec << "'");
+            break;
+        }
 
-        if (spec)
-            specs.push_back(spec);
-
-        ++count;
+        specs.push_back(spec);
     }
 
-    debugs(64, 8, "parsed range range count: " << count << ", kept " <<
-           specs.size());
-    return specs.count != 0;
+    debugs(64, 8, "got range specs: " << specs.size());
+    return !specs.empty();
 }
 
 HttpHdrRange::~HttpHdrRange()