]> Cypherpunks repositories - gostls13.git/commitdiff
net/http: Fix Range off-by-one error
authorJed Denlea <jed@fastly.com>
Tue, 16 Dec 2014 08:24:19 +0000 (00:24 -0800)
committerBrad Fitzpatrick <bradfitz@golang.org>
Sat, 20 Dec 2014 23:42:44 +0000 (23:42 +0000)
Given a file of size N, a request for "Range: bytes=N-*" should
return a 416 [1].  Currently, it returns a 206 and a body of 0
bytes, with the illegal Content-Range of "bytes N-(N-1)/N" [2].

[1]: RFC 7233, sec 2.1: "If a valid byte-range-set includes at least one
byte-range-spec with a first-byte-pos that is less than the current
length of the representation, [...]".  sec 3.1: "If all of the
preconditions are true, the server supports the Range header field for
the target resource, and the specified range(s) are invalid or
unsatisfiable, the server SHOULD send a 416 (Range Not Satisfiable)
response."

[2]: RFC 7233, sec 4.2: "A Content-Range field value is invalid if it
contains a byte-range-resp that has a last-byte-pos value less than its
first-byte-pos value, [...]"

Fixes #8988

Change-Id: If3e1134e7815f5d361efea01873b29aafe3de817
Reviewed-on: https://go-review.googlesource.com/1862
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
src/net/http/fs.go
src/net/http/fs_test.go

index e322f710a5d95361e9e6c0055641137b1b05b65d..9a80123f6d8e4805652f65ca8789034790b4bb6c 100644 (file)
@@ -503,7 +503,7 @@ func parseRange(s string, size int64) ([]httpRange, error) {
                        r.length = size - r.start
                } else {
                        i, err := strconv.ParseInt(start, 10, 64)
-                       if err != nil || i > size || i < 0 {
+                       if err != nil || i >= size || i < 0 {
                                return nil, errors.New("invalid range")
                        }
                        r.start = i
index 8770d9b4109e27f972cc780e436c35951a7b62d7..72f8c2cf1d67d4c202cf7804a5556ceabb427d65 100644 (file)
@@ -50,15 +50,23 @@ var ServeFileRangeTests = []struct {
        {r: "bytes=2-", code: StatusPartialContent, ranges: []wantRange{{2, testFileLen}}},
        {r: "bytes=-5", code: StatusPartialContent, ranges: []wantRange{{testFileLen - 5, testFileLen}}},
        {r: "bytes=3-7", code: StatusPartialContent, ranges: []wantRange{{3, 8}}},
-       {r: "bytes=20-", code: StatusRequestedRangeNotSatisfiable},
        {r: "bytes=0-0,-2", code: StatusPartialContent, ranges: []wantRange{{0, 1}, {testFileLen - 2, testFileLen}}},
        {r: "bytes=0-1,5-8", code: StatusPartialContent, ranges: []wantRange{{0, 2}, {5, 9}}},
        {r: "bytes=0-1,5-", code: StatusPartialContent, ranges: []wantRange{{0, 2}, {5, testFileLen}}},
        {r: "bytes=5-1000", code: StatusPartialContent, ranges: []wantRange{{5, testFileLen}}},
        {r: "bytes=0-,1-,2-,3-,4-", code: StatusOK}, // ignore wasteful range request
-       {r: "bytes=0-" + itoa(testFileLen-2), code: StatusPartialContent, ranges: []wantRange{{0, testFileLen - 1}}},
-       {r: "bytes=0-" + itoa(testFileLen-1), code: StatusPartialContent, ranges: []wantRange{{0, testFileLen}}},
-       {r: "bytes=0-" + itoa(testFileLen), code: StatusPartialContent, ranges: []wantRange{{0, testFileLen}}},
+       {r: "bytes=0-9", code: StatusPartialContent, ranges: []wantRange{{0, testFileLen - 1}}},
+       {r: "bytes=0-10", code: StatusPartialContent, ranges: []wantRange{{0, testFileLen}}},
+       {r: "bytes=0-11", code: StatusPartialContent, ranges: []wantRange{{0, testFileLen}}},
+       {r: "bytes=10-11", code: StatusPartialContent, ranges: []wantRange{{testFileLen - 1, testFileLen}}},
+       {r: "bytes=10-", code: StatusPartialContent, ranges: []wantRange{{testFileLen - 1, testFileLen}}},
+       {r: "bytes=11-", code: StatusRequestedRangeNotSatisfiable},
+       {r: "bytes=11-12", code: StatusRequestedRangeNotSatisfiable},
+       {r: "bytes=12-12", code: StatusRequestedRangeNotSatisfiable},
+       {r: "bytes=11-100", code: StatusRequestedRangeNotSatisfiable},
+       {r: "bytes=12-100", code: StatusRequestedRangeNotSatisfiable},
+       {r: "bytes=100-", code: StatusRequestedRangeNotSatisfiable},
+       {r: "bytes=100-1000", code: StatusRequestedRangeNotSatisfiable},
 }
 
 func TestServeFile(t *testing.T) {