blob: 6e78faaf3022589f67b732da8f140a7062e47c1d [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"
14 pref "google.golang.org/protobuf/reflect/protoreflect"
15 preg "google.golang.org/protobuf/reflect/protoregistry"
16 piface "google.golang.org/protobuf/runtime/protoiface"
17)
18
Damien Neil524c6062020-01-28 13:32:01 -080019type unmarshalOptions piface.UnmarshalOptions
Damien Neile91877d2019-06-27 10:54:42 -070020
21func (o unmarshalOptions) Options() proto.UnmarshalOptions {
22 return proto.UnmarshalOptions{
Joe Tsai705acad2019-09-14 18:22:59 -070023 Merge: true,
Damien Neile91877d2019-06-27 10:54:42 -070024 AllowPartial: true,
25 DiscardUnknown: o.DiscardUnknown(),
Damien Neil524c6062020-01-28 13:32:01 -080026 Resolver: o.Resolver,
Damien Neile91877d2019-06-27 10:54:42 -070027 }
28}
29
Damien Neil524c6062020-01-28 13:32:01 -080030func (o unmarshalOptions) DiscardUnknown() bool { return o.Flags&piface.UnmarshalDiscardUnknown != 0 }
Damien Neile91877d2019-06-27 10:54:42 -070031
Damien Neil0ae1c972020-01-28 14:53:44 -080032func (o unmarshalOptions) IsDefault() bool {
Damien Neil6fb29942020-02-05 16:26:45 -080033 return o.Flags == 0 && o.Resolver == preg.GlobalTypes
34}
35
36var lazyUnmarshalOptions = unmarshalOptions{
37 Resolver: preg.GlobalTypes,
Damien Neil0ae1c972020-01-28 14:53:44 -080038}
39
Damien Neilf0831e82020-01-21 14:25:12 -080040type unmarshalOutput struct {
Damien Neilc600d6c2020-01-21 15:00:33 -080041 n int // number of bytes consumed
42 initialized bool
Damien Neilf0831e82020-01-21 14:25:12 -080043}
44
Damien Neile91877d2019-06-27 10:54:42 -070045// unmarshal is protoreflect.Methods.Unmarshal.
Damien Neild30e5612020-01-22 10:28:16 -080046func (mi *MessageInfo) unmarshal(m pref.Message, in piface.UnmarshalInput, opts piface.UnmarshalOptions) (piface.UnmarshalOutput, error) {
Joe Tsai0f81b382019-07-10 23:14:31 -070047 var p pointer
48 if ms, ok := m.(*messageState); ok {
49 p = ms.pointer()
50 } else {
51 p = m.(*messageReflectWrapper).pointer()
52 }
Damien Neil524c6062020-01-28 13:32:01 -080053 out, err := mi.unmarshalPointer(in.Buf, p, 0, unmarshalOptions(opts))
Damien Neilc600d6c2020-01-21 15:00:33 -080054 return piface.UnmarshalOutput{
55 Initialized: out.initialized,
56 }, err
Damien Neile91877d2019-06-27 10:54:42 -070057}
58
59// errUnknown is returned during unmarshaling to indicate a parse error that
60// should result in a field being placed in the unknown fields section (for example,
61// when the wire type doesn't match) as opposed to the entire unmarshal operation
62// failing (for example, when a field extends past the available input).
63//
64// This is a sentinel error which should never be visible to the user.
65var errUnknown = errors.New("unknown")
66
Damien Neilf0831e82020-01-21 14:25:12 -080067func (mi *MessageInfo) unmarshalPointer(b []byte, p pointer, groupTag wire.Number, opts unmarshalOptions) (out unmarshalOutput, err error) {
Damien Neile91877d2019-06-27 10:54:42 -070068 mi.init()
Damien Neilce3384c2019-11-06 13:18:28 -080069 if flags.ProtoLegacy && mi.isMessageSet {
70 return unmarshalMessageSet(mi, b, p, opts)
71 }
Damien Neilc600d6c2020-01-21 15:00:33 -080072 initialized := true
73 var requiredMask uint64
Damien Neile91877d2019-06-27 10:54:42 -070074 var exts *map[int32]ExtensionField
75 start := len(b)
76 for len(b) > 0 {
77 // Parse the tag (field number and wire type).
Damien Neilce8f7f62020-01-24 16:00:20 -080078 var tag uint64
79 if b[0] < 0x80 {
80 tag = uint64(b[0])
81 b = b[1:]
82 } else if len(b) >= 2 && b[1] < 128 {
83 tag = uint64(b[0]&0x7f) + uint64(b[1])<<7
84 b = b[2:]
85 } else {
86 var n int
87 tag, n = wire.ConsumeVarint(b)
88 if n < 0 {
89 return out, wire.ParseError(n)
90 }
91 b = b[n:]
Damien Neile91877d2019-06-27 10:54:42 -070092 }
Damien Neila522d5f2020-01-27 21:50:47 -080093 var num wire.Number
94 if n := tag >> 3; n < uint64(wire.MinValidNumber) || n > uint64(wire.MaxValidNumber) {
Damien Neilf0831e82020-01-21 14:25:12 -080095 return out, errors.New("invalid field number")
Damien Neila522d5f2020-01-27 21:50:47 -080096 } else {
97 num = wire.Number(n)
Damien Neilfe15dd42019-12-06 15:36:03 -080098 }
Damien Neila522d5f2020-01-27 21:50:47 -080099 wtyp := wire.Type(tag & 7)
Damien Neile91877d2019-06-27 10:54:42 -0700100
Damien Neil2ae60932020-01-14 11:12:21 -0800101 if wtyp == wire.EndGroupType {
102 if num != groupTag {
Damien Neilf0831e82020-01-21 14:25:12 -0800103 return out, errors.New("mismatching end group marker")
Damien Neil2ae60932020-01-14 11:12:21 -0800104 }
Damien Neilc600d6c2020-01-21 15:00:33 -0800105 groupTag = 0
106 break
Damien Neil2ae60932020-01-14 11:12:21 -0800107 }
108
Damien Neile91877d2019-06-27 10:54:42 -0700109 var f *coderFieldInfo
110 if int(num) < len(mi.denseCoderFields) {
111 f = mi.denseCoderFields[num]
112 } else {
113 f = mi.coderFields[num]
114 }
Damien Neilce8f7f62020-01-24 16:00:20 -0800115 var n int
Damien Neile91877d2019-06-27 10:54:42 -0700116 err := errUnknown
117 switch {
118 case f != nil:
119 if f.funcs.unmarshal == nil {
120 break
121 }
Damien Neilf0831e82020-01-21 14:25:12 -0800122 var o unmarshalOutput
123 o, err = f.funcs.unmarshal(b, p.Apply(f.offset), wtyp, opts)
124 n = o.n
Damien Neil170b2bf2020-01-24 16:42:42 -0800125 if err != nil {
126 break
Damien Neilc600d6c2020-01-21 15:00:33 -0800127 }
Damien Neil170b2bf2020-01-24 16:42:42 -0800128 requiredMask |= f.validation.requiredBit
Damien Neilc600d6c2020-01-21 15:00:33 -0800129 if f.funcs.isInit != nil && !o.initialized {
130 initialized = false
131 }
Damien Neile91877d2019-06-27 10:54:42 -0700132 default:
133 // Possible extension.
134 if exts == nil && mi.extensionOffset.IsValid() {
135 exts = p.Apply(mi.extensionOffset).Extensions()
136 if *exts == nil {
137 *exts = make(map[int32]ExtensionField)
138 }
139 }
140 if exts == nil {
141 break
142 }
Damien Neilf0831e82020-01-21 14:25:12 -0800143 var o unmarshalOutput
144 o, err = mi.unmarshalExtension(b, num, wtyp, *exts, opts)
Damien Neil1887ff72020-01-29 16:40:05 -0800145 if err != nil {
146 break
147 }
Damien Neilf0831e82020-01-21 14:25:12 -0800148 n = o.n
Damien Neilc600d6c2020-01-21 15:00:33 -0800149 if !o.initialized {
150 initialized = false
151 }
Damien Neile91877d2019-06-27 10:54:42 -0700152 }
153 if err != nil {
154 if err != errUnknown {
Damien Neilf0831e82020-01-21 14:25:12 -0800155 return out, err
Damien Neile91877d2019-06-27 10:54:42 -0700156 }
157 n = wire.ConsumeFieldValue(num, wtyp, b)
158 if n < 0 {
Damien Neilf0831e82020-01-21 14:25:12 -0800159 return out, wire.ParseError(n)
Damien Neile91877d2019-06-27 10:54:42 -0700160 }
Damien Neila60e7092020-01-28 14:53:44 -0800161 if !opts.DiscardUnknown() && mi.unknownOffset.IsValid() {
Damien Neile91877d2019-06-27 10:54:42 -0700162 u := p.Apply(mi.unknownOffset).Bytes()
163 *u = wire.AppendTag(*u, num, wtyp)
164 *u = append(*u, b[:n]...)
165 }
166 }
167 b = b[n:]
168 }
169 if groupTag != 0 {
Damien Neilf0831e82020-01-21 14:25:12 -0800170 return out, errors.New("missing end group marker")
Damien Neile91877d2019-06-27 10:54:42 -0700171 }
Damien Neilc600d6c2020-01-21 15:00:33 -0800172 if mi.numRequiredFields > 0 && bits.OnesCount64(requiredMask) != int(mi.numRequiredFields) {
173 initialized = false
174 }
175 if initialized {
176 out.initialized = true
177 }
178 out.n = start - len(b)
Damien Neilf0831e82020-01-21 14:25:12 -0800179 return out, nil
Damien Neile91877d2019-06-27 10:54:42 -0700180}
181
Damien Neilf0831e82020-01-21 14:25:12 -0800182func (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 -0700183 x := exts[int32(num)]
Damien Neilef19a2a2019-11-01 12:00:37 -0700184 xt := x.Type()
Damien Neile91877d2019-06-27 10:54:42 -0700185 if xt == nil {
186 var err error
Damien Neil524c6062020-01-28 13:32:01 -0800187 xt, err = opts.Resolver.FindExtensionByNumber(mi.Desc.FullName(), num)
Damien Neile91877d2019-06-27 10:54:42 -0700188 if err != nil {
189 if err == preg.NotFound {
Damien Neilf0831e82020-01-21 14:25:12 -0800190 return out, errUnknown
Damien Neile91877d2019-06-27 10:54:42 -0700191 }
Damien Neil01b51b42020-01-17 13:40:51 -0800192 return out, errors.New("%v: unable to resolve extension %v: %v", mi.Desc.FullName(), num, err)
Damien Neile91877d2019-06-27 10:54:42 -0700193 }
Damien Neile91877d2019-06-27 10:54:42 -0700194 }
Damien Neil79571e92019-12-09 10:24:36 -0800195 xi := getExtensionFieldInfo(xt)
Damien Neile91877d2019-06-27 10:54:42 -0700196 if xi.funcs.unmarshal == nil {
Damien Neilf0831e82020-01-21 14:25:12 -0800197 return out, errUnknown
Damien Neile91877d2019-06-27 10:54:42 -0700198 }
Damien Neil0ae1c972020-01-28 14:53:44 -0800199 if flags.LazyUnmarshalExtensions {
200 if opts.IsDefault() && x.canLazy(xt) {
Damien Neil40cba142020-02-05 10:12:40 -0800201 out, valid := skipExtension(b, xi, num, wtyp, opts)
202 switch valid {
203 case ValidationValid:
204 if out.initialized {
205 x.appendLazyBytes(xt, xi, num, wtyp, b[:out.n])
206 exts[int32(num)] = x
207 return out, nil
208 }
209 case ValidationInvalid:
210 return out, errors.New("invalid wire format")
211 case ValidationUnknown:
Damien Neil0ae1c972020-01-28 14:53:44 -0800212 }
213 }
214 }
Damien Neil68b81c32019-08-22 11:41:32 -0700215 ival := x.Value()
216 if !ival.IsValid() && xi.unmarshalNeedsValue {
Damien Neile91877d2019-06-27 10:54:42 -0700217 // Create a new message, list, or map value to fill in.
218 // For enums, create a prototype value to let the unmarshal func know the
219 // concrete type.
Damien Neil68b81c32019-08-22 11:41:32 -0700220 ival = xt.New()
Damien Neile91877d2019-06-27 10:54:42 -0700221 }
Damien Neilf0831e82020-01-21 14:25:12 -0800222 v, out, err := xi.funcs.unmarshal(b, ival, num, wtyp, opts)
Damien Neile91877d2019-06-27 10:54:42 -0700223 if err != nil {
Damien Neilf0831e82020-01-21 14:25:12 -0800224 return out, err
Damien Neile91877d2019-06-27 10:54:42 -0700225 }
Damien Neil1887ff72020-01-29 16:40:05 -0800226 if xi.funcs.isInit == nil {
227 out.initialized = true
228 }
Damien Neil68b81c32019-08-22 11:41:32 -0700229 x.Set(xt, v)
Damien Neile91877d2019-06-27 10:54:42 -0700230 exts[int32(num)] = x
Damien Neilf0831e82020-01-21 14:25:12 -0800231 return out, nil
Damien Neile91877d2019-06-27 10:54:42 -0700232}
Damien Neil0ae1c972020-01-28 14:53:44 -0800233
Damien Neil40cba142020-02-05 10:12:40 -0800234func skipExtension(b []byte, xi *extensionFieldInfo, num wire.Number, wtyp wire.Type, opts unmarshalOptions) (out unmarshalOutput, _ ValidationStatus) {
Damien Neil0ae1c972020-01-28 14:53:44 -0800235 if xi.validation.mi == nil {
Damien Neil40cba142020-02-05 10:12:40 -0800236 return out, ValidationUnknown
Damien Neil0ae1c972020-01-28 14:53:44 -0800237 }
238 xi.validation.mi.init()
Damien Neil0ae1c972020-01-28 14:53:44 -0800239 switch xi.validation.typ {
240 case validationTypeMessage:
241 if wtyp != wire.BytesType {
Damien Neil40cba142020-02-05 10:12:40 -0800242 return out, ValidationUnknown
Damien Neil0ae1c972020-01-28 14:53:44 -0800243 }
Damien Neilcadb4ab2020-02-03 16:17:31 -0800244 v, n := wire.ConsumeBytes(b)
Damien Neil0ae1c972020-01-28 14:53:44 -0800245 if n < 0 {
Damien Neil40cba142020-02-05 10:12:40 -0800246 return out, ValidationUnknown
Damien Neil0ae1c972020-01-28 14:53:44 -0800247 }
Damien Neilcadb4ab2020-02-03 16:17:31 -0800248 out, st := xi.validation.mi.validate(v, 0, opts)
249 out.n = n
Damien Neil40cba142020-02-05 10:12:40 -0800250 return out, st
Damien Neil0ae1c972020-01-28 14:53:44 -0800251 case validationTypeGroup:
252 if wtyp != wire.StartGroupType {
Damien Neil40cba142020-02-05 10:12:40 -0800253 return out, ValidationUnknown
Damien Neil0ae1c972020-01-28 14:53:44 -0800254 }
Damien Neil40cba142020-02-05 10:12:40 -0800255 out, st := xi.validation.mi.validate(b, num, opts)
256 return out, st
Damien Neil0ae1c972020-01-28 14:53:44 -0800257 default:
Damien Neil40cba142020-02-05 10:12:40 -0800258 return out, ValidationUnknown
Damien Neil0ae1c972020-01-28 14:53:44 -0800259 }
Damien Neil0ae1c972020-01-28 14:53:44 -0800260}