internal/impl: messageset validation and isinit fixes

Recognize messagesets in the validator. Currently, this just gives
up and reports an unknown validity rather than trying to descend
into the messageset.

Plumb fast-path initialization checks through messageset decoding.

Change-Id: Ice55f28e8555764e4ce2720251830e8cf475c133
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/216245
Reviewed-by: Joe Tsai <joetsai@google.com>
diff --git a/internal/impl/codec_messageset.go b/internal/impl/codec_messageset.go
index 16bc3dc..2c09c79 100644
--- a/internal/impl/codec_messageset.go
+++ b/internal/impl/codec_messageset.go
@@ -101,15 +101,20 @@
 	}
 	ext := *ep
 	unknown := p.Apply(mi.unknownOffset).Bytes()
+	initialized := true
 	err = messageset.Unmarshal(b, true, func(num wire.Number, v []byte) error {
-		_, err := mi.unmarshalExtension(v, num, wire.BytesType, ext, opts)
+		o, err := mi.unmarshalExtension(v, num, wire.BytesType, ext, opts)
 		if err == errUnknown {
 			*unknown = wire.AppendTag(*unknown, num, wire.BytesType)
 			*unknown = append(*unknown, v...)
 			return nil
 		}
+		if !o.initialized {
+			initialized = false
+		}
 		return err
 	})
 	out.n = len(b)
+	out.initialized = initialized
 	return out, err
 }
diff --git a/internal/impl/validate.go b/internal/impl/validate.go
index 1d34063..cb6a820 100644
--- a/internal/impl/validate.go
+++ b/internal/impl/validate.go
@@ -12,6 +12,7 @@
 	"unicode/utf8"
 
 	"google.golang.org/protobuf/internal/encoding/wire"
+	"google.golang.org/protobuf/internal/flags"
 	"google.golang.org/protobuf/internal/strs"
 	pref "google.golang.org/protobuf/reflect/protoreflect"
 	preg "google.golang.org/protobuf/reflect/protoregistry"
@@ -242,6 +243,9 @@
 		st := &states[len(states)-1]
 		if st.mi != nil {
 			st.mi.init()
+			if flags.ProtoLegacy && st.mi.isMessageSet {
+				return ValidationUnknown
+			}
 		}
 	Field:
 		for len(b) > 0 {