fs: fix negative offset when a suffix Range request exceeds object size

A Range header requesting a suffix longer than the object (e.g.
"bytes=-90407" against a 5 byte object) caused RangeOption.Decode to
compute a negative offset (size - End), which serve.Object then used
directly as a slice/seek offset and panicked with "slice bounds out of
range". FixRangeOption (used by backends like OneDrive/Box that lack
native suffix-range support) had the same root cause: it produced a
RangeOption with a negative Start, which Header() silently dropped,
turning the request into the wrong byte range instead of erroring or
serving the whole object.

Per RFC 7233 section 2.1, when the suffix-length exceeds the
representation size, the entire representation should be served.
Clamp the computed offset/start to 0 in both places.

Fixes #6310
This commit is contained in:
Amit Mishra
2026-07-04 09:11:52 +01:00
committed by Nick Craig-Wood
parent b12251f07f
commit cb41e42d04
3 changed files with 53 additions and 1 deletions
+14 -1
View File
@@ -126,6 +126,12 @@ func (o *RangeOption) Decode(size int64) (offset, limit int64) {
} else {
if o.End >= 0 {
offset = size - o.End
if offset < 0 {
// RFC 7233 section 2.1: if the suffix-length is
// larger than the representation, use the entire
// representation.
offset = 0
}
} else {
offset = 0
}
@@ -162,7 +168,14 @@ func FixRangeOption(options []OpenOption, size int64) {
case *RangeOption:
// If start is < 0 then fetch from the end
if x.Start < 0 {
x = &RangeOption{Start: size - x.End, End: -1}
start := size - x.End
if start < 0 {
// RFC 7233 section 2.1: if the suffix-length is
// larger than the representation, use the entire
// representation (#6310).
start = 0
}
x = &RangeOption{Start: start, End: -1}
options[i] = x
}
// If end is too big or undefined, fetch to the end