From ab02ea4de4195bd6c4c06f1c8a6e55796bbd428f Mon Sep 17 00:00:00 2001 From: Sunny Klair Date: Thu, 26 Oct 2017 13:48:31 -0400 Subject: [PATCH] Validate index offset table checksums on read --- index.go | 36 ++++++++++++++++++++++++------------ 1 file changed, 24 insertions(+), 12 deletions(-) diff --git a/index.go b/index.go index 972aaa8bde..cc0ad140c4 100644 --- a/index.go +++ b/index.go @@ -619,11 +619,6 @@ func newIndexReader(dir string) (*indexReader, error) { func (r *indexReader) readTOC() error { d := r.decbufAt(len(r.b) - indexTOCLen) - crc := newCRC32() - if _, err := crc.Write(d.get()[:d.len()-4]); err != nil { - return errors.Wrap(err, "write to hash") - } - r.toc.symbols = d.be64() r.toc.series = d.be64() r.toc.labelIndices = d.be64() @@ -631,9 +626,8 @@ func (r *indexReader) readTOC() error { r.toc.postings = d.be64() r.toc.postingsTable = d.be64() - // Validate checksum - if d.be32() != crc.Sum32() { - return errors.Wrap(errInvalidChecksum, "TOC checksum") + if valid, err := r.validCrc(d.be32(), len(r.b)-indexTOCLen, indexTOCLen-4); !valid { + return errors.Wrap(err, "TOC checksum") } return d.err() @@ -646,6 +640,20 @@ func (r *indexReader) decbufAt(off int) decbuf { return decbuf{b: r.b[off:]} } +func (r *indexReader) validCrc(crc uint32, off, cnt int) (bool, error) { + c2 := newCRC32() + if len(r.b) < off+cnt { + return false, errInvalidSize + } + if _, err := c2.Write(r.b[off : off+cnt]); err != nil { + return false, errors.Wrap(err, "write to hash") + } + if c2.Sum32() != crc { + return false, errInvalidChecksum + } + return true, nil +} + // readSymbols reads the symbol table fully into memory and allocates proper strings for them. // Strings backed by the mmap'd memory would cause memory faults if applications keep using them // after the reader is closed. @@ -677,9 +685,10 @@ func (r *indexReader) readOffsetTable(off uint64) (map[string]uint32, error) { const sep = "\xff" var ( - d1 = r.decbufAt(int(off)) - d2 = d1.decbuf(d1.be32int()) - cnt = d2.be32() + d1 = r.decbufAt(int(off)) + tableLen = d1.be32int() + d2 = d1.decbuf(tableLen) + cnt = d2.be32() ) res := make(map[string]uint32, 512) @@ -696,7 +705,10 @@ func (r *indexReader) readOffsetTable(off uint64) (map[string]uint32, error) { cnt-- } - // TODO(fabxc): verify checksum from remainer of d1. + if valid, err := r.validCrc(d1.be32(), int(off)+4, tableLen); !valid { + return res, errors.Wrap(err, "offset table checksum") + } + return res, d2.err() }