From f7cecf0945fc5d7eff1aea96764dec854c5fe9ce Mon Sep 17 00:00:00 2001 From: Klaus Post Date: Tue, 31 May 2022 19:06:57 -0700 Subject: [PATCH] Make isIndexedMetaV2 return errors (#15012) Indexed streams would be decoded by the legacy loader if there was an error loading it. Return an error when the stream is indexed and it cannot be loaded. Fixes "unknown minor metadata version" on corrupted xl.meta files and returns an actual error. --- cmd/metacache-entries.go | 4 +++- cmd/xl-storage-format-utils.go | 8 ++++++-- cmd/xl-storage-format-v2.go | 24 ++++++++++++------------ cmd/xl-storage-format_test.go | 4 ++-- 4 files changed, 23 insertions(+), 17 deletions(-) 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") }