Commit 71f05cb7 authored by Luke Champine's avatar Luke Champine

add checksums to each update

parent 524cd6ee
......@@ -128,13 +128,11 @@ func openJournal(filename string, data *contractorPersist) (*journal, error) {
for {
var set updateSet
if err = dec.Decode(&set); err == io.EOF || err == io.ErrUnexpectedEOF {
// unexpected EOF means the last update was corrupted
// unexpected EOF means the last update was corrupted; skip it
break
} else if _, ok := err.(*json.SyntaxError); ok {
// skip malformed update sets
continue
} else if err != nil {
return nil, err
// skip corrupted update sets
continue
}
for _, u := range set {
u.apply(data)
......@@ -152,8 +150,9 @@ type journalUpdate interface {
}
type marshaledUpdate struct {
Type string `json:"t"`
Data rawJSON `json:"d"`
Type string `json:"t"`
Data rawJSON `json:"d"`
Checksum crypto.Hash `json:"c"`
}
// TODO: replace with json.RawMessage after upgrading to Go 1.8
......@@ -172,7 +171,7 @@ func (r *rawJSON) UnmarshalJSON(data []byte) error {
if r == nil {
return errors.New("rawJSON: UnmarshalJSON on nil pointer")
}
*r = append((*r)[0:0], data...)
*r = append((*r)[:0], data...)
return nil
}
......@@ -186,6 +185,7 @@ func (set updateSet) MarshalJSON() ([]byte, error) {
build.Critical("failed to marshal known type:", err)
}
marshaledSet[i].Data = data
marshaledSet[i].Checksum = crypto.HashBytes(data)
switch u.(type) {
case updateUploadRevision:
marshaledSet[i].Type = "uploadRevision"
......@@ -206,6 +206,9 @@ func (set *updateSet) UnmarshalJSON(b []byte) error {
return err
}
for _, u := range marshaledSet {
if crypto.HashBytes(u.Data) != u.Checksum {
return errors.New("bad checksum")
}
var err error
switch u.Type {
case "uploadRevision":
......
......@@ -92,7 +92,7 @@ func TestJournalMalformed(t *testing.T) {
// write a partially-malformed log
f.WriteString(`{"cachedrevisions":{}}
[{"t":"cachedDownloadRevision","d":{"revision":{"parentid":"1000000000000000000000000000000000000000000000000000000000000000"}}}]
[{"t":"cachedDownloadRevision","d":{"revision":{"parentid":"1000000000000000000000000000000000000000000000000000000000000000"}},"c":"24cf20c26569ade37fc8948532bbcb113f8550d00ee01ab530026f44f4d6f1b4"}]
[{"t":"cachedDownloadRevision","d":{"revision":{"parentid":"2000000000000000000000000000000000000000000000000000000000000000"
`)
f.Close()
......@@ -109,13 +109,36 @@ func TestJournalMalformed(t *testing.T) {
if _, ok := data.CachedRevisions["1000000000000000000000000000000000000000000000000000000000000000"]; !ok {
t.Fatal("log was not applied correctly:", data)
}
// write a log with a bad checksum
f, cleanup = tempFile(t, "TestJournalMalformed2")
defer cleanup()
// write a partially-malformed log
f.WriteString(`{"cachedrevisions":{}}
[{"t":"cachedDownloadRevision","d":{"revision":{"parentid":"1000000000000000000000000000000000000000000000000000000000000000"}},"c":"24cf20c26569ade37fc8948532bbcb113f8550d00ee01ab530026f44f4d6f1b4"}]
[{"t":"cachedDownloadRevision","d":{"revision":{"parentid":"2000000000000000000000000000000000000000000000000000000000000000"}},"c":"bad checksum"}]
`)
f.Close()
// load log
j, err = openJournal(f.Name(), &data)
if err != nil {
t.Fatal(err)
}
j.Close()
// the last update set should have been discarded
if _, ok := data.CachedRevisions["1000000000000000000000000000000000000000000000000000000000000000"]; !ok {
t.Fatal("log was not applied correctly:", data)
}
}
func BenchmarkUpdateJournal(b *testing.B) {
f, cleanup := tempFile(b, "BenchmarkUpdateJournal")
j, cleanup := tempJournal(b, "BenchmarkUpdateJournal")
defer cleanup()
j := &journal{f: f}
us := updateSet{
updateCachedUploadRevision{
Revision: types.FileContractRevision{
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment