diff options
Diffstat (limited to 'src/internal/zstd/zstd.go')
| -rw-r--r-- | src/internal/zstd/zstd.go | 28 |
1 files changed, 25 insertions, 3 deletions
diff --git a/src/internal/zstd/zstd.go b/src/internal/zstd/zstd.go index 9cf62a6bac..0230076f50 100644 --- a/src/internal/zstd/zstd.go +++ b/src/internal/zstd/zstd.go @@ -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) + } + 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(relativeOffset) + int64(size) + r.blockOffset += int64(size) return nil } |
