xref: /aosp_15_r20/external/golang-protobuf/internal/impl/validate.go (revision 1c12ee1efe575feb122dbf939ff15148a3b3e8f2)
1*1c12ee1eSDan Willemsen// Copyright 2019 The Go Authors. All rights reserved.
2*1c12ee1eSDan Willemsen// Use of this source code is governed by a BSD-style
3*1c12ee1eSDan Willemsen// license that can be found in the LICENSE file.
4*1c12ee1eSDan Willemsen
5*1c12ee1eSDan Willemsenpackage impl
6*1c12ee1eSDan Willemsen
7*1c12ee1eSDan Willemsenimport (
8*1c12ee1eSDan Willemsen	"fmt"
9*1c12ee1eSDan Willemsen	"math"
10*1c12ee1eSDan Willemsen	"math/bits"
11*1c12ee1eSDan Willemsen	"reflect"
12*1c12ee1eSDan Willemsen	"unicode/utf8"
13*1c12ee1eSDan Willemsen
14*1c12ee1eSDan Willemsen	"google.golang.org/protobuf/encoding/protowire"
15*1c12ee1eSDan Willemsen	"google.golang.org/protobuf/internal/encoding/messageset"
16*1c12ee1eSDan Willemsen	"google.golang.org/protobuf/internal/flags"
17*1c12ee1eSDan Willemsen	"google.golang.org/protobuf/internal/genid"
18*1c12ee1eSDan Willemsen	"google.golang.org/protobuf/internal/strs"
19*1c12ee1eSDan Willemsen	"google.golang.org/protobuf/reflect/protoreflect"
20*1c12ee1eSDan Willemsen	"google.golang.org/protobuf/reflect/protoregistry"
21*1c12ee1eSDan Willemsen	"google.golang.org/protobuf/runtime/protoiface"
22*1c12ee1eSDan Willemsen)
23*1c12ee1eSDan Willemsen
24*1c12ee1eSDan Willemsen// ValidationStatus is the result of validating the wire-format encoding of a message.
25*1c12ee1eSDan Willemsentype ValidationStatus int
26*1c12ee1eSDan Willemsen
27*1c12ee1eSDan Willemsenconst (
28*1c12ee1eSDan Willemsen	// ValidationUnknown indicates that unmarshaling the message might succeed or fail.
29*1c12ee1eSDan Willemsen	// The validator was unable to render a judgement.
30*1c12ee1eSDan Willemsen	//
31*1c12ee1eSDan Willemsen	// The only causes of this status are an aberrant message type appearing somewhere
32*1c12ee1eSDan Willemsen	// in the message or a failure in the extension resolver.
33*1c12ee1eSDan Willemsen	ValidationUnknown ValidationStatus = iota + 1
34*1c12ee1eSDan Willemsen
35*1c12ee1eSDan Willemsen	// ValidationInvalid indicates that unmarshaling the message will fail.
36*1c12ee1eSDan Willemsen	ValidationInvalid
37*1c12ee1eSDan Willemsen
38*1c12ee1eSDan Willemsen	// ValidationValid indicates that unmarshaling the message will succeed.
39*1c12ee1eSDan Willemsen	ValidationValid
40*1c12ee1eSDan Willemsen)
41*1c12ee1eSDan Willemsen
42*1c12ee1eSDan Willemsenfunc (v ValidationStatus) String() string {
43*1c12ee1eSDan Willemsen	switch v {
44*1c12ee1eSDan Willemsen	case ValidationUnknown:
45*1c12ee1eSDan Willemsen		return "ValidationUnknown"
46*1c12ee1eSDan Willemsen	case ValidationInvalid:
47*1c12ee1eSDan Willemsen		return "ValidationInvalid"
48*1c12ee1eSDan Willemsen	case ValidationValid:
49*1c12ee1eSDan Willemsen		return "ValidationValid"
50*1c12ee1eSDan Willemsen	default:
51*1c12ee1eSDan Willemsen		return fmt.Sprintf("ValidationStatus(%d)", int(v))
52*1c12ee1eSDan Willemsen	}
53*1c12ee1eSDan Willemsen}
54*1c12ee1eSDan Willemsen
55*1c12ee1eSDan Willemsen// Validate determines whether the contents of the buffer are a valid wire encoding
56*1c12ee1eSDan Willemsen// of the message type.
57*1c12ee1eSDan Willemsen//
58*1c12ee1eSDan Willemsen// This function is exposed for testing.
59*1c12ee1eSDan Willemsenfunc Validate(mt protoreflect.MessageType, in protoiface.UnmarshalInput) (out protoiface.UnmarshalOutput, _ ValidationStatus) {
60*1c12ee1eSDan Willemsen	mi, ok := mt.(*MessageInfo)
61*1c12ee1eSDan Willemsen	if !ok {
62*1c12ee1eSDan Willemsen		return out, ValidationUnknown
63*1c12ee1eSDan Willemsen	}
64*1c12ee1eSDan Willemsen	if in.Resolver == nil {
65*1c12ee1eSDan Willemsen		in.Resolver = protoregistry.GlobalTypes
66*1c12ee1eSDan Willemsen	}
67*1c12ee1eSDan Willemsen	o, st := mi.validate(in.Buf, 0, unmarshalOptions{
68*1c12ee1eSDan Willemsen		flags:    in.Flags,
69*1c12ee1eSDan Willemsen		resolver: in.Resolver,
70*1c12ee1eSDan Willemsen	})
71*1c12ee1eSDan Willemsen	if o.initialized {
72*1c12ee1eSDan Willemsen		out.Flags |= protoiface.UnmarshalInitialized
73*1c12ee1eSDan Willemsen	}
74*1c12ee1eSDan Willemsen	return out, st
75*1c12ee1eSDan Willemsen}
76*1c12ee1eSDan Willemsen
77*1c12ee1eSDan Willemsentype validationInfo struct {
78*1c12ee1eSDan Willemsen	mi               *MessageInfo
79*1c12ee1eSDan Willemsen	typ              validationType
80*1c12ee1eSDan Willemsen	keyType, valType validationType
81*1c12ee1eSDan Willemsen
82*1c12ee1eSDan Willemsen	// For non-required fields, requiredBit is 0.
83*1c12ee1eSDan Willemsen	//
84*1c12ee1eSDan Willemsen	// For required fields, requiredBit's nth bit is set, where n is a
85*1c12ee1eSDan Willemsen	// unique index in the range [0, MessageInfo.numRequiredFields).
86*1c12ee1eSDan Willemsen	//
87*1c12ee1eSDan Willemsen	// If there are more than 64 required fields, requiredBit is 0.
88*1c12ee1eSDan Willemsen	requiredBit uint64
89*1c12ee1eSDan Willemsen}
90*1c12ee1eSDan Willemsen
91*1c12ee1eSDan Willemsentype validationType uint8
92*1c12ee1eSDan Willemsen
93*1c12ee1eSDan Willemsenconst (
94*1c12ee1eSDan Willemsen	validationTypeOther validationType = iota
95*1c12ee1eSDan Willemsen	validationTypeMessage
96*1c12ee1eSDan Willemsen	validationTypeGroup
97*1c12ee1eSDan Willemsen	validationTypeMap
98*1c12ee1eSDan Willemsen	validationTypeRepeatedVarint
99*1c12ee1eSDan Willemsen	validationTypeRepeatedFixed32
100*1c12ee1eSDan Willemsen	validationTypeRepeatedFixed64
101*1c12ee1eSDan Willemsen	validationTypeVarint
102*1c12ee1eSDan Willemsen	validationTypeFixed32
103*1c12ee1eSDan Willemsen	validationTypeFixed64
104*1c12ee1eSDan Willemsen	validationTypeBytes
105*1c12ee1eSDan Willemsen	validationTypeUTF8String
106*1c12ee1eSDan Willemsen	validationTypeMessageSetItem
107*1c12ee1eSDan Willemsen)
108*1c12ee1eSDan Willemsen
109*1c12ee1eSDan Willemsenfunc newFieldValidationInfo(mi *MessageInfo, si structInfo, fd protoreflect.FieldDescriptor, ft reflect.Type) validationInfo {
110*1c12ee1eSDan Willemsen	var vi validationInfo
111*1c12ee1eSDan Willemsen	switch {
112*1c12ee1eSDan Willemsen	case fd.ContainingOneof() != nil && !fd.ContainingOneof().IsSynthetic():
113*1c12ee1eSDan Willemsen		switch fd.Kind() {
114*1c12ee1eSDan Willemsen		case protoreflect.MessageKind:
115*1c12ee1eSDan Willemsen			vi.typ = validationTypeMessage
116*1c12ee1eSDan Willemsen			if ot, ok := si.oneofWrappersByNumber[fd.Number()]; ok {
117*1c12ee1eSDan Willemsen				vi.mi = getMessageInfo(ot.Field(0).Type)
118*1c12ee1eSDan Willemsen			}
119*1c12ee1eSDan Willemsen		case protoreflect.GroupKind:
120*1c12ee1eSDan Willemsen			vi.typ = validationTypeGroup
121*1c12ee1eSDan Willemsen			if ot, ok := si.oneofWrappersByNumber[fd.Number()]; ok {
122*1c12ee1eSDan Willemsen				vi.mi = getMessageInfo(ot.Field(0).Type)
123*1c12ee1eSDan Willemsen			}
124*1c12ee1eSDan Willemsen		case protoreflect.StringKind:
125*1c12ee1eSDan Willemsen			if strs.EnforceUTF8(fd) {
126*1c12ee1eSDan Willemsen				vi.typ = validationTypeUTF8String
127*1c12ee1eSDan Willemsen			}
128*1c12ee1eSDan Willemsen		}
129*1c12ee1eSDan Willemsen	default:
130*1c12ee1eSDan Willemsen		vi = newValidationInfo(fd, ft)
131*1c12ee1eSDan Willemsen	}
132*1c12ee1eSDan Willemsen	if fd.Cardinality() == protoreflect.Required {
133*1c12ee1eSDan Willemsen		// Avoid overflow. The required field check is done with a 64-bit mask, with
134*1c12ee1eSDan Willemsen		// any message containing more than 64 required fields always reported as
135*1c12ee1eSDan Willemsen		// potentially uninitialized, so it is not important to get a precise count
136*1c12ee1eSDan Willemsen		// of the required fields past 64.
137*1c12ee1eSDan Willemsen		if mi.numRequiredFields < math.MaxUint8 {
138*1c12ee1eSDan Willemsen			mi.numRequiredFields++
139*1c12ee1eSDan Willemsen			vi.requiredBit = 1 << (mi.numRequiredFields - 1)
140*1c12ee1eSDan Willemsen		}
141*1c12ee1eSDan Willemsen	}
142*1c12ee1eSDan Willemsen	return vi
143*1c12ee1eSDan Willemsen}
144*1c12ee1eSDan Willemsen
145*1c12ee1eSDan Willemsenfunc newValidationInfo(fd protoreflect.FieldDescriptor, ft reflect.Type) validationInfo {
146*1c12ee1eSDan Willemsen	var vi validationInfo
147*1c12ee1eSDan Willemsen	switch {
148*1c12ee1eSDan Willemsen	case fd.IsList():
149*1c12ee1eSDan Willemsen		switch fd.Kind() {
150*1c12ee1eSDan Willemsen		case protoreflect.MessageKind:
151*1c12ee1eSDan Willemsen			vi.typ = validationTypeMessage
152*1c12ee1eSDan Willemsen			if ft.Kind() == reflect.Slice {
153*1c12ee1eSDan Willemsen				vi.mi = getMessageInfo(ft.Elem())
154*1c12ee1eSDan Willemsen			}
155*1c12ee1eSDan Willemsen		case protoreflect.GroupKind:
156*1c12ee1eSDan Willemsen			vi.typ = validationTypeGroup
157*1c12ee1eSDan Willemsen			if ft.Kind() == reflect.Slice {
158*1c12ee1eSDan Willemsen				vi.mi = getMessageInfo(ft.Elem())
159*1c12ee1eSDan Willemsen			}
160*1c12ee1eSDan Willemsen		case protoreflect.StringKind:
161*1c12ee1eSDan Willemsen			vi.typ = validationTypeBytes
162*1c12ee1eSDan Willemsen			if strs.EnforceUTF8(fd) {
163*1c12ee1eSDan Willemsen				vi.typ = validationTypeUTF8String
164*1c12ee1eSDan Willemsen			}
165*1c12ee1eSDan Willemsen		default:
166*1c12ee1eSDan Willemsen			switch wireTypes[fd.Kind()] {
167*1c12ee1eSDan Willemsen			case protowire.VarintType:
168*1c12ee1eSDan Willemsen				vi.typ = validationTypeRepeatedVarint
169*1c12ee1eSDan Willemsen			case protowire.Fixed32Type:
170*1c12ee1eSDan Willemsen				vi.typ = validationTypeRepeatedFixed32
171*1c12ee1eSDan Willemsen			case protowire.Fixed64Type:
172*1c12ee1eSDan Willemsen				vi.typ = validationTypeRepeatedFixed64
173*1c12ee1eSDan Willemsen			}
174*1c12ee1eSDan Willemsen		}
175*1c12ee1eSDan Willemsen	case fd.IsMap():
176*1c12ee1eSDan Willemsen		vi.typ = validationTypeMap
177*1c12ee1eSDan Willemsen		switch fd.MapKey().Kind() {
178*1c12ee1eSDan Willemsen		case protoreflect.StringKind:
179*1c12ee1eSDan Willemsen			if strs.EnforceUTF8(fd) {
180*1c12ee1eSDan Willemsen				vi.keyType = validationTypeUTF8String
181*1c12ee1eSDan Willemsen			}
182*1c12ee1eSDan Willemsen		}
183*1c12ee1eSDan Willemsen		switch fd.MapValue().Kind() {
184*1c12ee1eSDan Willemsen		case protoreflect.MessageKind:
185*1c12ee1eSDan Willemsen			vi.valType = validationTypeMessage
186*1c12ee1eSDan Willemsen			if ft.Kind() == reflect.Map {
187*1c12ee1eSDan Willemsen				vi.mi = getMessageInfo(ft.Elem())
188*1c12ee1eSDan Willemsen			}
189*1c12ee1eSDan Willemsen		case protoreflect.StringKind:
190*1c12ee1eSDan Willemsen			if strs.EnforceUTF8(fd) {
191*1c12ee1eSDan Willemsen				vi.valType = validationTypeUTF8String
192*1c12ee1eSDan Willemsen			}
193*1c12ee1eSDan Willemsen		}
194*1c12ee1eSDan Willemsen	default:
195*1c12ee1eSDan Willemsen		switch fd.Kind() {
196*1c12ee1eSDan Willemsen		case protoreflect.MessageKind:
197*1c12ee1eSDan Willemsen			vi.typ = validationTypeMessage
198*1c12ee1eSDan Willemsen			if !fd.IsWeak() {
199*1c12ee1eSDan Willemsen				vi.mi = getMessageInfo(ft)
200*1c12ee1eSDan Willemsen			}
201*1c12ee1eSDan Willemsen		case protoreflect.GroupKind:
202*1c12ee1eSDan Willemsen			vi.typ = validationTypeGroup
203*1c12ee1eSDan Willemsen			vi.mi = getMessageInfo(ft)
204*1c12ee1eSDan Willemsen		case protoreflect.StringKind:
205*1c12ee1eSDan Willemsen			vi.typ = validationTypeBytes
206*1c12ee1eSDan Willemsen			if strs.EnforceUTF8(fd) {
207*1c12ee1eSDan Willemsen				vi.typ = validationTypeUTF8String
208*1c12ee1eSDan Willemsen			}
209*1c12ee1eSDan Willemsen		default:
210*1c12ee1eSDan Willemsen			switch wireTypes[fd.Kind()] {
211*1c12ee1eSDan Willemsen			case protowire.VarintType:
212*1c12ee1eSDan Willemsen				vi.typ = validationTypeVarint
213*1c12ee1eSDan Willemsen			case protowire.Fixed32Type:
214*1c12ee1eSDan Willemsen				vi.typ = validationTypeFixed32
215*1c12ee1eSDan Willemsen			case protowire.Fixed64Type:
216*1c12ee1eSDan Willemsen				vi.typ = validationTypeFixed64
217*1c12ee1eSDan Willemsen			case protowire.BytesType:
218*1c12ee1eSDan Willemsen				vi.typ = validationTypeBytes
219*1c12ee1eSDan Willemsen			}
220*1c12ee1eSDan Willemsen		}
221*1c12ee1eSDan Willemsen	}
222*1c12ee1eSDan Willemsen	return vi
223*1c12ee1eSDan Willemsen}
224*1c12ee1eSDan Willemsen
225*1c12ee1eSDan Willemsenfunc (mi *MessageInfo) validate(b []byte, groupTag protowire.Number, opts unmarshalOptions) (out unmarshalOutput, result ValidationStatus) {
226*1c12ee1eSDan Willemsen	mi.init()
227*1c12ee1eSDan Willemsen	type validationState struct {
228*1c12ee1eSDan Willemsen		typ              validationType
229*1c12ee1eSDan Willemsen		keyType, valType validationType
230*1c12ee1eSDan Willemsen		endGroup         protowire.Number
231*1c12ee1eSDan Willemsen		mi               *MessageInfo
232*1c12ee1eSDan Willemsen		tail             []byte
233*1c12ee1eSDan Willemsen		requiredMask     uint64
234*1c12ee1eSDan Willemsen	}
235*1c12ee1eSDan Willemsen
236*1c12ee1eSDan Willemsen	// Pre-allocate some slots to avoid repeated slice reallocation.
237*1c12ee1eSDan Willemsen	states := make([]validationState, 0, 16)
238*1c12ee1eSDan Willemsen	states = append(states, validationState{
239*1c12ee1eSDan Willemsen		typ: validationTypeMessage,
240*1c12ee1eSDan Willemsen		mi:  mi,
241*1c12ee1eSDan Willemsen	})
242*1c12ee1eSDan Willemsen	if groupTag > 0 {
243*1c12ee1eSDan Willemsen		states[0].typ = validationTypeGroup
244*1c12ee1eSDan Willemsen		states[0].endGroup = groupTag
245*1c12ee1eSDan Willemsen	}
246*1c12ee1eSDan Willemsen	initialized := true
247*1c12ee1eSDan Willemsen	start := len(b)
248*1c12ee1eSDan WillemsenState:
249*1c12ee1eSDan Willemsen	for len(states) > 0 {
250*1c12ee1eSDan Willemsen		st := &states[len(states)-1]
251*1c12ee1eSDan Willemsen		for len(b) > 0 {
252*1c12ee1eSDan Willemsen			// Parse the tag (field number and wire type).
253*1c12ee1eSDan Willemsen			var tag uint64
254*1c12ee1eSDan Willemsen			if b[0] < 0x80 {
255*1c12ee1eSDan Willemsen				tag = uint64(b[0])
256*1c12ee1eSDan Willemsen				b = b[1:]
257*1c12ee1eSDan Willemsen			} else if len(b) >= 2 && b[1] < 128 {
258*1c12ee1eSDan Willemsen				tag = uint64(b[0]&0x7f) + uint64(b[1])<<7
259*1c12ee1eSDan Willemsen				b = b[2:]
260*1c12ee1eSDan Willemsen			} else {
261*1c12ee1eSDan Willemsen				var n int
262*1c12ee1eSDan Willemsen				tag, n = protowire.ConsumeVarint(b)
263*1c12ee1eSDan Willemsen				if n < 0 {
264*1c12ee1eSDan Willemsen					return out, ValidationInvalid
265*1c12ee1eSDan Willemsen				}
266*1c12ee1eSDan Willemsen				b = b[n:]
267*1c12ee1eSDan Willemsen			}
268*1c12ee1eSDan Willemsen			var num protowire.Number
269*1c12ee1eSDan Willemsen			if n := tag >> 3; n < uint64(protowire.MinValidNumber) || n > uint64(protowire.MaxValidNumber) {
270*1c12ee1eSDan Willemsen				return out, ValidationInvalid
271*1c12ee1eSDan Willemsen			} else {
272*1c12ee1eSDan Willemsen				num = protowire.Number(n)
273*1c12ee1eSDan Willemsen			}
274*1c12ee1eSDan Willemsen			wtyp := protowire.Type(tag & 7)
275*1c12ee1eSDan Willemsen
276*1c12ee1eSDan Willemsen			if wtyp == protowire.EndGroupType {
277*1c12ee1eSDan Willemsen				if st.endGroup == num {
278*1c12ee1eSDan Willemsen					goto PopState
279*1c12ee1eSDan Willemsen				}
280*1c12ee1eSDan Willemsen				return out, ValidationInvalid
281*1c12ee1eSDan Willemsen			}
282*1c12ee1eSDan Willemsen			var vi validationInfo
283*1c12ee1eSDan Willemsen			switch {
284*1c12ee1eSDan Willemsen			case st.typ == validationTypeMap:
285*1c12ee1eSDan Willemsen				switch num {
286*1c12ee1eSDan Willemsen				case genid.MapEntry_Key_field_number:
287*1c12ee1eSDan Willemsen					vi.typ = st.keyType
288*1c12ee1eSDan Willemsen				case genid.MapEntry_Value_field_number:
289*1c12ee1eSDan Willemsen					vi.typ = st.valType
290*1c12ee1eSDan Willemsen					vi.mi = st.mi
291*1c12ee1eSDan Willemsen					vi.requiredBit = 1
292*1c12ee1eSDan Willemsen				}
293*1c12ee1eSDan Willemsen			case flags.ProtoLegacy && st.mi.isMessageSet:
294*1c12ee1eSDan Willemsen				switch num {
295*1c12ee1eSDan Willemsen				case messageset.FieldItem:
296*1c12ee1eSDan Willemsen					vi.typ = validationTypeMessageSetItem
297*1c12ee1eSDan Willemsen				}
298*1c12ee1eSDan Willemsen			default:
299*1c12ee1eSDan Willemsen				var f *coderFieldInfo
300*1c12ee1eSDan Willemsen				if int(num) < len(st.mi.denseCoderFields) {
301*1c12ee1eSDan Willemsen					f = st.mi.denseCoderFields[num]
302*1c12ee1eSDan Willemsen				} else {
303*1c12ee1eSDan Willemsen					f = st.mi.coderFields[num]
304*1c12ee1eSDan Willemsen				}
305*1c12ee1eSDan Willemsen				if f != nil {
306*1c12ee1eSDan Willemsen					vi = f.validation
307*1c12ee1eSDan Willemsen					if vi.typ == validationTypeMessage && vi.mi == nil {
308*1c12ee1eSDan Willemsen						// Probable weak field.
309*1c12ee1eSDan Willemsen						//
310*1c12ee1eSDan Willemsen						// TODO: Consider storing the results of this lookup somewhere
311*1c12ee1eSDan Willemsen						// rather than recomputing it on every validation.
312*1c12ee1eSDan Willemsen						fd := st.mi.Desc.Fields().ByNumber(num)
313*1c12ee1eSDan Willemsen						if fd == nil || !fd.IsWeak() {
314*1c12ee1eSDan Willemsen							break
315*1c12ee1eSDan Willemsen						}
316*1c12ee1eSDan Willemsen						messageName := fd.Message().FullName()
317*1c12ee1eSDan Willemsen						messageType, err := protoregistry.GlobalTypes.FindMessageByName(messageName)
318*1c12ee1eSDan Willemsen						switch err {
319*1c12ee1eSDan Willemsen						case nil:
320*1c12ee1eSDan Willemsen							vi.mi, _ = messageType.(*MessageInfo)
321*1c12ee1eSDan Willemsen						case protoregistry.NotFound:
322*1c12ee1eSDan Willemsen							vi.typ = validationTypeBytes
323*1c12ee1eSDan Willemsen						default:
324*1c12ee1eSDan Willemsen							return out, ValidationUnknown
325*1c12ee1eSDan Willemsen						}
326*1c12ee1eSDan Willemsen					}
327*1c12ee1eSDan Willemsen					break
328*1c12ee1eSDan Willemsen				}
329*1c12ee1eSDan Willemsen				// Possible extension field.
330*1c12ee1eSDan Willemsen				//
331*1c12ee1eSDan Willemsen				// TODO: We should return ValidationUnknown when:
332*1c12ee1eSDan Willemsen				//   1. The resolver is not frozen. (More extensions may be added to it.)
333*1c12ee1eSDan Willemsen				//   2. The resolver returns preg.NotFound.
334*1c12ee1eSDan Willemsen				// In this case, a type added to the resolver in the future could cause
335*1c12ee1eSDan Willemsen				// unmarshaling to begin failing. Supporting this requires some way to
336*1c12ee1eSDan Willemsen				// determine if the resolver is frozen.
337*1c12ee1eSDan Willemsen				xt, err := opts.resolver.FindExtensionByNumber(st.mi.Desc.FullName(), num)
338*1c12ee1eSDan Willemsen				if err != nil && err != protoregistry.NotFound {
339*1c12ee1eSDan Willemsen					return out, ValidationUnknown
340*1c12ee1eSDan Willemsen				}
341*1c12ee1eSDan Willemsen				if err == nil {
342*1c12ee1eSDan Willemsen					vi = getExtensionFieldInfo(xt).validation
343*1c12ee1eSDan Willemsen				}
344*1c12ee1eSDan Willemsen			}
345*1c12ee1eSDan Willemsen			if vi.requiredBit != 0 {
346*1c12ee1eSDan Willemsen				// Check that the field has a compatible wire type.
347*1c12ee1eSDan Willemsen				// We only need to consider non-repeated field types,
348*1c12ee1eSDan Willemsen				// since repeated fields (and maps) can never be required.
349*1c12ee1eSDan Willemsen				ok := false
350*1c12ee1eSDan Willemsen				switch vi.typ {
351*1c12ee1eSDan Willemsen				case validationTypeVarint:
352*1c12ee1eSDan Willemsen					ok = wtyp == protowire.VarintType
353*1c12ee1eSDan Willemsen				case validationTypeFixed32:
354*1c12ee1eSDan Willemsen					ok = wtyp == protowire.Fixed32Type
355*1c12ee1eSDan Willemsen				case validationTypeFixed64:
356*1c12ee1eSDan Willemsen					ok = wtyp == protowire.Fixed64Type
357*1c12ee1eSDan Willemsen				case validationTypeBytes, validationTypeUTF8String, validationTypeMessage:
358*1c12ee1eSDan Willemsen					ok = wtyp == protowire.BytesType
359*1c12ee1eSDan Willemsen				case validationTypeGroup:
360*1c12ee1eSDan Willemsen					ok = wtyp == protowire.StartGroupType
361*1c12ee1eSDan Willemsen				}
362*1c12ee1eSDan Willemsen				if ok {
363*1c12ee1eSDan Willemsen					st.requiredMask |= vi.requiredBit
364*1c12ee1eSDan Willemsen				}
365*1c12ee1eSDan Willemsen			}
366*1c12ee1eSDan Willemsen
367*1c12ee1eSDan Willemsen			switch wtyp {
368*1c12ee1eSDan Willemsen			case protowire.VarintType:
369*1c12ee1eSDan Willemsen				if len(b) >= 10 {
370*1c12ee1eSDan Willemsen					switch {
371*1c12ee1eSDan Willemsen					case b[0] < 0x80:
372*1c12ee1eSDan Willemsen						b = b[1:]
373*1c12ee1eSDan Willemsen					case b[1] < 0x80:
374*1c12ee1eSDan Willemsen						b = b[2:]
375*1c12ee1eSDan Willemsen					case b[2] < 0x80:
376*1c12ee1eSDan Willemsen						b = b[3:]
377*1c12ee1eSDan Willemsen					case b[3] < 0x80:
378*1c12ee1eSDan Willemsen						b = b[4:]
379*1c12ee1eSDan Willemsen					case b[4] < 0x80:
380*1c12ee1eSDan Willemsen						b = b[5:]
381*1c12ee1eSDan Willemsen					case b[5] < 0x80:
382*1c12ee1eSDan Willemsen						b = b[6:]
383*1c12ee1eSDan Willemsen					case b[6] < 0x80:
384*1c12ee1eSDan Willemsen						b = b[7:]
385*1c12ee1eSDan Willemsen					case b[7] < 0x80:
386*1c12ee1eSDan Willemsen						b = b[8:]
387*1c12ee1eSDan Willemsen					case b[8] < 0x80:
388*1c12ee1eSDan Willemsen						b = b[9:]
389*1c12ee1eSDan Willemsen					case b[9] < 0x80 && b[9] < 2:
390*1c12ee1eSDan Willemsen						b = b[10:]
391*1c12ee1eSDan Willemsen					default:
392*1c12ee1eSDan Willemsen						return out, ValidationInvalid
393*1c12ee1eSDan Willemsen					}
394*1c12ee1eSDan Willemsen				} else {
395*1c12ee1eSDan Willemsen					switch {
396*1c12ee1eSDan Willemsen					case len(b) > 0 && b[0] < 0x80:
397*1c12ee1eSDan Willemsen						b = b[1:]
398*1c12ee1eSDan Willemsen					case len(b) > 1 && b[1] < 0x80:
399*1c12ee1eSDan Willemsen						b = b[2:]
400*1c12ee1eSDan Willemsen					case len(b) > 2 && b[2] < 0x80:
401*1c12ee1eSDan Willemsen						b = b[3:]
402*1c12ee1eSDan Willemsen					case len(b) > 3 && b[3] < 0x80:
403*1c12ee1eSDan Willemsen						b = b[4:]
404*1c12ee1eSDan Willemsen					case len(b) > 4 && b[4] < 0x80:
405*1c12ee1eSDan Willemsen						b = b[5:]
406*1c12ee1eSDan Willemsen					case len(b) > 5 && b[5] < 0x80:
407*1c12ee1eSDan Willemsen						b = b[6:]
408*1c12ee1eSDan Willemsen					case len(b) > 6 && b[6] < 0x80:
409*1c12ee1eSDan Willemsen						b = b[7:]
410*1c12ee1eSDan Willemsen					case len(b) > 7 && b[7] < 0x80:
411*1c12ee1eSDan Willemsen						b = b[8:]
412*1c12ee1eSDan Willemsen					case len(b) > 8 && b[8] < 0x80:
413*1c12ee1eSDan Willemsen						b = b[9:]
414*1c12ee1eSDan Willemsen					case len(b) > 9 && b[9] < 2:
415*1c12ee1eSDan Willemsen						b = b[10:]
416*1c12ee1eSDan Willemsen					default:
417*1c12ee1eSDan Willemsen						return out, ValidationInvalid
418*1c12ee1eSDan Willemsen					}
419*1c12ee1eSDan Willemsen				}
420*1c12ee1eSDan Willemsen				continue State
421*1c12ee1eSDan Willemsen			case protowire.BytesType:
422*1c12ee1eSDan Willemsen				var size uint64
423*1c12ee1eSDan Willemsen				if len(b) >= 1 && b[0] < 0x80 {
424*1c12ee1eSDan Willemsen					size = uint64(b[0])
425*1c12ee1eSDan Willemsen					b = b[1:]
426*1c12ee1eSDan Willemsen				} else if len(b) >= 2 && b[1] < 128 {
427*1c12ee1eSDan Willemsen					size = uint64(b[0]&0x7f) + uint64(b[1])<<7
428*1c12ee1eSDan Willemsen					b = b[2:]
429*1c12ee1eSDan Willemsen				} else {
430*1c12ee1eSDan Willemsen					var n int
431*1c12ee1eSDan Willemsen					size, n = protowire.ConsumeVarint(b)
432*1c12ee1eSDan Willemsen					if n < 0 {
433*1c12ee1eSDan Willemsen						return out, ValidationInvalid
434*1c12ee1eSDan Willemsen					}
435*1c12ee1eSDan Willemsen					b = b[n:]
436*1c12ee1eSDan Willemsen				}
437*1c12ee1eSDan Willemsen				if size > uint64(len(b)) {
438*1c12ee1eSDan Willemsen					return out, ValidationInvalid
439*1c12ee1eSDan Willemsen				}
440*1c12ee1eSDan Willemsen				v := b[:size]
441*1c12ee1eSDan Willemsen				b = b[size:]
442*1c12ee1eSDan Willemsen				switch vi.typ {
443*1c12ee1eSDan Willemsen				case validationTypeMessage:
444*1c12ee1eSDan Willemsen					if vi.mi == nil {
445*1c12ee1eSDan Willemsen						return out, ValidationUnknown
446*1c12ee1eSDan Willemsen					}
447*1c12ee1eSDan Willemsen					vi.mi.init()
448*1c12ee1eSDan Willemsen					fallthrough
449*1c12ee1eSDan Willemsen				case validationTypeMap:
450*1c12ee1eSDan Willemsen					if vi.mi != nil {
451*1c12ee1eSDan Willemsen						vi.mi.init()
452*1c12ee1eSDan Willemsen					}
453*1c12ee1eSDan Willemsen					states = append(states, validationState{
454*1c12ee1eSDan Willemsen						typ:     vi.typ,
455*1c12ee1eSDan Willemsen						keyType: vi.keyType,
456*1c12ee1eSDan Willemsen						valType: vi.valType,
457*1c12ee1eSDan Willemsen						mi:      vi.mi,
458*1c12ee1eSDan Willemsen						tail:    b,
459*1c12ee1eSDan Willemsen					})
460*1c12ee1eSDan Willemsen					b = v
461*1c12ee1eSDan Willemsen					continue State
462*1c12ee1eSDan Willemsen				case validationTypeRepeatedVarint:
463*1c12ee1eSDan Willemsen					// Packed field.
464*1c12ee1eSDan Willemsen					for len(v) > 0 {
465*1c12ee1eSDan Willemsen						_, n := protowire.ConsumeVarint(v)
466*1c12ee1eSDan Willemsen						if n < 0 {
467*1c12ee1eSDan Willemsen							return out, ValidationInvalid
468*1c12ee1eSDan Willemsen						}
469*1c12ee1eSDan Willemsen						v = v[n:]
470*1c12ee1eSDan Willemsen					}
471*1c12ee1eSDan Willemsen				case validationTypeRepeatedFixed32:
472*1c12ee1eSDan Willemsen					// Packed field.
473*1c12ee1eSDan Willemsen					if len(v)%4 != 0 {
474*1c12ee1eSDan Willemsen						return out, ValidationInvalid
475*1c12ee1eSDan Willemsen					}
476*1c12ee1eSDan Willemsen				case validationTypeRepeatedFixed64:
477*1c12ee1eSDan Willemsen					// Packed field.
478*1c12ee1eSDan Willemsen					if len(v)%8 != 0 {
479*1c12ee1eSDan Willemsen						return out, ValidationInvalid
480*1c12ee1eSDan Willemsen					}
481*1c12ee1eSDan Willemsen				case validationTypeUTF8String:
482*1c12ee1eSDan Willemsen					if !utf8.Valid(v) {
483*1c12ee1eSDan Willemsen						return out, ValidationInvalid
484*1c12ee1eSDan Willemsen					}
485*1c12ee1eSDan Willemsen				}
486*1c12ee1eSDan Willemsen			case protowire.Fixed32Type:
487*1c12ee1eSDan Willemsen				if len(b) < 4 {
488*1c12ee1eSDan Willemsen					return out, ValidationInvalid
489*1c12ee1eSDan Willemsen				}
490*1c12ee1eSDan Willemsen				b = b[4:]
491*1c12ee1eSDan Willemsen			case protowire.Fixed64Type:
492*1c12ee1eSDan Willemsen				if len(b) < 8 {
493*1c12ee1eSDan Willemsen					return out, ValidationInvalid
494*1c12ee1eSDan Willemsen				}
495*1c12ee1eSDan Willemsen				b = b[8:]
496*1c12ee1eSDan Willemsen			case protowire.StartGroupType:
497*1c12ee1eSDan Willemsen				switch {
498*1c12ee1eSDan Willemsen				case vi.typ == validationTypeGroup:
499*1c12ee1eSDan Willemsen					if vi.mi == nil {
500*1c12ee1eSDan Willemsen						return out, ValidationUnknown
501*1c12ee1eSDan Willemsen					}
502*1c12ee1eSDan Willemsen					vi.mi.init()
503*1c12ee1eSDan Willemsen					states = append(states, validationState{
504*1c12ee1eSDan Willemsen						typ:      validationTypeGroup,
505*1c12ee1eSDan Willemsen						mi:       vi.mi,
506*1c12ee1eSDan Willemsen						endGroup: num,
507*1c12ee1eSDan Willemsen					})
508*1c12ee1eSDan Willemsen					continue State
509*1c12ee1eSDan Willemsen				case flags.ProtoLegacy && vi.typ == validationTypeMessageSetItem:
510*1c12ee1eSDan Willemsen					typeid, v, n, err := messageset.ConsumeFieldValue(b, false)
511*1c12ee1eSDan Willemsen					if err != nil {
512*1c12ee1eSDan Willemsen						return out, ValidationInvalid
513*1c12ee1eSDan Willemsen					}
514*1c12ee1eSDan Willemsen					xt, err := opts.resolver.FindExtensionByNumber(st.mi.Desc.FullName(), typeid)
515*1c12ee1eSDan Willemsen					switch {
516*1c12ee1eSDan Willemsen					case err == protoregistry.NotFound:
517*1c12ee1eSDan Willemsen						b = b[n:]
518*1c12ee1eSDan Willemsen					case err != nil:
519*1c12ee1eSDan Willemsen						return out, ValidationUnknown
520*1c12ee1eSDan Willemsen					default:
521*1c12ee1eSDan Willemsen						xvi := getExtensionFieldInfo(xt).validation
522*1c12ee1eSDan Willemsen						if xvi.mi != nil {
523*1c12ee1eSDan Willemsen							xvi.mi.init()
524*1c12ee1eSDan Willemsen						}
525*1c12ee1eSDan Willemsen						states = append(states, validationState{
526*1c12ee1eSDan Willemsen							typ:  xvi.typ,
527*1c12ee1eSDan Willemsen							mi:   xvi.mi,
528*1c12ee1eSDan Willemsen							tail: b[n:],
529*1c12ee1eSDan Willemsen						})
530*1c12ee1eSDan Willemsen						b = v
531*1c12ee1eSDan Willemsen						continue State
532*1c12ee1eSDan Willemsen					}
533*1c12ee1eSDan Willemsen				default:
534*1c12ee1eSDan Willemsen					n := protowire.ConsumeFieldValue(num, wtyp, b)
535*1c12ee1eSDan Willemsen					if n < 0 {
536*1c12ee1eSDan Willemsen						return out, ValidationInvalid
537*1c12ee1eSDan Willemsen					}
538*1c12ee1eSDan Willemsen					b = b[n:]
539*1c12ee1eSDan Willemsen				}
540*1c12ee1eSDan Willemsen			default:
541*1c12ee1eSDan Willemsen				return out, ValidationInvalid
542*1c12ee1eSDan Willemsen			}
543*1c12ee1eSDan Willemsen		}
544*1c12ee1eSDan Willemsen		if st.endGroup != 0 {
545*1c12ee1eSDan Willemsen			return out, ValidationInvalid
546*1c12ee1eSDan Willemsen		}
547*1c12ee1eSDan Willemsen		if len(b) != 0 {
548*1c12ee1eSDan Willemsen			return out, ValidationInvalid
549*1c12ee1eSDan Willemsen		}
550*1c12ee1eSDan Willemsen		b = st.tail
551*1c12ee1eSDan Willemsen	PopState:
552*1c12ee1eSDan Willemsen		numRequiredFields := 0
553*1c12ee1eSDan Willemsen		switch st.typ {
554*1c12ee1eSDan Willemsen		case validationTypeMessage, validationTypeGroup:
555*1c12ee1eSDan Willemsen			numRequiredFields = int(st.mi.numRequiredFields)
556*1c12ee1eSDan Willemsen		case validationTypeMap:
557*1c12ee1eSDan Willemsen			// If this is a map field with a message value that contains
558*1c12ee1eSDan Willemsen			// required fields, require that the value be present.
559*1c12ee1eSDan Willemsen			if st.mi != nil && st.mi.numRequiredFields > 0 {
560*1c12ee1eSDan Willemsen				numRequiredFields = 1
561*1c12ee1eSDan Willemsen			}
562*1c12ee1eSDan Willemsen		}
563*1c12ee1eSDan Willemsen		// If there are more than 64 required fields, this check will
564*1c12ee1eSDan Willemsen		// always fail and we will report that the message is potentially
565*1c12ee1eSDan Willemsen		// uninitialized.
566*1c12ee1eSDan Willemsen		if numRequiredFields > 0 && bits.OnesCount64(st.requiredMask) != numRequiredFields {
567*1c12ee1eSDan Willemsen			initialized = false
568*1c12ee1eSDan Willemsen		}
569*1c12ee1eSDan Willemsen		states = states[:len(states)-1]
570*1c12ee1eSDan Willemsen	}
571*1c12ee1eSDan Willemsen	out.n = start - len(b)
572*1c12ee1eSDan Willemsen	if initialized {
573*1c12ee1eSDan Willemsen		out.initialized = true
574*1c12ee1eSDan Willemsen	}
575*1c12ee1eSDan Willemsen	return out, ValidationValid
576*1c12ee1eSDan Willemsen}
577