Fix suffix byte ranges on empty files

Reject suffix byte-range requests when the content length is zero instead of
returning an invalid range with endPos=-1. This prevents the file-serving path
from passing a negative end position to SetContentRange and panicking.
This commit is contained in:
Erik Dubbelboer
2026-06-13 05:18:48 +02:00
parent 0643f42190
commit c7e642b843
2 changed files with 42 additions and 0 deletions
+3
View File
@@ -1473,6 +1473,9 @@ func ParseByteRange(byteRange []byte, contentLength int) (startPos, endPos int,
if err != nil {
return 0, 0, err
}
if contentLength <= 0 {
return 0, 0, fmt.Errorf("byte range %q is invalid for empty content", byteRange)
}
startPos := max(contentLength-v, 0)
return startPos, contentLength - 1, nil
}
+39
View File
@@ -541,6 +541,42 @@ func runFSByteRangeSingleThread(t *testing.T, fs *FS) {
testFSByteRange(t, h, "/README.md")
}
func TestFSByteRangeZeroLengthSuffixRange(t *testing.T) {
t.Parallel()
dir := t.TempDir()
if err := os.WriteFile(filepath.Join(dir, "empty.txt"), nil, 0o600); err != nil {
t.Fatalf("cannot create empty test file: %v", err)
}
stop := make(chan struct{})
defer close(stop)
fs := &FS{
Root: dir,
AcceptByteRange: true,
CleanStop: stop,
}
h := fs.NewRequestHandler()
var ctx RequestCtx
ctx.Init(&Request{}, nil, nil)
ctx.Request.SetRequestURI("/empty.txt")
ctx.Request.Header.SetByteRange(-5, -1)
defer func() {
if r := recover(); r != nil {
t.Fatalf("unexpected panic for suffix range on empty file: %v", r)
}
}()
h(&ctx)
resp := readResponseFromCtx(t, &ctx, false)
if resp.StatusCode() != StatusRequestedRangeNotSatisfiable {
t.Fatalf("unexpected status code: %d. Expecting %d", resp.StatusCode(), StatusRequestedRangeNotSatisfiable)
}
}
func testFSByteRange(t *testing.T, h RequestHandler, filePath string) {
t.Helper()
@@ -660,6 +696,9 @@ func TestParseByteRangeError(t *testing.T) {
// byte range exceeding contentLength
testParseByteRangeError(t, "bytes=123-", 12)
// suffix byte range for empty content
testParseByteRangeError(t, "bytes=-5", 0)
// startPos exceeding endPos
testParseByteRangeError(t, "bytes=123-34", 1234)
}