reflect/protoreflect: remove nullability from repeated extension fields
Remove repeated extension fields from the set of nullable fields,
so that Has reports false and Range does not visit a a zero-length
repeated extension field.
This corrects a fuzzer-detected case where unmarshaling and remarshaling
a wire-format message could result in a semantic change. For a repeated
extension field in non-packed encoding, unmarshaling a packed
representation of the field would result in a message which Has the
extension. Remarshaling it would discard the the field.
Fixes golang.org/protobuf#975
Change-Id: Ie836559c93d218db5b5201742a3b8ebbaacf54ed
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/204897
Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
Reviewed-by: Joe Tsai <joetsai@google.com>
diff --git a/testing/prototest/prototest.go b/testing/prototest/prototest.go
index 437c216..79c792d 100644
--- a/testing/prototest/prototest.go
+++ b/testing/prototest/prototest.go
@@ -118,12 +118,12 @@
if fd.Syntax() == pref.Proto3 && fd.Message() == nil {
wantHas = false
}
- if fd.Cardinality() == pref.Repeated {
- wantHas = false
- }
if fd.IsExtension() {
wantHas = true
}
+ if fd.Cardinality() == pref.Repeated {
+ wantHas = false
+ }
if fd.ContainingOneof() != nil {
wantHas = true
}
@@ -176,7 +176,7 @@
switch {
case fd.IsList() || fd.IsMap():
m.Set(fd, m.Get(fd))
- if got, want := m.Has(fd), fd.IsExtension() || fd.ContainingOneof() != nil; got != want {
+ if got, want := m.Has(fd), (fd.IsExtension() && fd.Cardinality() != pref.Repeated) || fd.ContainingOneof() != nil; got != want {
t.Errorf("after setting %q to default:\nMessage.Has(%v) = %v, want %v", name, num, got, want)
}
case fd.Message() == nil:
@@ -300,7 +300,7 @@
// Append values.
var want pref.List = &testList{}
for i, n := range []seed{1, 0, minVal, maxVal} {
- if got, want := m.Has(fd), i > 0 || fd.IsExtension(); got != want {
+ if got, want := m.Has(fd), i > 0; got != want {
t.Errorf("after appending %d elements to %q:\nMessage.Has(%v) = %v, want %v", i, name, num, got, want)
}
v := newListElement(fd, list, n, nil)
@@ -327,7 +327,7 @@
n := want.Len() - 1
want.Truncate(n)
list.Truncate(n)
- if got, want := m.Has(fd), want.Len() > 0 || fd.IsExtension(); got != want {
+ if got, want := m.Has(fd), want.Len() > 0; got != want {
t.Errorf("after truncating %q to %d:\nMessage.Has(%v) = %v, want %v", name, n, num, got, want)
}
if got, want := m.Get(fd), pref.ValueOfList(want); !valueEqual(got, want) {