proto, internal/impl: zero-length proto2 bytes fields should be non-nil

Fix decoding of zero-length bytes fields to produce a non-nil []byte.

Change-Id: Ifb7791a47df81091700f7226523371d1386fb1ad
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/188765
Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
diff --git a/proto/decode_test.go b/proto/decode_test.go
index c32c94c..6088eb5 100644
--- a/proto/decode_test.go
+++ b/proto/decode_test.go
@@ -108,6 +108,21 @@
 	}
 }
 
+func TestDecodeZeroLengthBytes(t *testing.T) {
+	// Verify that proto3 bytes fields don't give the mistaken
+	// impression that they preserve presence.
+	wire := pack.Message{
+		pack.Tag{15, pack.BytesType}, pack.Bytes(nil),
+	}.Marshal()
+	m := &test3pb.TestAllTypes{}
+	if err := proto.Unmarshal(wire, m); err != nil {
+		t.Fatal(err)
+	}
+	if m.OptionalBytes != nil {
+		t.Errorf("unmarshal zero-length proto3 bytes field: got %v, want nil", m.OptionalBytes)
+	}
+}
+
 var testProtos = []testProto{
 	{
 		desc: "basic scalar types",
@@ -184,6 +199,60 @@
 		}.Marshal(),
 	},
 	{
+		desc: "zero values",
+		decodeTo: []proto.Message{&testpb.TestAllTypes{
+			OptionalInt32:    proto.Int32(0),
+			OptionalInt64:    proto.Int64(0),
+			OptionalUint32:   proto.Uint32(0),
+			OptionalUint64:   proto.Uint64(0),
+			OptionalSint32:   proto.Int32(0),
+			OptionalSint64:   proto.Int64(0),
+			OptionalFixed32:  proto.Uint32(0),
+			OptionalFixed64:  proto.Uint64(0),
+			OptionalSfixed32: proto.Int32(0),
+			OptionalSfixed64: proto.Int64(0),
+			OptionalFloat:    proto.Float32(0),
+			OptionalDouble:   proto.Float64(0),
+			OptionalBool:     proto.Bool(false),
+			OptionalString:   proto.String(""),
+			OptionalBytes:    []byte{},
+		}, &test3pb.TestAllTypes{}, build(
+			&testpb.TestAllExtensions{},
+			extend(testpb.E_OptionalInt32Extension, int32(0)),
+			extend(testpb.E_OptionalInt64Extension, int64(0)),
+			extend(testpb.E_OptionalUint32Extension, uint32(0)),
+			extend(testpb.E_OptionalUint64Extension, uint64(0)),
+			extend(testpb.E_OptionalSint32Extension, int32(0)),
+			extend(testpb.E_OptionalSint64Extension, int64(0)),
+			extend(testpb.E_OptionalFixed32Extension, uint32(0)),
+			extend(testpb.E_OptionalFixed64Extension, uint64(0)),
+			extend(testpb.E_OptionalSfixed32Extension, int32(0)),
+			extend(testpb.E_OptionalSfixed64Extension, int64(0)),
+			extend(testpb.E_OptionalFloatExtension, float32(0)),
+			extend(testpb.E_OptionalDoubleExtension, float64(0)),
+			extend(testpb.E_OptionalBoolExtension, bool(false)),
+			extend(testpb.E_OptionalStringExtension, string("")),
+			extend(testpb.E_OptionalBytesExtension, []byte{}),
+		)},
+		wire: pack.Message{
+			pack.Tag{1, pack.VarintType}, pack.Varint(0),
+			pack.Tag{2, pack.VarintType}, pack.Varint(0),
+			pack.Tag{3, pack.VarintType}, pack.Uvarint(0),
+			pack.Tag{4, pack.VarintType}, pack.Uvarint(0),
+			pack.Tag{5, pack.VarintType}, pack.Svarint(0),
+			pack.Tag{6, pack.VarintType}, pack.Svarint(0),
+			pack.Tag{7, pack.Fixed32Type}, pack.Uint32(0),
+			pack.Tag{8, pack.Fixed64Type}, pack.Uint64(0),
+			pack.Tag{9, pack.Fixed32Type}, pack.Int32(0),
+			pack.Tag{10, pack.Fixed64Type}, pack.Int64(0),
+			pack.Tag{11, pack.Fixed32Type}, pack.Float32(0),
+			pack.Tag{12, pack.Fixed64Type}, pack.Float64(0),
+			pack.Tag{13, pack.VarintType}, pack.Bool(false),
+			pack.Tag{14, pack.BytesType}, pack.String(""),
+			pack.Tag{15, pack.BytesType}, pack.Bytes(nil),
+		}.Marshal(),
+	},
+	{
 		desc: "groups",
 		decodeTo: []proto.Message{&testpb.TestAllTypes{
 			Optionalgroup: &testpb.TestAllTypes_OptionalGroup{