mirror of
https://github.com/golang/go
synced 2024-09-28 18:14:29 -06:00
internal/zstd: fix seek offset bounds check in skipFrame
This change enhances the zstd Reader's skipFrame function to validate
the new offset when skipping frames in a seekable stream, preventing
invalid offsets that could occur previously.
A set of "bad" test strings has been added to fuzz_test.go to extend
the robustness checks against potential decompression panics.
Additionally, a new test named TestReaderBad is introduced in
zstd_test.go to verify proper error handling with corrupted input
strings.
The BenchmarkLarge function has also been refactored for clarity,
removing unnecessary timer stops and resets.
Updates #63824
Change-Id: Iccd248756ad6348afa1395c7799350d07402868a
GitHub-Last-Rev: 63055b91e9
GitHub-Pull-Request: golang/go#64056
Reviewed-on: https://go-review.googlesource.com/c/go/+/541220
Reviewed-by: Bryan Mills <bcmills@google.com>
Reviewed-by: David Chase <drchase@google.com>
Reviewed-by: Klaus Post <klauspost@gmail.com>
Auto-Submit: Bryan Mills <bcmills@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
This commit is contained in:
parent
2184a76fb8
commit
ae9fdbd8bc
@ -24,6 +24,7 @@ var badStrings = []string{
|
||||
"(\xb5/\xfd001\x00\x0000000000000000000",
|
||||
"(\xb5/\xfd00\xec\x00\x00&@\x05\x05A7002\x02\x00\x02\x00\x02\x0000000000000000",
|
||||
"(\xb5/\xfd00\xec\x00\x00V@\x05\x0517002\x02\x00\x02\x00\x02\x0000000000000000",
|
||||
"\x50\x2a\x4d\x18\x02\x00\x00\x00",
|
||||
}
|
||||
|
||||
// This is a simple fuzzer to see if the decompressor panics.
|
||||
|
@ -326,12 +326,34 @@ func (r *Reader) skipFrame() error {
|
||||
relativeOffset += 4
|
||||
|
||||
size := binary.LittleEndian.Uint32(r.scratch[:4])
|
||||
if size == 0 {
|
||||
r.blockOffset += int64(relativeOffset)
|
||||
return nil
|
||||
}
|
||||
|
||||
if seeker, ok := r.r.(io.Seeker); ok {
|
||||
if _, err := seeker.Seek(int64(size), io.SeekCurrent); err != nil {
|
||||
return err
|
||||
r.blockOffset += int64(relativeOffset)
|
||||
// Implementations of Seeker do not always detect invalid offsets,
|
||||
// so check that the new offset is valid by comparing to the end.
|
||||
prev, err := seeker.Seek(0, io.SeekCurrent)
|
||||
if err != nil {
|
||||
return r.wrapError(0, err)
|
||||
}
|
||||
r.blockOffset += int64(relativeOffset) + int64(size)
|
||||
end, err := seeker.Seek(0, io.SeekEnd)
|
||||
if err != nil {
|
||||
return r.wrapError(0, err)
|
||||
}
|
||||
if prev > end-int64(size) {
|
||||
r.blockOffset += end - prev
|
||||
return r.makeEOFError(0)
|
||||
}
|
||||
|
||||
// The new offset is valid, so seek to it.
|
||||
_, err = seeker.Seek(prev+int64(size), io.SeekStart)
|
||||
if err != nil {
|
||||
return r.wrapError(0, err)
|
||||
}
|
||||
r.blockOffset += int64(size)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -304,6 +304,17 @@ func TestFileSamples(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestReaderBad(t *testing.T) {
|
||||
for i, s := range badStrings {
|
||||
t.Run(fmt.Sprintf("badStrings#%d", i), func(t *testing.T) {
|
||||
_, err := io.Copy(io.Discard, NewReader(strings.NewReader(s)))
|
||||
if err == nil {
|
||||
t.Error("expected error")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkLarge(b *testing.B) {
|
||||
b.StopTimer()
|
||||
b.ReportAllocs()
|
||||
|
Loading…
Reference in New Issue
Block a user