From 488a9ac1bb68a295aae1569452a8e9bf2ec8ba3f Mon Sep 17 00:00:00 2001 From: Ben McClelland Date: Mon, 1 Sep 2025 17:12:38 -0700 Subject: [PATCH] fix: panic in signed-chunk-reader with incorrect debug string The following panic was triggered when mc client (that uses chunked uploads) would upload a 171164 byte file. This likely could have been hit with other sizes as well, but this size was able to reliably reproduce the issue. panic: runtime error: slice bounds out of range [:2] with capacity 1 goroutine 66 [running]: github.com/versity/versitygw/s3api/utils.(*ChunkReader).parseChunkHeaderBytes(0x14000276200, {0x14000167fff?, 0x14000103180?, 0x200000003?}) versitygw/s3api/utils/signed-chunk-reader.go:372 +0xe54 github.com/versity/versitygw/s3api/utils.(*ChunkReader).parseAndRemoveChunkInfo(0x14000276200, {0x14000167fff, 0x1, 0x1}) versitygw/s3api/utils/signed-chunk-reader.go:251 +0x50 github.com/versity/versitygw/s3api/utils.(*ChunkReader).Read(0x14000276200, {0x14000160000, 0x14000056c00?, 0x8000}) versitygw/s3api/utils/signed-chunk-reader.go:126 +0x188 io.(*teeReader).Read(0x140000b09c0, {0x14000160000, 0x105e7b368?, 0x8000}) /usr/local/go/src/io/io.go:628 +0x34 ... The reproducer is: % truncate -s 171764 testfile % mc cp testfile gwtest/mybucket/testfile mc: Failed to copy `/Users/ben/repo/s3perf/tools/testfile`. Put "http://127.0.0.1:7070/mybucket/testfile": dial tcp 127.0.0.1:7070: connect: connection refused The panic can happen because the capacity of header ([]byte) at the point of the debuglog line can be less than 2, but we were trying to always send the first 2 bytes to the debug log. --- s3api/utils/signed-chunk-reader.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/s3api/utils/signed-chunk-reader.go b/s3api/utils/signed-chunk-reader.go index feb31d02..d356361c 100644 --- a/s3api/utils/signed-chunk-reader.go +++ b/s3api/utils/signed-chunk-reader.go @@ -363,7 +363,7 @@ func (cr *ChunkReader) parseChunkHeaderBytes(header []byte) (int64, string, int, if !cr.isFirstHeader { err := readAndSkip(rdr, '\r', '\n') if err != nil { - debuglogger.Logf("failed to read chunk header first 2 bytes: (should be): \\r\\n, (got): %q", header[:2]) + debuglogger.Logf("failed to read chunk header first 2 bytes: (should be): \\r\\n, (got): %q", header[:min(2, len(header))]) return cr.handleRdrErr(err, header) } }