Use the zero value when decoding a map element that is missing its key or value.
Signed-off-by: David Symonds <dsymonds@golang.org>
diff --git a/proto/all_test.go b/proto/all_test.go
index f68f913..4888308 100644
--- a/proto/all_test.go
+++ b/proto/all_test.go
@@ -1958,6 +1958,40 @@
}
}
+func TestDecodeMapFieldMissingKey(t *testing.T) {
+ b := []byte{
+ 0x0A, 0x03, // message, tag 1 (name_mapping), of length 3 bytes
+ // no key
+ 0x12, 0x01, 0x6D, // string value of length 1 byte, value "m"
+ }
+ got := &MessageWithMap{}
+ err := Unmarshal(b, got)
+ if err != nil {
+ t.Fatalf("failed to marshal map with missing key: %v", err)
+ }
+ want := &MessageWithMap{NameMapping: map[int32]string{0: "m"}}
+ if !Equal(got, want) {
+ t.Errorf("Unmarshaled map with no key was not as expected. got: %v, want %v", got, want)
+ }
+}
+
+func TestDecodeMapFieldMissingValue(t *testing.T) {
+ b := []byte{
+ 0x0A, 0x02, // message, tag 1 (name_mapping), of length 2 bytes
+ 0x08, 0x01, // varint key, value 1
+ // no value
+ }
+ got := &MessageWithMap{}
+ err := Unmarshal(b, got)
+ if err != nil {
+ t.Fatalf("failed to marshal map with missing value: %v", err)
+ }
+ want := &MessageWithMap{NameMapping: map[int32]string{1: ""}}
+ if !Equal(got, want) {
+ t.Errorf("Unmarshaled map with no value was not as expected. got: %v, want %v", got, want)
+ }
+}
+
func TestOneof(t *testing.T) {
m := &Communique{}
b, err := Marshal(m)
diff --git a/proto/decode.go b/proto/decode.go
index 5810782..f94b9f4 100644
--- a/proto/decode.go
+++ b/proto/decode.go
@@ -768,10 +768,11 @@
}
}
keyelem, valelem := keyptr.Elem(), valptr.Elem()
- if !keyelem.IsValid() || !valelem.IsValid() {
- // We did not decode the key or the value in the map entry.
- // Either way, it's an invalid map entry.
- return fmt.Errorf("proto: bad map data: missing key/val")
+ if !keyelem.IsValid() {
+ keyelem = reflect.Zero(p.mtype.Key())
+ }
+ if !valelem.IsValid() {
+ valelem = reflect.Zero(p.mtype.Elem())
}
v.SetMapIndex(keyelem, valelem)