From e4c78ee199580d8a1b87daf62e992e985a77ffb2 Mon Sep 17 00:00:00 2001 From: Protobuf Team Bot Date: Thu, 12 Dec 2024 14:38:55 -0800 Subject: [PATCH] Collect extensions with the descriptor pool where the file descriptor was built from, instead of with the generated pool. PiperOrigin-RevId: 705635053 --- src/google/protobuf/compiler/java/file.cc | 71 +++++++++-------------- 1 file changed, 29 insertions(+), 42 deletions(-) diff --git a/src/google/protobuf/compiler/java/file.cc b/src/google/protobuf/compiler/java/file.cc index 34aad8667059..ce56dbf7a1cc 100644 --- a/src/google/protobuf/compiler/java/file.cc +++ b/src/google/protobuf/compiler/java/file.cc @@ -102,44 +102,34 @@ bool CollectExtensions(const Message& message, FieldDescriptorSet* extensions) { return true; } -// Finds all extensions in the given message and its sub-messages. If the -// message contains unknown fields (which could be extensions), then those -// extensions are defined in alternate_pool. -// The message will be converted to a DynamicMessage backed by alternate_pool -// in order to handle this case. -void CollectExtensions(const FileDescriptorProto& file_proto, - const DescriptorPool& alternate_pool, - FieldDescriptorSet* extensions, - const std::string& file_data) { - if (!CollectExtensions(file_proto, extensions)) { - // There are unknown fields in the file_proto, which are probably - // extensions. We need to parse the data into a dynamic message based on the - // builder-pool to find out all extensions. - const Descriptor* file_proto_desc = alternate_pool.FindMessageTypeByName( - file_proto.GetDescriptor()->full_name()); - ABSL_CHECK(file_proto_desc) - << "Find unknown fields in FileDescriptorProto when building " - << file_proto.name() - << ". It's likely that those fields are custom options, however, " - "descriptor.proto is not in the transitive dependencies. " - "This normally should not happen. Please report a bug."; - DynamicMessageFactory factory; - std::unique_ptr dynamic_file_proto( - factory.GetPrototype(file_proto_desc)->New()); - ABSL_CHECK(dynamic_file_proto.get() != nullptr); - ABSL_CHECK(dynamic_file_proto->ParseFromString(file_data)); - - // Collect the extensions again from the dynamic message. There should be no - // more unknown fields this time, i.e. all the custom options should be - // parsed as extensions now. - extensions->clear(); - ABSL_CHECK(CollectExtensions(*dynamic_file_proto, extensions)) - << "Find unknown fields in FileDescriptorProto when building " - << file_proto.name() - << ". It's likely that those fields are custom options, however, " - "those options cannot be recognized in the builder pool. " - "This normally should not happen. Please report a bug."; - } +// Finds all extensions for custom options in the given file descriptor with the +// builder pool which resolves Java features instead of the generated pool. +void CollectExtensions(const FileDescriptor& file, + FieldDescriptorSet* extensions) { + FileDescriptorProto file_proto = StripSourceRetentionOptions(file); + std::string file_data; + file_proto.SerializeToString(&file_data); + const Descriptor* file_proto_desc = file.pool()->FindMessageTypeByName( + file_proto.GetDescriptor()->full_name()); + + // descriptor.proto is not found in the builder pool, meaning there are no + // custom options. + if (file_proto_desc == nullptr) return; + + DynamicMessageFactory factory; + std::unique_ptr dynamic_file_proto( + factory.GetPrototype(file_proto_desc)->New()); + ABSL_CHECK(dynamic_file_proto.get() != nullptr); + ABSL_CHECK(dynamic_file_proto->ParseFromString(file_data)); + + // Collect the extensions again from the dynamic message. + extensions->clear(); + ABSL_CHECK(CollectExtensions(*dynamic_file_proto, extensions)) + << "Found unknown fields in FileDescriptorProto when building " + << file_proto.name() + << ". It's likely that those fields are custom options, however, " + "those options cannot be recognized in the builder pool. " + "This normally should not happen. Please report a bug."; } // Our static initialization methods can become very, very large. @@ -474,11 +464,8 @@ void FileGenerator::GenerateDescriptorInitializationCodeForImmutable( // To find those extensions, we need to parse the data into a dynamic message // of the FileDescriptor based on the builder-pool, then we can use // reflections to find all extension fields - FileDescriptorProto file_proto = StripSourceRetentionOptions(*file_); - std::string file_data; - file_proto.SerializeToString(&file_data); FieldDescriptorSet extensions; - CollectExtensions(file_proto, *file_->pool(), &extensions, file_data); + CollectExtensions(*file_, &extensions); if (options_.strip_nonfunctional_codegen) { // Skip feature extensions, which are a visible (but non-functional)