diff --git a/api/layer/multi_object_reader.go b/api/layer/multi_object_reader.go index 0f401923..da6dc82f 100644 --- a/api/layer/multi_object_reader.go +++ b/api/layer/multi_object_reader.go @@ -93,15 +93,22 @@ func newMultiObjectReader(ctx context.Context, cfg multiObjectReaderConfig) (*mu } func findStartPart(cfg multiObjectReaderConfig) (index int, offset uint64) { - return findPartByPosition(cfg.off, cfg.parts) + position := cfg.off + for i, part := range cfg.parts { + // Strict inequality when searching for start position to avoid reading zero length part. + if position < part.Size { + return i, position + } + position -= part.Size + } + + return -1, 0 } func findEndPart(cfg multiObjectReaderConfig) (index int, length uint64) { - return findPartByPosition(cfg.off+cfg.ln, cfg.parts) -} - -func findPartByPosition(position uint64, parts []partObj) (index int, positionInPart uint64) { - for i, part := range parts { + position := cfg.off + cfg.ln + for i, part := range cfg.parts { + // Non-strict inequality when searching for end position to avoid out of payload range error. if position <= part.Size { return i, position } diff --git a/api/layer/multi_object_reader_test.go b/api/layer/multi_object_reader_test.go index 3fa15c94..3b57b740 100644 --- a/api/layer/multi_object_reader_test.go +++ b/api/layer/multi_object_reader_test.go @@ -90,6 +90,16 @@ func TestMultiReader(t *testing.T) { off: parts[0].Size - 4, ln: parts[1].Size + 8, }, + { + name: "second part", + off: parts[0].Size, + ln: parts[1].Size, + }, + { + name: "second and third", + off: parts[0].Size, + ln: parts[1].Size + parts[2].Size, + }, { name: "offset out of range", off: uint64(len(fullPayload) + 1),