Skip to content

Commit 7c7c5a0

Browse files
Copilotsendya
andcommitted
fix: pass correct chunk index to checkChunkSize in getContents
In getContents, checkChunkSize was called with idx (reqChunks[from]) but the chunk file was opened for availableChunks[index]. These can be different values, causing incorrect size validation — especially for the last chunk which has a different (smaller) expected size. Fixes omalloc/tavern#issue Co-authored-by: sendya <5404542+sendya@users.noreply.github.com>
1 parent d51c0bf commit 7c7c5a0

File tree

2 files changed

+72
-1
lines changed

2 files changed

+72
-1
lines changed

server/middleware/caching/caching_chunkpart_test.go

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,3 +90,74 @@ func Test_getContents(t *testing.T) {
9090
// 所以最终会返回一个流,包含 chunk1 和 chunk2 的数据
9191
assert.Equal(t, 1, len(readers))
9292
}
93+
94+
// Test_getContents_lastChunkSizeMismatch verifies that checkChunkSize receives
95+
// the correct chunk index (availableChunks[index]) rather than the requested
96+
// chunk index (idx). When the available anchor chunk is the last chunk with a
97+
// smaller size, passing the wrong index would cause a false size-mismatch error.
98+
func Test_getContents_lastChunkSizeMismatch(t *testing.T) {
99+
memoryBucket, _ := memory.New(&storage.BucketConfig{}, sharedkv.NewEmpty())
100+
101+
req, _ := http.NewRequestWithContext(t.Context(), http.MethodGet, "http://www.example.com/path/to/2.apk", nil)
102+
req.Header.Set("Range", "bytes=524288-1672863")
103+
objectID, _ := newObjectIDFromRequest(req, "", true)
104+
105+
blockSize := uint64(524288)
106+
totalSize := blockSize*3 + 100000 // 3 full chunks + 1 partial last chunk (100000 bytes)
107+
108+
c := &Caching{
109+
log: log.NewHelper(log.GetLogger()),
110+
processor: mockProcessorChain(),
111+
id: objectID,
112+
req: req,
113+
opt: &cachingOption{
114+
SliceSize: blockSize,
115+
},
116+
md: &object.Metadata{
117+
ID: objectID,
118+
Size: totalSize,
119+
BlockSize: blockSize,
120+
Chunks: bitmap.Bitmap{},
121+
},
122+
bucket: memoryBucket,
123+
proxyClient: proxy.New(),
124+
}
125+
126+
// Cached chunks: 0 (full) and 3 (last, partial)
127+
c.md.Chunks.Set(0)
128+
c.md.Chunks.Set(3)
129+
130+
// Write chunk 0 with full block size
131+
f0, _, err := memoryBucket.WriteChunkFile(context.Background(), objectID, 0)
132+
assert.NoError(t, err)
133+
_, _ = f0.Write(makebuf(int(blockSize)))
134+
_ = f0.Close()
135+
136+
// Write chunk 3 (last chunk) with partial size
137+
f3, _, err := memoryBucket.WriteChunkFile(context.Background(), objectID, 3)
138+
assert.NoError(t, err)
139+
_, _ = f3.Write(makebuf(int(totalSize % blockSize))) // 100000 bytes
140+
_ = f3.Close()
141+
142+
// Request chunks 1, 2, 3
143+
// idx will be reqChunks[0]=1, but the anchor chunk found is chunk 3 (the last chunk).
144+
// Before the fix, checkChunkSize was called with idx=1 instead of 3,
145+
// causing it to expect full blockSize (524288) for a 100000-byte file.
146+
reqChunks := []uint32{1, 2, 3}
147+
148+
readers := make([]io.ReadCloser, 0, len(reqChunks))
149+
for i := 0; i < len(reqChunks); {
150+
reader, count, err := getContents(c, reqChunks, uint32(i))
151+
assert.NoError(t, err, "getContents should not return a size mismatch error")
152+
153+
if count == -1 {
154+
break
155+
}
156+
157+
readers = append(readers, reader)
158+
i += count
159+
}
160+
161+
t.Logf("all readers %d", len(readers))
162+
assert.Equal(t, 1, len(readers))
163+
}

server/middleware/caching/internal.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,7 +192,7 @@ func getContents(c *Caching, reqChunks []uint32, from uint32) (io.ReadCloser, in
192192
if index < len(availableChunks) {
193193
chunkFile, _ := getSliceChunkFile(c, availableChunks[index])
194194
if chunkFile != nil {
195-
if err := checkChunkSize(c, chunkFile, idx); err != nil {
195+
if err := checkChunkSize(c, chunkFile, availableChunks[index]); err != nil {
196196
_ = chunkFile.Close()
197197
_ = c.bucket.Discard(context.Background(), c.id)
198198
return nil, 0, err

0 commit comments

Comments
 (0)