Skip to content

Commit f770609

Browse files
committed
protoparse should not return dynamic extensions, take 2: must also examine dependencies
1 parent 0880b17 commit f770609

File tree

3 files changed

+53
-8
lines changed

3 files changed

+53
-8
lines changed

desc/protoparse/options_test.go

+1-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ package protoparse
33
import (
44
"fmt"
55
"io"
6-
"io/ioutil"
76
"os"
87
"strings"
98
"testing"
@@ -147,7 +146,7 @@ func TestOptionsInUnlinkedFiles(t *testing.T) {
147146
func accessorFor(name, contents string) FileAccessor {
148147
return func(n string) (io.ReadCloser, error) {
149148
if n == name {
150-
return ioutil.NopCloser(strings.NewReader(contents)), nil
149+
return io.NopCloser(strings.NewReader(contents)), nil
151150
}
152151
return nil, os.ErrNotExist
153152
}

desc/protoparse/parser.go

+21-6
Original file line numberDiff line numberDiff line change
@@ -179,11 +179,10 @@ func (p Parser) ParseFiles(filenames ...string) ([]*desc.FileDescriptor, error)
179179
}
180180

181181
fds := make([]protoreflect.FileDescriptor, len(results))
182+
alreadySeen := make(map[string]struct{}, len(results))
182183
for i, res := range results {
183-
if linkRes, ok := res.(linker.Result); ok {
184-
removeDynamicExtensions(linkRes.FileDescriptorProto())
185-
}
186-
fds[i] = results[i]
184+
removeDynamicExtensions(res, alreadySeen)
185+
fds[i] = res
187186
}
188187
return desc.WrapFiles(fds)
189188
}
@@ -261,7 +260,7 @@ func (p Parser) ParseFilesButDoNotLink(filenames ...string) ([]*descriptorpb.Fil
261260
if err != nil {
262261
return nil, err
263262
}
264-
removeDynamicExtensions(protos[i])
263+
removeDynamicExtensionsFromProto(protos[i])
265264
}
266265
if p.IncludeSourceCodeInfo {
267266
protos[i].SourceCodeInfo = sourceinfo.GenerateSourceInfo(res.AST(), optsIndex)
@@ -597,7 +596,23 @@ func fixupFilenames(protos map[string]parser.Result) map[string]parser.Result {
597596
return revisedProtos
598597
}
599598

600-
func removeDynamicExtensions(fd *descriptorpb.FileDescriptorProto) {
599+
func removeDynamicExtensions(fd protoreflect.FileDescriptor, alreadySeen map[string]struct{}) {
600+
if _, ok := alreadySeen[fd.Path()]; ok {
601+
// already processed
602+
return
603+
}
604+
alreadySeen[fd.Path()] = struct{}{}
605+
res, ok := fd.(linker.Result)
606+
if ok {
607+
removeDynamicExtensionsFromProto(res.FileDescriptorProto())
608+
}
609+
// also remove extensions from dependencies
610+
for i, length := 0, fd.Imports().Len(); i < length; i++ {
611+
removeDynamicExtensions(fd.Imports().Get(i).FileDescriptor, alreadySeen)
612+
}
613+
}
614+
615+
func removeDynamicExtensionsFromProto(fd *descriptorpb.FileDescriptorProto) {
601616
// protocompile returns descriptors with dynamic extension fields for custom options.
602617
// But protoparse only used known custom options and everything else defined in the
603618
// sources would be stored as unrecognized fields. So to bridge the difference in

desc/protoparse/parser_test.go

+31
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,18 @@ import (
77
"io"
88
"io/ioutil"
99
"os"
10+
"path/filepath"
1011
"sort"
12+
"strings"
1113
"testing"
1214

1315
"github.com/bufbuild/protocompile/parser"
1416
"github.com/bufbuild/protocompile/reporter"
17+
"github.com/golang/protobuf/proto"
1518
"google.golang.org/protobuf/types/descriptorpb"
1619

1720
"github.com/jhump/protoreflect/desc"
21+
"github.com/jhump/protoreflect/internal/testprotos"
1822
"github.com/jhump/protoreflect/internal/testutil"
1923
)
2024

@@ -370,6 +374,33 @@ func TestParseFilesWithDependencies(t *testing.T) {
370374
})
371375
}
372376

377+
func TestParseFilesReturnsKnownExtensions(t *testing.T) {
378+
accessor := func(filename string) (io.ReadCloser, error) {
379+
if filename == "desc_test3.proto" {
380+
return io.NopCloser(strings.NewReader(`
381+
syntax = "proto3";
382+
import "desc_test_complex.proto";
383+
message Foo {
384+
foo.bar.Simple field = 1;
385+
}
386+
`)), nil
387+
}
388+
return os.Open(filepath.Join("../../internal/testprotos", filename))
389+
}
390+
p := Parser{
391+
Accessor: accessor,
392+
}
393+
fds, err := p.ParseFiles("desc_test3.proto")
394+
testutil.Ok(t, err)
395+
fd := fds[0].GetDependencies()[0]
396+
md := fd.FindMessage("foo.bar.Test.Nested._NestedNested")
397+
testutil.Require(t, md != nil)
398+
val, err := proto.GetExtension(md.GetOptions(), testprotos.E_Rept)
399+
testutil.Ok(t, err)
400+
_, ok := val.([]*testprotos.Test)
401+
testutil.Require(t, ok)
402+
}
403+
373404
func TestParseCommentsBeforeDot(t *testing.T) {
374405
accessor := FileContentsFromMap(map[string]string{
375406
"test.proto": `

0 commit comments

Comments
 (0)