snapshot: read meta.json correctly. (#5193)
* snapshot: read meta.json correctly. Fixes #4452.
This commit is contained in:
parent
7b1bd33add
commit
08502cfa61
|
@ -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)
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Binary file not shown.
Loading…
Reference in New Issue