Skip to content

Commit 8fa7078

Browse files
author
jchadwick-buf
authored
Remove resolution of legacy protovalidate extension (#243)
It is unlikely this is being used anywhere anymore. Unfortunately, if it is, this will cause validation to silently pass when it should not.
1 parent a177f34 commit 8fa7078

File tree

2 files changed

+19
-90
lines changed

2 files changed

+19
-90
lines changed

resolve/resolve.go

Lines changed: 19 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -16,43 +16,32 @@ package resolve
1616

1717
import (
1818
"buf.build/gen/go/bufbuild/protovalidate/protocolbuffers/go/buf/validate"
19-
"google.golang.org/protobuf/encoding/protowire"
2019
"google.golang.org/protobuf/proto"
21-
"google.golang.org/protobuf/reflect/protodesc"
2220
"google.golang.org/protobuf/reflect/protoreflect"
2321
"google.golang.org/protobuf/reflect/protoregistry"
24-
"google.golang.org/protobuf/types/descriptorpb"
25-
"google.golang.org/protobuf/types/dynamicpb"
26-
)
27-
28-
const (
29-
legacyExtensionIndex protowire.Number = 51071 // protovalidate versions < v0.2.0
3022
)
3123

3224
//nolint:gochecknoglobals // static data, only want single instance
3325
var resolver = newExtensionResolver()
3426

35-
// MessageRules returns the MessageRules option set for the
36-
// MessageDescriptor.
27+
// MessageRules returns the MessageRules option set for the MessageDescriptor.
3728
func MessageRules(desc protoreflect.MessageDescriptor) (*validate.MessageRules, error) {
3829
return resolve[*validate.MessageRules](desc.Options(), validate.E_Message)
3930
}
4031

41-
// OneofRules returns the OneofRules option set for the
42-
// OneofDescriptor.
32+
// OneofRules returns the OneofRules option set for the OneofDescriptor.
4333
func OneofRules(desc protoreflect.OneofDescriptor) (*validate.OneofRules, error) {
4434
return resolve[*validate.OneofRules](desc.Options(), validate.E_Oneof)
4535
}
4636

47-
// FieldRules returns the FieldRules option set for the
48-
// FieldDescriptor.
37+
// FieldRules returns the FieldRules option set for the FieldDescriptor.
4938
func FieldRules(desc protoreflect.FieldDescriptor) (*validate.FieldRules, error) {
5039
return resolve[*validate.FieldRules](desc.Options(), validate.E_Field)
5140
}
5241

53-
// PredefinedRules returns the PredefinedRules option set for
54-
// the FieldDescriptor. Note that this value is only meaningful if it is set on
55-
// a field or extension of a field rule message. This method is provided for
42+
// PredefinedRules returns the PredefinedRules option set for the
43+
// FieldDescriptor. Note that this value is only meaningful if it is set on a
44+
// field or extension of a field rule message. This method is provided for
5645
// convenience.
5746
func PredefinedRules(desc protoreflect.FieldDescriptor) (*validate.PredefinedRules, error) {
5847
return resolve[*validate.PredefinedRules](desc.Options(), validate.E_Predefined)
@@ -96,27 +85,18 @@ func resolve[C proto.Message](
9685
type extensionResolver struct {
9786
// types is a types that just contains the protovalidate extensions.
9887
types *protoregistry.Types
99-
100-
// legacyExtensionMap is a mapping from current protovalidate extensions to
101-
// legacy protovalidate extensions, used for backwards compatibility. This
102-
// map will not be modified, so it is safe to read concurrently.
103-
legacyExtensionMap map[protoreflect.ExtensionType]protoreflect.ExtensionType
10488
}
10589

10690
// newExtensionResolver creates a new extension resolver. This is only called at
10791
// init and will panic if it fails.
10892
func newExtensionResolver() extensionResolver {
10993
resolver := extensionResolver{
110-
types: &protoregistry.Types{},
111-
legacyExtensionMap: make(map[protoreflect.ExtensionType]protoreflect.ExtensionType),
94+
types: &protoregistry.Types{},
11295
}
11396
resolver.register(validate.E_Field)
11497
resolver.register(validate.E_Message)
11598
resolver.register(validate.E_Oneof)
11699
resolver.register(validate.E_Predefined)
117-
resolver.registerLegacy(validate.E_Field)
118-
resolver.registerLegacy(validate.E_Message)
119-
resolver.registerLegacy(validate.E_Oneof)
120100
return resolver
121101
}
122102

@@ -129,53 +109,24 @@ func (resolver extensionResolver) register(extension protoreflect.ExtensionType)
129109
}
130110
}
131111

132-
// registerLegacy creates and registers a legacy extension.
133-
func (resolver extensionResolver) registerLegacy(extension protoreflect.ExtensionType) {
134-
fileDescriptor, err := protodesc.NewFile(&descriptorpb.FileDescriptorProto{
135-
Name: proto.String("buf/validate/validate_legacy.proto"),
136-
Package: proto.String("buf.validate"),
137-
Dependency: []string{
138-
"buf/validate/validate.proto",
139-
"google/protobuf/descriptor.proto",
140-
},
141-
Extension: []*descriptorpb.FieldDescriptorProto{
142-
{
143-
Name: proto.String(string(extension.TypeDescriptor().Name()) + "_legacy"),
144-
Number: proto.Int32(int32(legacyExtensionIndex)),
145-
Label: descriptorpb.FieldDescriptorProto_LABEL_OPTIONAL.Enum(),
146-
Type: descriptorpb.FieldDescriptorProto_TYPE_MESSAGE.Enum(),
147-
TypeName: proto.String(string(extension.TypeDescriptor().Message().FullName())),
148-
Extendee: proto.String(string(extension.TypeDescriptor().ContainingMessage().FullName())),
149-
},
150-
},
151-
}, protoregistry.GlobalFiles)
152-
if err != nil {
153-
//nolint:forbidigo // this needs to be a fatal at init
154-
panic(err)
155-
}
156-
legacyExtension := dynamicpb.NewExtensionType(fileDescriptor.Extensions().Get(0))
157-
resolver.register(legacyExtension)
158-
resolver.legacyExtensionMap[extension] = legacyExtension
159-
}
160-
161112
// resolve handles the majority of extension resolution logic. This will return
162113
// a proto.Message for the given extension if the message has the tag number of
163-
// the provided extension (or an equivalent legacy extension). If there was no
164-
// such tag number present in the known or unknown fields, this method will
165-
// return nil. Note that the returned message may be dynamicpb.Message or
166-
// another type, and thus may need to still be reparsed if needed.
114+
// the provided extension. If there was no such tag number present in the known
115+
// or unknown fields, this method will return nil. Note that the returned
116+
// message may be dynamicpb.Message or another type, and thus may need to still
117+
// be reparsed if needed.
167118
func (resolver extensionResolver) resolve(
168119
options proto.Message,
169120
extensionType protoreflect.ExtensionType,
170121
) (msg proto.Message, err error) {
171-
msg = resolver.getExtensionOrLegacy(options, extensionType)
122+
msg = resolver.getExtension(options, extensionType)
172123
if msg == nil {
173124
if unknown := options.ProtoReflect().GetUnknown(); len(unknown) > 0 {
174125
reparsedOptions := options.ProtoReflect().Type().New().Interface()
175126
if err = (proto.UnmarshalOptions{
176127
Resolver: resolver.types,
177128
}).Unmarshal(unknown, reparsedOptions); err == nil {
178-
msg = resolver.getExtensionOrLegacy(reparsedOptions, extensionType)
129+
msg = resolver.getExtension(reparsedOptions, extensionType)
179130
}
180131
}
181132
}
@@ -185,11 +136,11 @@ func (resolver extensionResolver) resolve(
185136
return msg, nil
186137
}
187138

188-
// getExtensionOrLegacy gets the extension extensionType on message, or if it is
189-
// not found, the corresponding legacy extensionType. Unlike proto.GetExtension,
190-
// this method will not panic if the runtime type of the extension is unexpected
191-
// and returns nil if the extension is not present.
192-
func (resolver extensionResolver) getExtensionOrLegacy(
139+
// getExtension gets the extension extensionType on message, or if it is not
140+
// found, nil. Unlike proto.GetExtension, this method will not panic if the
141+
// runtime type of the extension is unexpected and returns nil if the extension
142+
// is not present.
143+
func (resolver extensionResolver) getExtension(
193144
message proto.Message,
194145
extensionType protoreflect.ExtensionType,
195146
) proto.Message {
@@ -198,9 +149,5 @@ func (resolver extensionResolver) getExtensionOrLegacy(
198149
extension, _ := reflect.Get(extensionType.TypeDescriptor()).Interface().(protoreflect.Message)
199150
return extension.Interface()
200151
}
201-
legacyExtensionType, ok := resolver.legacyExtensionMap[extensionType]
202-
if !ok {
203-
return nil
204-
}
205-
return resolver.getExtensionOrLegacy(message, legacyExtensionType)
152+
return nil
206153
}

resolve/resolve_test.go

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -84,24 +84,6 @@ func TestResolve(t *testing.T) {
8484
return options
8585
},
8686
},
87-
{
88-
name: "Legacy",
89-
builder: func() proto.Message {
90-
var unknownBytes []byte
91-
unknownBytes = protowire.AppendTag(
92-
unknownBytes,
93-
legacyExtensionIndex,
94-
protowire.BytesType,
95-
)
96-
unknownBytes = protowire.AppendBytes(
97-
unknownBytes,
98-
expectedRulesBytes,
99-
)
100-
options := &descriptorpb.FieldOptions{}
101-
options.ProtoReflect().SetUnknown(protoreflect.RawFields(unknownBytes))
102-
return options
103-
},
104-
},
10587
}
10688

10789
for _, tc := range tests {

0 commit comments

Comments
 (0)