Skip to content

Commit

Permalink
protoparse: it is not allowed to reference a synthetic map entry (#522)
Browse files Browse the repository at this point in the history
  • Loading branch information
jhump committed Aug 15, 2022
1 parent bc733da commit 7614117
Show file tree
Hide file tree
Showing 2 changed files with 41 additions and 0 deletions.
19 changes: 19 additions & 0 deletions desc/protoparse/linker.go
Expand Up @@ -3,6 +3,7 @@ package protoparse
import (
"bytes"
"fmt"
"google.golang.org/protobuf/types/descriptorpb"
"sort"
"strings"

Expand Down Expand Up @@ -518,6 +519,24 @@ func (l *linker) resolveFieldTypes(r *parseResult, fd *dpb.FileDescriptorProto,
}
switch dsc := dsc.(type) {
case *dpb.DescriptorProto:
if dsc.GetOptions().GetMapEntry() {
isValid := false
switch node.(type) {
case *ast.MapFieldNode:
// We have an AST for this file and can see this field is from a map declaration
isValid = true
case ast.NoSourceNode:
// We don't have an AST for the file (it came from a provided descriptor). So we
// need to validate that it's not an illegal reference. To be valid, the field
// must be repeated and the entry type must be nested in the same enclosing
// message as the field.
expectFqn := prefix + dsc.GetName()
isValid = expectFqn == fqn && fld.GetLabel() == descriptorpb.FieldDescriptorProto_LABEL_REPEATED
}
if !isValid {
return l.errs.handleErrorWithPos(node.FieldType().Start(), "%s: %s is a synthetic map entry and may not be referenced explicitly", scope, fqn)
}
}
fld.TypeName = proto.String("." + fqn)
// if type was tentatively unset, we now know it's actually a message
if fld.Type == nil {
Expand Down
22 changes: 22 additions & 0 deletions desc/protoparse/linker_test.go
Expand Up @@ -984,6 +984,28 @@ func TestLinkerValidation(t *testing.T) {
},
"", // should succeed
},
{
map[string]string{
"foo.proto": "syntax = \"proto3\";\n" +
"message Foo {\n" +
" map<string,string> bar = 1;\n" +
"}\n" +
"message Baz {\n" +
" Foo.BarEntry e = 1;\n" +
"}\n",
},
"foo.proto:6:3: field Baz.e: Foo.BarEntry is a synthetic map entry and may not be referenced explicitly",
},
{
map[string]string{
"foo.proto": "syntax = \"proto3\";\n" +
"import \"google/protobuf/struct.proto\";\n" +
"message Foo {\n" +
" google.protobuf.Struct.FieldsEntry e = 1;\n" +
"}\n",
},
"foo.proto:4:3: field Foo.e: google.protobuf.Struct.FieldsEntry is a synthetic map entry and may not be referenced explicitly",
},
}
for i, tc := range testCases {
acc := func(filename string) (io.ReadCloser, error) {
Expand Down

0 comments on commit 7614117

Please sign in to comment.