diff --git a/go-fuzz-build/main.go b/go-fuzz-build/main.go index fc6897078..12bf30f26 100644 --- a/go-fuzz-build/main.go +++ b/go-fuzz-build/main.go @@ -160,6 +160,16 @@ func main() { zipFile("cover.exe", coverBin) zipFile("sonar.exe", sonarBin) zipFile("metadata", metaData) + + // Add version file. + w, err := zipw.Create("version") + if err != nil { + c.failf("failed to create zip file: %v", err) + } + if _, err := w.Write([]byte(Version)); err != nil { + c.failf("failed to write version to zip file: %v", err) + } + if err := zipw.Close(); err != nil { c.failf("failed to close zip file: %v", err) } diff --git a/go-fuzz/worker.go b/go-fuzz/worker.go index cbbc5c957..c649ea77f 100644 --- a/go-fuzz/worker.go +++ b/go-fuzz/worker.go @@ -20,6 +20,7 @@ import ( . "github.com/dvyukov/go-fuzz/go-fuzz-defs" . "github.com/dvyukov/go-fuzz/internal/go-fuzz-types" + types "github.com/dvyukov/go-fuzz/internal/go-fuzz-types" ) type execType byte @@ -78,16 +79,34 @@ func workerMain() { } var coverBin, sonarBin string var metadata MetaData + var foundVersion bool for _, zipf := range zipr.File { r, err := zipf.Open() if err != nil { log.Fatalf("failed to unzip file from input archive: %v", err) } - if zipf.Name == "metadata" { + switch zipf.Name { + case "metadata": if err := json.NewDecoder(r).Decode(&metadata); err != nil { log.Fatalf("failed to decode metadata: %v", err) } - } else { + case "version": + foundVersion = true + v, err := ioutil.ReadAll(r) + if err != nil { + log.Fatalf("failed to read version: %v", err) + } + if types.Version != string(v) { + log.Fatalf(` +Version skew detected. + +The zip file %v was built with go-fuzz-build version %q. +This go-fuzz uses version %q. +Please ensure that go-fuzz and go-fuzz-build have the +same version, and then re-build the zip file. +`[1:], *flagBin, string(v), types.Version) + } + default: f, err := ioutil.TempFile("", "go-fuzz") if err != nil { log.Fatalf("failed to create temp file: %v", err) @@ -117,6 +136,14 @@ func workerMain() { if coverBin == "" || sonarBin == "" || len(metadata.Blocks) == 0 || len(metadata.Funcs) == 0 { log.Fatalf("bad input archive: missing file") } + if !foundVersion { + log.Fatalf(` +Version skew detected. + +The zip file %v was built with an old version of go-fuzz-build. +Please ensure that go-fuzz and go-fuzz-build have the +same version, and then re-build the zip file.`[1:], *flagBin) + } cleanup := func() { os.Remove(coverBin) diff --git a/internal/go-fuzz-types/types.go b/internal/go-fuzz-types/types.go index 360481ff2..6a228ee68 100644 --- a/internal/go-fuzz-types/types.go +++ b/internal/go-fuzz-types/types.go @@ -1,9 +1,17 @@ // Copyright 2015 go-fuzz project authors. All rights reserved. // Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file. -// Package types provides types shared between go-fuzz-build and go-fuzz. +// Package types provides types and data shared between go-fuzz-build and go-fuzz. package types +// Version is an opaque identifier describing the zip file +// generated by go-fuzz-build and consumed by go-fuzz. +// It should be altered to a never-before-used value +// any time you make a change that could cause a zip file +// generated by go-fuzz-build not to be fully interoperable +// with a different version of go-fuzz. +const Version = "1" + type CoverBlock struct { ID int File string