16
16
#include <vector>
17
17
18
18
#include "absl/container/btree_set.h"
19
+
#include "absl/container/flat_hash_set.h"
19
20
#include "absl/log/absl_check.h"
20
21
#include "absl/log/absl_log.h"
21
22
#include "absl/status/status.h"
@@ -70,11 +71,14 @@ using FieldDescriptorSet =
70
71
// Recursively searches the given message to collect extensions.
71
72
// Returns true if all the extensions can be recognized. The extensions will be
72
73
// appended in to the extensions parameter.
73
-
// Unknown extensions may be present in the case of option imports and will be
74
-
// ignored.
75
-
void CollectExtensions(const Message& message, FieldDescriptorSet* extensions) {
74
+
// Returns false when there are unknown fields, in which case the data in the
75
+
// extensions output parameter is not reliable and should be discarded.
76
+
bool CollectExtensions(const Message& message, FieldDescriptorSet* extensions) {
76
77
const Reflection* reflection = message.GetReflection();
77
78
79
+
// There are unknown fields that could be extensions, thus this call fails.
80
+
if (reflection->GetUnknownFields(message).field_count() > 0) return false;
81
+
78
82
std::vector<const FieldDescriptor*> fields;
79
83
reflection->ListFields(message, &fields);
80
84
@@ -89,14 +93,25 @@ void CollectExtensions(const Message& message, FieldDescriptorSet* extensions) {
89
93
for (int j = 0; j < size; j++) {
90
94
const Message& sub_message =
91
95
reflection->GetRepeatedMessage(message, fields[i], j);
92
-
CollectExtensions(sub_message, extensions);
96
+
if (!CollectExtensions(sub_message, extensions)) return false;
93
97
}
94
98
} else {
95
99
const Message& sub_message = reflection->GetMessage(message, fields[i]);
96
-
CollectExtensions(sub_message, extensions);
100
+
if (!CollectExtensions(sub_message, extensions)) return false;
97
101
}
98
102
}
99
103
}
104
+
105
+
return true;
106
+
}
107
+
108
+
void CollectPublicDependencies(
109
+
const FileDescriptor* file,
110
+
absl::flat_hash_set<const FileDescriptor*>* dependencies) {
111
+
if (file == nullptr || !dependencies->insert(file).second) return;
112
+
for (int i = 0; file != nullptr && i < file->public_dependency_count(); i++) {
113
+
CollectPublicDependencies(file->public_dependency(i), dependencies);
114
+
}
100
115
}
101
116
102
117
// Finds all extensions for custom options in the given file descriptor with the
@@ -123,6 +138,20 @@ void CollectExtensions(const FileDescriptor& file,
123
138
extensions->clear();
124
139
// Unknown extensions are ok and expected in the case of option imports.
125
140
CollectExtensions(*dynamic_file_proto, extensions);
141
+
142
+
// TODO: Remove descriptor pool pollution from protoc full.
143
+
// Check against dependencies to handle option dependencies polluting pool
144
+
// from using protoc_full with built-in generators instead of plugins.
145
+
// Option dependencies and transitive dependencies are not allowed, except in
146
+
// the case of import public.
147
+
absl::flat_hash_set<const FileDescriptor*> dependencies;
148
+
dependencies.insert(&file);
149
+
for (int i = 0; i < file.dependency_count(); i++) {
150
+
CollectPublicDependencies(file.dependency(i), &dependencies);
151
+
}
152
+
absl::erase_if(*extensions, [&](const FieldDescriptor* fieldDescriptor) {
153
+
return !dependencies.contains(fieldDescriptor->file());
154
+
});
126
155
}
127
156
128
157
// Our static initialization methods can become very, very large.
RetroSearch is an open source project built by @garambo | Open a GitHub Issue
Search and Browse the WWW like it's 1997 | Search results from DuckDuckGo
HTML:
3.2
| Encoding:
UTF-8
| Version:
0.7.4