snapshot: read meta.json correctly. (#5193)

* snapshot: read meta.json correctly.

Fixes #4452.
This commit is contained in:
Hans Hasselberg 2019-01-08 17:06:28 +01:00 committed by GitHub
parent 7b1bd33add
commit 08502cfa61
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 36 additions and 2 deletions

View File

@ -18,6 +18,7 @@ import (
"fmt"
"hash"
"io"
"io/ioutil"
"time"
"github.com/hashicorp/raft"
@ -193,8 +194,19 @@ func read(in io.Reader, metadata *raft.SnapshotMeta, snap io.Writer) error {
switch hdr.Name {
case "meta.json":
dec := json.NewDecoder(io.TeeReader(archive, metaHash))
if err := dec.Decode(&metadata); err != nil {
// Previously we used json.Decode to decode the archive stream. There are
// edgecases in which it doesn't read all the bytes from the stream, even
// though the json object is still being parsed properly. Since we
// simutaniously feeded everything to metaHash, our hash ended up being
// different than what we calculated when creating the snapshot. Which in
// turn made the snapshot verification fail. By explicitly reading the
// whole thing first we ensure that we calculate the correct hash
// independent of how json.Decode works internally.
buf, err := ioutil.ReadAll(io.TeeReader(archive, metaHash))
if err != nil {
return fmt.Errorf("failed to read snapshot metadata: %v", err)
}
if err := json.Unmarshal(buf, &metadata); err != nil {
return fmt.Errorf("failed to decode snapshot metadata: %v", err)
}

View File

@ -63,6 +63,25 @@ func TestArchive(t *testing.T) {
}
}
func TestArchive_GoodData(t *testing.T) {
paths := []string{
"../test/snapshot/spaces-meta.tar",
}
for i, p := range paths {
f, err := os.Open(p)
if err != nil {
t.Fatalf("err: %v", err)
}
defer f.Close()
var metadata raft.SnapshotMeta
err = read(f, &metadata, ioutil.Discard)
if err != nil {
t.Fatalf("case %d: should've read the snapshot, but didn't: %v", i, err)
}
}
}
func TestArchive_BadData(t *testing.T) {
cases := []struct {
Name string

BIN
test/snapshot/spaces-meta.tar (Stored with Git LFS) Normal file

Binary file not shown.