internal/fuzz: add basic fuzzing target for Marshal/Unmarshal

Change-Id: Ibc4e1d53958abd0973fd568e9dafd5be9a8bdc0d
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/200537
Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
diff --git a/.gitignore b/.gitignore
index fd09e45..6e3f595 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,6 +6,7 @@
 /cmd/protoc-gen-go-grpc/protoc-gen-go-grpc
 /cmd/protoc-gen-go-grpc/testdata/go.sum
 /vendor
+/internal/fuzz/wire/fuzz-fuzz.zip
 
 # This file includes artifacts of the system test that should not be checked in.
 # For files created by specific development environment (e.g. editor),
diff --git a/internal/fuzz/README.md b/internal/fuzz/README.md
new file mode 100644
index 0000000..9ec6586
--- /dev/null
+++ b/internal/fuzz/README.md
@@ -0,0 +1,12 @@
+# Fuzzing
+
+Fuzzing support using [go-fuzz](https://github.com/dvyukov/go-fuzz).
+
+Basic operation:
+
+```sh
+$ go install github.com/dvyukov/go-fuzz/go-fuzz github.com/dvyukov/go-fuzz/go-fuzz-build
+$ cd internal/fuzz/{fuzzer}
+$ GOFUZZ111MODULE=on go-fuzz-build .
+$ go-fuzz
+```
diff --git a/internal/fuzz/wire/fuzz.go b/internal/fuzz/wire/fuzz.go
new file mode 100644
index 0000000..c0da64a
--- /dev/null
+++ b/internal/fuzz/wire/fuzz.go
@@ -0,0 +1,40 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// +build gofuzz
+
+// Package wire includes a fuzzer for the wire marshaler and unmarshaler.
+package wire
+
+import (
+	"google.golang.org/protobuf/proto"
+
+	testpb "google.golang.org/protobuf/internal/testprotos/test"
+)
+
+// Fuzz is a fuzzer for proto.Marshal and proto.Unmarshal.
+func Fuzz(data []byte) int {
+	score := 0
+	for _, newf := range []func() proto.Message{
+		func() proto.Message { return &testpb.TestAllTypes{} },
+	} {
+		m1 := newf()
+		if err := proto.Unmarshal(data, m1); err != nil {
+			continue
+		}
+		score = 1
+		data1, err := proto.Marshal(m1)
+		if err != nil {
+			panic(err)
+		}
+		m2 := newf()
+		if err := proto.Unmarshal(data1, m2); err != nil {
+			panic(err)
+		}
+		if !proto.Equal(m1, m2) {
+			panic("not equal")
+		}
+	}
+	return score
+}