blob: 5a19f23036f44dd97ecb6414363a7522d3c4bf24 [file] [log] [blame]
Damien Neile91877d2019-06-27 10:54:42 -07001// Copyright 2019 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package impl
6
7import (
Damien Neilc600d6c2020-01-21 15:00:33 -08008 "math/bits"
9
Damien Neile91877d2019-06-27 10:54:42 -070010 "google.golang.org/protobuf/internal/encoding/wire"
11 "google.golang.org/protobuf/internal/errors"
Damien Neilce3384c2019-11-06 13:18:28 -080012 "google.golang.org/protobuf/internal/flags"
Damien Neile91877d2019-06-27 10:54:42 -070013 "google.golang.org/protobuf/proto"
Damien Neil466dd772020-02-14 14:49:35 -080014 "google.golang.org/protobuf/reflect/protoreflect"
Damien Neile91877d2019-06-27 10:54:42 -070015 preg "google.golang.org/protobuf/reflect/protoregistry"
Damien Neil466dd772020-02-14 14:49:35 -080016 "google.golang.org/protobuf/runtime/protoiface"
Damien Neile91877d2019-06-27 10:54:42 -070017 piface "google.golang.org/protobuf/runtime/protoiface"
18)
19
Damien Neil466dd772020-02-14 14:49:35 -080020type unmarshalOptions struct {
21 flags protoiface.UnmarshalInputFlags
22 resolver interface {
23 FindExtensionByName(field protoreflect.FullName) (protoreflect.ExtensionType, error)
24 FindExtensionByNumber(message protoreflect.FullName, field protoreflect.FieldNumber) (protoreflect.ExtensionType, error)
25 }
26}
Damien Neile91877d2019-06-27 10:54:42 -070027
28func (o unmarshalOptions) Options() proto.UnmarshalOptions {
29 return proto.UnmarshalOptions{
Joe Tsai705acad2019-09-14 18:22:59 -070030 Merge: true,
Damien Neile91877d2019-06-27 10:54:42 -070031 AllowPartial: true,
32 DiscardUnknown: o.DiscardUnknown(),
Damien Neil466dd772020-02-14 14:49:35 -080033 Resolver: o.resolver,
Damien Neile91877d2019-06-27 10:54:42 -070034 }
35}
36
Damien Neil466dd772020-02-14 14:49:35 -080037func (o unmarshalOptions) DiscardUnknown() bool { return o.flags&piface.UnmarshalDiscardUnknown != 0 }
Damien Neile91877d2019-06-27 10:54:42 -070038
Damien Neil0ae1c972020-01-28 14:53:44 -080039func (o unmarshalOptions) IsDefault() bool {
Damien Neil466dd772020-02-14 14:49:35 -080040 return o.flags == 0 && o.resolver == preg.GlobalTypes
Damien Neil6fb29942020-02-05 16:26:45 -080041}
42
43var lazyUnmarshalOptions = unmarshalOptions{
Damien Neil466dd772020-02-14 14:49:35 -080044 resolver: preg.GlobalTypes,
Damien Neil0ae1c972020-01-28 14:53:44 -080045}
46
Damien Neilf0831e82020-01-21 14:25:12 -080047type unmarshalOutput struct {
Damien Neilc600d6c2020-01-21 15:00:33 -080048 n int // number of bytes consumed
49 initialized bool
Damien Neilf0831e82020-01-21 14:25:12 -080050}
51
Damien Neile91877d2019-06-27 10:54:42 -070052// unmarshal is protoreflect.Methods.Unmarshal.
Damien Neil466dd772020-02-14 14:49:35 -080053func (mi *MessageInfo) unmarshal(in piface.UnmarshalInput) (piface.UnmarshalOutput, error) {
Joe Tsai0f81b382019-07-10 23:14:31 -070054 var p pointer
Damien Neil466dd772020-02-14 14:49:35 -080055 if ms, ok := in.Message.(*messageState); ok {
Joe Tsai0f81b382019-07-10 23:14:31 -070056 p = ms.pointer()
57 } else {
Damien Neil466dd772020-02-14 14:49:35 -080058 p = in.Message.(*messageReflectWrapper).pointer()
Joe Tsai0f81b382019-07-10 23:14:31 -070059 }
Damien Neil466dd772020-02-14 14:49:35 -080060 out, err := mi.unmarshalPointer(in.Buf, p, 0, unmarshalOptions{
61 flags: in.Flags,
62 resolver: in.Resolver,
63 })
64 var flags piface.UnmarshalOutputFlags
65 if out.initialized {
66 flags |= piface.UnmarshalInitialized
67 }
Damien Neilc600d6c2020-01-21 15:00:33 -080068 return piface.UnmarshalOutput{
Damien Neil466dd772020-02-14 14:49:35 -080069 Flags: flags,
Damien Neilc600d6c2020-01-21 15:00:33 -080070 }, err
Damien Neile91877d2019-06-27 10:54:42 -070071}
72
73// errUnknown is returned during unmarshaling to indicate a parse error that
74// should result in a field being placed in the unknown fields section (for example,
75// when the wire type doesn't match) as opposed to the entire unmarshal operation
76// failing (for example, when a field extends past the available input).
77//
78// This is a sentinel error which should never be visible to the user.
79var errUnknown = errors.New("unknown")
80
Damien Neilf0831e82020-01-21 14:25:12 -080081func (mi *MessageInfo) unmarshalPointer(b []byte, p pointer, groupTag wire.Number, opts unmarshalOptions) (out unmarshalOutput, err error) {
Damien Neile91877d2019-06-27 10:54:42 -070082 mi.init()
Damien Neilce3384c2019-11-06 13:18:28 -080083 if flags.ProtoLegacy && mi.isMessageSet {
84 return unmarshalMessageSet(mi, b, p, opts)
85 }
Damien Neilc600d6c2020-01-21 15:00:33 -080086 initialized := true
87 var requiredMask uint64
Damien Neile91877d2019-06-27 10:54:42 -070088 var exts *map[int32]ExtensionField
89 start := len(b)
90 for len(b) > 0 {
91 // Parse the tag (field number and wire type).
Damien Neilce8f7f62020-01-24 16:00:20 -080092 var tag uint64
93 if b[0] < 0x80 {
94 tag = uint64(b[0])
95 b = b[1:]
96 } else if len(b) >= 2 && b[1] < 128 {
97 tag = uint64(b[0]&0x7f) + uint64(b[1])<<7
98 b = b[2:]
99 } else {
100 var n int
101 tag, n = wire.ConsumeVarint(b)
102 if n < 0 {
103 return out, wire.ParseError(n)
104 }
105 b = b[n:]
Damien Neile91877d2019-06-27 10:54:42 -0700106 }
Damien Neila522d5f2020-01-27 21:50:47 -0800107 var num wire.Number
108 if n := tag >> 3; n < uint64(wire.MinValidNumber) || n > uint64(wire.MaxValidNumber) {
Damien Neilf0831e82020-01-21 14:25:12 -0800109 return out, errors.New("invalid field number")
Damien Neila522d5f2020-01-27 21:50:47 -0800110 } else {
111 num = wire.Number(n)
Damien Neilfe15dd42019-12-06 15:36:03 -0800112 }
Damien Neila522d5f2020-01-27 21:50:47 -0800113 wtyp := wire.Type(tag & 7)
Damien Neile91877d2019-06-27 10:54:42 -0700114
Damien Neil2ae60932020-01-14 11:12:21 -0800115 if wtyp == wire.EndGroupType {
116 if num != groupTag {
Damien Neilf0831e82020-01-21 14:25:12 -0800117 return out, errors.New("mismatching end group marker")
Damien Neil2ae60932020-01-14 11:12:21 -0800118 }
Damien Neilc600d6c2020-01-21 15:00:33 -0800119 groupTag = 0
120 break
Damien Neil2ae60932020-01-14 11:12:21 -0800121 }
122
Damien Neile91877d2019-06-27 10:54:42 -0700123 var f *coderFieldInfo
124 if int(num) < len(mi.denseCoderFields) {
125 f = mi.denseCoderFields[num]
126 } else {
127 f = mi.coderFields[num]
128 }
Damien Neilce8f7f62020-01-24 16:00:20 -0800129 var n int
Damien Neile91877d2019-06-27 10:54:42 -0700130 err := errUnknown
131 switch {
132 case f != nil:
133 if f.funcs.unmarshal == nil {
134 break
135 }
Damien Neilf0831e82020-01-21 14:25:12 -0800136 var o unmarshalOutput
Damien Neil316febd2020-02-09 12:26:50 -0800137 o, err = f.funcs.unmarshal(b, p.Apply(f.offset), wtyp, f, opts)
Damien Neilf0831e82020-01-21 14:25:12 -0800138 n = o.n
Damien Neil170b2bf2020-01-24 16:42:42 -0800139 if err != nil {
140 break
Damien Neilc600d6c2020-01-21 15:00:33 -0800141 }
Damien Neil170b2bf2020-01-24 16:42:42 -0800142 requiredMask |= f.validation.requiredBit
Damien Neilc600d6c2020-01-21 15:00:33 -0800143 if f.funcs.isInit != nil && !o.initialized {
144 initialized = false
145 }
Damien Neile91877d2019-06-27 10:54:42 -0700146 default:
147 // Possible extension.
148 if exts == nil && mi.extensionOffset.IsValid() {
149 exts = p.Apply(mi.extensionOffset).Extensions()
150 if *exts == nil {
151 *exts = make(map[int32]ExtensionField)
152 }
153 }
154 if exts == nil {
155 break
156 }
Damien Neilf0831e82020-01-21 14:25:12 -0800157 var o unmarshalOutput
158 o, err = mi.unmarshalExtension(b, num, wtyp, *exts, opts)
Damien Neil1887ff72020-01-29 16:40:05 -0800159 if err != nil {
160 break
161 }
Damien Neilf0831e82020-01-21 14:25:12 -0800162 n = o.n
Damien Neilc600d6c2020-01-21 15:00:33 -0800163 if !o.initialized {
164 initialized = false
165 }
Damien Neile91877d2019-06-27 10:54:42 -0700166 }
167 if err != nil {
168 if err != errUnknown {
Damien Neilf0831e82020-01-21 14:25:12 -0800169 return out, err
Damien Neile91877d2019-06-27 10:54:42 -0700170 }
171 n = wire.ConsumeFieldValue(num, wtyp, b)
172 if n < 0 {
Damien Neilf0831e82020-01-21 14:25:12 -0800173 return out, wire.ParseError(n)
Damien Neile91877d2019-06-27 10:54:42 -0700174 }
Damien Neila60e7092020-01-28 14:53:44 -0800175 if !opts.DiscardUnknown() && mi.unknownOffset.IsValid() {
Damien Neile91877d2019-06-27 10:54:42 -0700176 u := p.Apply(mi.unknownOffset).Bytes()
177 *u = wire.AppendTag(*u, num, wtyp)
178 *u = append(*u, b[:n]...)
179 }
180 }
181 b = b[n:]
182 }
183 if groupTag != 0 {
Damien Neilf0831e82020-01-21 14:25:12 -0800184 return out, errors.New("missing end group marker")
Damien Neile91877d2019-06-27 10:54:42 -0700185 }
Damien Neilc600d6c2020-01-21 15:00:33 -0800186 if mi.numRequiredFields > 0 && bits.OnesCount64(requiredMask) != int(mi.numRequiredFields) {
187 initialized = false
188 }
189 if initialized {
190 out.initialized = true
191 }
192 out.n = start - len(b)
Damien Neilf0831e82020-01-21 14:25:12 -0800193 return out, nil
Damien Neile91877d2019-06-27 10:54:42 -0700194}
195
Damien Neilf0831e82020-01-21 14:25:12 -0800196func (mi *MessageInfo) unmarshalExtension(b []byte, num wire.Number, wtyp wire.Type, exts map[int32]ExtensionField, opts unmarshalOptions) (out unmarshalOutput, err error) {
Damien Neile91877d2019-06-27 10:54:42 -0700197 x := exts[int32(num)]
Damien Neilef19a2a2019-11-01 12:00:37 -0700198 xt := x.Type()
Damien Neile91877d2019-06-27 10:54:42 -0700199 if xt == nil {
200 var err error
Damien Neil466dd772020-02-14 14:49:35 -0800201 xt, err = opts.resolver.FindExtensionByNumber(mi.Desc.FullName(), num)
Damien Neile91877d2019-06-27 10:54:42 -0700202 if err != nil {
203 if err == preg.NotFound {
Damien Neilf0831e82020-01-21 14:25:12 -0800204 return out, errUnknown
Damien Neile91877d2019-06-27 10:54:42 -0700205 }
Damien Neil01b51b42020-01-17 13:40:51 -0800206 return out, errors.New("%v: unable to resolve extension %v: %v", mi.Desc.FullName(), num, err)
Damien Neile91877d2019-06-27 10:54:42 -0700207 }
Damien Neile91877d2019-06-27 10:54:42 -0700208 }
Damien Neil79571e92019-12-09 10:24:36 -0800209 xi := getExtensionFieldInfo(xt)
Damien Neile91877d2019-06-27 10:54:42 -0700210 if xi.funcs.unmarshal == nil {
Damien Neilf0831e82020-01-21 14:25:12 -0800211 return out, errUnknown
Damien Neile91877d2019-06-27 10:54:42 -0700212 }
Damien Neil0ae1c972020-01-28 14:53:44 -0800213 if flags.LazyUnmarshalExtensions {
214 if opts.IsDefault() && x.canLazy(xt) {
Damien Neil40cba142020-02-05 10:12:40 -0800215 out, valid := skipExtension(b, xi, num, wtyp, opts)
216 switch valid {
217 case ValidationValid:
218 if out.initialized {
219 x.appendLazyBytes(xt, xi, num, wtyp, b[:out.n])
220 exts[int32(num)] = x
221 return out, nil
222 }
223 case ValidationInvalid:
224 return out, errors.New("invalid wire format")
225 case ValidationUnknown:
Damien Neil0ae1c972020-01-28 14:53:44 -0800226 }
227 }
228 }
Damien Neil68b81c32019-08-22 11:41:32 -0700229 ival := x.Value()
230 if !ival.IsValid() && xi.unmarshalNeedsValue {
Damien Neile91877d2019-06-27 10:54:42 -0700231 // Create a new message, list, or map value to fill in.
232 // For enums, create a prototype value to let the unmarshal func know the
233 // concrete type.
Damien Neil68b81c32019-08-22 11:41:32 -0700234 ival = xt.New()
Damien Neile91877d2019-06-27 10:54:42 -0700235 }
Damien Neilf0831e82020-01-21 14:25:12 -0800236 v, out, err := xi.funcs.unmarshal(b, ival, num, wtyp, opts)
Damien Neile91877d2019-06-27 10:54:42 -0700237 if err != nil {
Damien Neilf0831e82020-01-21 14:25:12 -0800238 return out, err
Damien Neile91877d2019-06-27 10:54:42 -0700239 }
Damien Neil1887ff72020-01-29 16:40:05 -0800240 if xi.funcs.isInit == nil {
241 out.initialized = true
242 }
Damien Neil68b81c32019-08-22 11:41:32 -0700243 x.Set(xt, v)
Damien Neile91877d2019-06-27 10:54:42 -0700244 exts[int32(num)] = x
Damien Neilf0831e82020-01-21 14:25:12 -0800245 return out, nil
Damien Neile91877d2019-06-27 10:54:42 -0700246}
Damien Neil0ae1c972020-01-28 14:53:44 -0800247
Damien Neil40cba142020-02-05 10:12:40 -0800248func skipExtension(b []byte, xi *extensionFieldInfo, num wire.Number, wtyp wire.Type, opts unmarshalOptions) (out unmarshalOutput, _ ValidationStatus) {
Damien Neil0ae1c972020-01-28 14:53:44 -0800249 if xi.validation.mi == nil {
Damien Neil40cba142020-02-05 10:12:40 -0800250 return out, ValidationUnknown
Damien Neil0ae1c972020-01-28 14:53:44 -0800251 }
252 xi.validation.mi.init()
Damien Neil0ae1c972020-01-28 14:53:44 -0800253 switch xi.validation.typ {
254 case validationTypeMessage:
255 if wtyp != wire.BytesType {
Damien Neil40cba142020-02-05 10:12:40 -0800256 return out, ValidationUnknown
Damien Neil0ae1c972020-01-28 14:53:44 -0800257 }
Damien Neilcadb4ab2020-02-03 16:17:31 -0800258 v, n := wire.ConsumeBytes(b)
Damien Neil0ae1c972020-01-28 14:53:44 -0800259 if n < 0 {
Damien Neil40cba142020-02-05 10:12:40 -0800260 return out, ValidationUnknown
Damien Neil0ae1c972020-01-28 14:53:44 -0800261 }
Damien Neilcadb4ab2020-02-03 16:17:31 -0800262 out, st := xi.validation.mi.validate(v, 0, opts)
263 out.n = n
Damien Neil40cba142020-02-05 10:12:40 -0800264 return out, st
Damien Neil0ae1c972020-01-28 14:53:44 -0800265 case validationTypeGroup:
266 if wtyp != wire.StartGroupType {
Damien Neil40cba142020-02-05 10:12:40 -0800267 return out, ValidationUnknown
Damien Neil0ae1c972020-01-28 14:53:44 -0800268 }
Damien Neil40cba142020-02-05 10:12:40 -0800269 out, st := xi.validation.mi.validate(b, num, opts)
270 return out, st
Damien Neil0ae1c972020-01-28 14:53:44 -0800271 default:
Damien Neil40cba142020-02-05 10:12:40 -0800272 return out, ValidationUnknown
Damien Neil0ae1c972020-01-28 14:53:44 -0800273 }
Damien Neil0ae1c972020-01-28 14:53:44 -0800274}