diff --git a/cmd/metacache-entries.go b/cmd/metacache-entries.go index 3ced82825..41c3da3b1 100644 --- a/cmd/metacache-entries.go +++ b/cmd/metacache-entries.go @@ -168,8 +168,10 @@ func (e *metaCacheEntry) isLatestDeletemarker() bool { if !isXL2V1Format(e.metadata) { return false } - if meta, _ := isIndexedMetaV2(e.metadata); meta != nil { + if meta, _, err := isIndexedMetaV2(e.metadata); meta != nil { return meta.IsLatestDeleteMarker() + } else if err != nil { + return true } // Fall back... xlMeta, err := e.xlmeta() diff --git a/cmd/xl-storage-format-utils.go b/cmd/xl-storage-format-utils.go index 51ef99a77..3d9ea8864 100644 --- a/cmd/xl-storage-format-utils.go +++ b/cmd/xl-storage-format-utils.go @@ -50,7 +50,9 @@ func getAllFileInfoVersions(xlMetaBuf []byte, volume, path string) (FileInfoVers var versions []FileInfo var err error - if buf, _ := isIndexedMetaV2(xlMetaBuf); buf != nil { + if buf, _, e := isIndexedMetaV2(xlMetaBuf); e != nil { + return FileInfoVersions{}, e + } else if buf != nil { versions, err = buf.ListVersions(volume, path) } else { var xlMeta xlMetaV2 @@ -87,7 +89,9 @@ func getFileInfo(xlMetaBuf []byte, volume, path, versionID string, data bool) (F var fi FileInfo var err error var inData xlMetaInlineData - if buf, data := isIndexedMetaV2(xlMetaBuf); buf != nil { + if buf, data, e := isIndexedMetaV2(xlMetaBuf); e != nil { + return FileInfo{}, e + } else if buf != nil { inData = data fi, err = buf.ToFileInfo(volume, path, versionID) if len(buf) != 0 && errors.Is(err, errFileNotFound) { diff --git a/cmd/xl-storage-format-v2.go b/cmd/xl-storage-format-v2.go index 4d04cb841..cfa38d09b 100644 --- a/cmd/xl-storage-format-v2.go +++ b/cmd/xl-storage-format-v2.go @@ -793,34 +793,32 @@ func decodeVersions(buf []byte, versions int, fn func(idx int, hdr, meta []byte) } // isIndexedMetaV2 returns non-nil result if metadata is indexed. -// If data doesn't validate nil is also returned. -func isIndexedMetaV2(buf []byte) (meta xlMetaBuf, data xlMetaInlineData) { +// Returns 3x nil if not XLV2 or not indexed. +// If indexed and unable to parse an error will be returned. +func isIndexedMetaV2(buf []byte) (meta xlMetaBuf, data xlMetaInlineData, err error) { buf, major, minor, err := checkXL2V1(buf) - if err != nil { - return nil, nil - } - if major != 1 || minor < 3 { - return nil, nil + if err != nil || major != 1 || minor < 3 { + return nil, nil, nil } meta, buf, err = msgp.ReadBytesZC(buf) if err != nil { - return nil, nil + return nil, nil, err } if crc, nbuf, err := msgp.ReadUint32Bytes(buf); err == nil { // Read metadata CRC buf = nbuf if got := uint32(xxhash.Sum64(meta)); got != crc { - return nil, nil + return nil, nil, fmt.Errorf("xlMetaV2.Load version(%d), CRC mismatch, want 0x%x, got 0x%x", minor, crc, got) } } else { - return nil, nil + return nil, nil, err } data = buf if data.validate() != nil { data.repair() } - return meta, data + return meta, data, nil } type xlMetaV2ShallowVersion struct { @@ -865,7 +863,9 @@ func (x *xlMetaV2) LoadOrConvert(buf []byte) error { // Load all versions of the stored data. // Note that references to the incoming buffer will be kept. func (x *xlMetaV2) Load(buf []byte) error { - if meta, data := isIndexedMetaV2(buf); meta != nil { + if meta, data, err := isIndexedMetaV2(buf); err != nil { + return err + } else if meta != nil { return x.loadIndexed(meta, data) } // Convert older format. diff --git a/cmd/xl-storage-format_test.go b/cmd/xl-storage-format_test.go index ba776837c..ffdc1beb2 100644 --- a/cmd/xl-storage-format_test.go +++ b/cmd/xl-storage-format_test.go @@ -514,7 +514,7 @@ func BenchmarkXlMetaV2Shallow(b *testing.B) { b.ResetTimer() b.ReportAllocs() for i := 0; i < b.N; i++ { - buf, _ := isIndexedMetaV2(enc) + buf, _, _ := isIndexedMetaV2(enc) if buf == nil { b.Fatal("buf == nil") } @@ -529,7 +529,7 @@ func BenchmarkXlMetaV2Shallow(b *testing.B) { b.ResetTimer() b.ReportAllocs() for i := 0; i < b.N; i++ { - buf, _ := isIndexedMetaV2(enc) + buf, _, _ := isIndexedMetaV2(enc) if buf == nil { b.Fatal("buf == nil") }