From 6a7b578c5bfe3e3efef936d4ff259888e36a0a6e Mon Sep 17 00:00:00 2001 From: Josh Bleecher Snyder Date: Thu, 3 Oct 2019 11:24:36 -0700 Subject: [PATCH] all: add basic version skew detection Version skew between go-fuzz-build and go-fuzz is already a problem, and may get worse as we switch go-fuzz to modules. This change introduces simple, manual skew detection. Hopefully this will become less manual over time, and more sophisticated as needed. This change will force everyone to rebuild their zip files. But it will also tell them so, and explain why. --- go-fuzz-build/main.go | 10 ++++++++++ go-fuzz/worker.go | 31 +++++++++++++++++++++++++++++-- internal/go-fuzz-types/types.go | 10 +++++++++- 3 files changed, 48 insertions(+), 3 deletions(-) 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