1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc.  All rights reserved.
3 // https://developers.google.com/protocol-buffers/
4 //
5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are
7 // met:
8 //
9 //     * Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer.
11 //     * Redistributions in binary form must reproduce the above
12 // copyright notice, this list of conditions and the following disclaimer
13 // in the documentation and/or other materials provided with the
14 // distribution.
15 //     * Neither the name of Google Inc. nor the names of its
16 // contributors may be used to endorse or promote products derived from
17 // this software without specific prior written permission.
18 //
19 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30 
31 // Author: kenton@google.com (Kenton Varda)
32 //  Based on original Protocol Buffers design by
33 //  Sanjay Ghemawat, Jeff Dean, and others.
34 
35 #include <google/protobuf/descriptor.h>
36 
37 #include <algorithm>
38 #include <functional>
39 #include <limits>
40 #include <map>
41 #include <memory>
42 #include <set>
43 #include <string>
44 #include <unordered_map>
45 #include <unordered_set>
46 #include <vector>
47 
48 #include <google/protobuf/stubs/common.h>
49 #include <google/protobuf/stubs/logging.h>
50 #include <google/protobuf/stubs/stringprintf.h>
51 #include <google/protobuf/stubs/strutil.h>
52 #include <google/protobuf/any.h>
53 #include <google/protobuf/descriptor.pb.h>
54 #include <google/protobuf/io/coded_stream.h>
55 #include <google/protobuf/io/tokenizer.h>
56 #include <google/protobuf/io/zero_copy_stream_impl.h>
57 #include <google/protobuf/descriptor_database.h>
58 #include <google/protobuf/dynamic_message.h>
59 #include <google/protobuf/generated_message_util.h>
60 #include <google/protobuf/text_format.h>
61 #include <google/protobuf/unknown_field_set.h>
62 #include <google/protobuf/wire_format.h>
63 #include <google/protobuf/stubs/casts.h>
64 #include <google/protobuf/stubs/substitute.h>
65 #include <google/protobuf/io/strtod.h>
66 #include <google/protobuf/stubs/map_util.h>
67 #include <google/protobuf/stubs/stl_util.h>
68 #include <google/protobuf/stubs/hash.h>
69 
70 #undef PACKAGE  // autoheader #defines this.  :(
71 
72 
73 #include <google/protobuf/port_def.inc>
74 
75 namespace google {
76 namespace protobuf {
77 
78 struct Symbol {
79   enum Type {
80     NULL_SYMBOL,
81     MESSAGE,
82     FIELD,
83     ONEOF,
84     ENUM,
85     ENUM_VALUE,
86     SERVICE,
87     METHOD,
88     PACKAGE
89   };
90   Type type;
91   union {
92     const Descriptor* descriptor;
93     const FieldDescriptor* field_descriptor;
94     const OneofDescriptor* oneof_descriptor;
95     const EnumDescriptor* enum_descriptor;
96     const EnumValueDescriptor* enum_value_descriptor;
97     const ServiceDescriptor* service_descriptor;
98     const MethodDescriptor* method_descriptor;
99     const FileDescriptor* package_file_descriptor;
100   };
101 
Symbolgoogle::protobuf::Symbol102   inline Symbol() : type(NULL_SYMBOL) { descriptor = nullptr; }
IsNullgoogle::protobuf::Symbol103   inline bool IsNull() const { return type == NULL_SYMBOL; }
IsTypegoogle::protobuf::Symbol104   inline bool IsType() const { return type == MESSAGE || type == ENUM; }
IsAggregategoogle::protobuf::Symbol105   inline bool IsAggregate() const {
106     return type == MESSAGE || type == PACKAGE || type == ENUM ||
107            type == SERVICE;
108   }
109 
110 #define CONSTRUCTOR(TYPE, TYPE_CONSTANT, FIELD) \
111   inline explicit Symbol(const TYPE* value) {   \
112     type = TYPE_CONSTANT;                       \
113     this->FIELD = value;                        \
114   }
115 
CONSTRUCTORgoogle::protobuf::Symbol116   CONSTRUCTOR(Descriptor, MESSAGE, descriptor)
117   CONSTRUCTOR(FieldDescriptor, FIELD, field_descriptor)
118   CONSTRUCTOR(OneofDescriptor, ONEOF, oneof_descriptor)
119   CONSTRUCTOR(EnumDescriptor, ENUM, enum_descriptor)
120   CONSTRUCTOR(EnumValueDescriptor, ENUM_VALUE, enum_value_descriptor)
121   CONSTRUCTOR(ServiceDescriptor, SERVICE, service_descriptor)
122   CONSTRUCTOR(MethodDescriptor, METHOD, method_descriptor)
123   CONSTRUCTOR(FileDescriptor, PACKAGE, package_file_descriptor)
124 #undef CONSTRUCTOR
125 
126   const FileDescriptor* GetFile() const {
127     switch (type) {
128       case NULL_SYMBOL:
129         return nullptr;
130       case MESSAGE:
131         return descriptor->file();
132       case FIELD:
133         return field_descriptor->file();
134       case ONEOF:
135         return oneof_descriptor->containing_type()->file();
136       case ENUM:
137         return enum_descriptor->file();
138       case ENUM_VALUE:
139         return enum_value_descriptor->type()->file();
140       case SERVICE:
141         return service_descriptor->file();
142       case METHOD:
143         return method_descriptor->service()->file();
144       case PACKAGE:
145         return package_file_descriptor;
146     }
147     return nullptr;
148   }
149 };
150 
151 const FieldDescriptor::CppType
152     FieldDescriptor::kTypeToCppTypeMap[MAX_TYPE + 1] = {
153         static_cast<CppType>(0),  // 0 is reserved for errors
154 
155         CPPTYPE_DOUBLE,   // TYPE_DOUBLE
156         CPPTYPE_FLOAT,    // TYPE_FLOAT
157         CPPTYPE_INT64,    // TYPE_INT64
158         CPPTYPE_UINT64,   // TYPE_UINT64
159         CPPTYPE_INT32,    // TYPE_INT32
160         CPPTYPE_UINT64,   // TYPE_FIXED64
161         CPPTYPE_UINT32,   // TYPE_FIXED32
162         CPPTYPE_BOOL,     // TYPE_BOOL
163         CPPTYPE_STRING,   // TYPE_STRING
164         CPPTYPE_MESSAGE,  // TYPE_GROUP
165         CPPTYPE_MESSAGE,  // TYPE_MESSAGE
166         CPPTYPE_STRING,   // TYPE_BYTES
167         CPPTYPE_UINT32,   // TYPE_UINT32
168         CPPTYPE_ENUM,     // TYPE_ENUM
169         CPPTYPE_INT32,    // TYPE_SFIXED32
170         CPPTYPE_INT64,    // TYPE_SFIXED64
171         CPPTYPE_INT32,    // TYPE_SINT32
172         CPPTYPE_INT64,    // TYPE_SINT64
173 };
174 
175 const char* const FieldDescriptor::kTypeToName[MAX_TYPE + 1] = {
176     "ERROR",  // 0 is reserved for errors
177 
178     "double",    // TYPE_DOUBLE
179     "float",     // TYPE_FLOAT
180     "int64",     // TYPE_INT64
181     "uint64",    // TYPE_UINT64
182     "int32",     // TYPE_INT32
183     "fixed64",   // TYPE_FIXED64
184     "fixed32",   // TYPE_FIXED32
185     "bool",      // TYPE_BOOL
186     "string",    // TYPE_STRING
187     "group",     // TYPE_GROUP
188     "message",   // TYPE_MESSAGE
189     "bytes",     // TYPE_BYTES
190     "uint32",    // TYPE_UINT32
191     "enum",      // TYPE_ENUM
192     "sfixed32",  // TYPE_SFIXED32
193     "sfixed64",  // TYPE_SFIXED64
194     "sint32",    // TYPE_SINT32
195     "sint64",    // TYPE_SINT64
196 };
197 
198 const char* const FieldDescriptor::kCppTypeToName[MAX_CPPTYPE + 1] = {
199     "ERROR",  // 0 is reserved for errors
200 
201     "int32",    // CPPTYPE_INT32
202     "int64",    // CPPTYPE_INT64
203     "uint32",   // CPPTYPE_UINT32
204     "uint64",   // CPPTYPE_UINT64
205     "double",   // CPPTYPE_DOUBLE
206     "float",    // CPPTYPE_FLOAT
207     "bool",     // CPPTYPE_BOOL
208     "enum",     // CPPTYPE_ENUM
209     "string",   // CPPTYPE_STRING
210     "message",  // CPPTYPE_MESSAGE
211 };
212 
213 const char* const FieldDescriptor::kLabelToName[MAX_LABEL + 1] = {
214     "ERROR",  // 0 is reserved for errors
215 
216     "optional",  // LABEL_OPTIONAL
217     "required",  // LABEL_REQUIRED
218     "repeated",  // LABEL_REPEATED
219 };
220 
SyntaxName(FileDescriptor::Syntax syntax)221 const char* FileDescriptor::SyntaxName(FileDescriptor::Syntax syntax) {
222   switch (syntax) {
223     case SYNTAX_PROTO2:
224       return "proto2";
225     case SYNTAX_PROTO3:
226       return "proto3";
227     case SYNTAX_UNKNOWN:
228       return "unknown";
229   }
230   GOOGLE_LOG(FATAL) << "can't reach here.";
231   return nullptr;
232 }
233 
234 static const char* const kNonLinkedWeakMessageReplacementName = "google.protobuf.Empty";
235 
236 #if !defined(_MSC_VER) || _MSC_VER >= 1900
237 const int FieldDescriptor::kMaxNumber;
238 const int FieldDescriptor::kFirstReservedNumber;
239 const int FieldDescriptor::kLastReservedNumber;
240 #endif
241 
242 namespace {
243 
244 // Note:  I distrust ctype.h due to locales.
ToUpper(char ch)245 char ToUpper(char ch) {
246   return (ch >= 'a' && ch <= 'z') ? (ch - 'a' + 'A') : ch;
247 }
248 
ToLower(char ch)249 char ToLower(char ch) {
250   return (ch >= 'A' && ch <= 'Z') ? (ch - 'A' + 'a') : ch;
251 }
252 
ToCamelCase(const std::string & input,bool lower_first)253 std::string ToCamelCase(const std::string& input, bool lower_first) {
254   bool capitalize_next = !lower_first;
255   std::string result;
256   result.reserve(input.size());
257 
258   for (char character : input) {
259     if (character == '_') {
260       capitalize_next = true;
261     } else if (capitalize_next) {
262       result.push_back(ToUpper(character));
263       capitalize_next = false;
264     } else {
265       result.push_back(character);
266     }
267   }
268 
269   // Lower-case the first letter.
270   if (lower_first && !result.empty()) {
271     result[0] = ToLower(result[0]);
272   }
273 
274   return result;
275 }
276 
ToJsonName(const std::string & input)277 std::string ToJsonName(const std::string& input) {
278   bool capitalize_next = false;
279   std::string result;
280   result.reserve(input.size());
281 
282   for (char character : input) {
283     if (character == '_') {
284       capitalize_next = true;
285     } else if (capitalize_next) {
286       result.push_back(ToUpper(character));
287       capitalize_next = false;
288     } else {
289       result.push_back(character);
290     }
291   }
292 
293   return result;
294 }
295 
EnumValueToPascalCase(const std::string & input)296 std::string EnumValueToPascalCase(const std::string& input) {
297   bool next_upper = true;
298   std::string result;
299   result.reserve(input.size());
300 
301   for (char character : input) {
302     if (character == '_') {
303       next_upper = true;
304     } else {
305       if (next_upper) {
306         result.push_back(ToUpper(character));
307       } else {
308         result.push_back(ToLower(character));
309       }
310       next_upper = false;
311     }
312   }
313 
314   return result;
315 }
316 
317 // Class to remove an enum prefix from enum values.
318 class PrefixRemover {
319  public:
PrefixRemover(StringPiece prefix)320   PrefixRemover(StringPiece prefix) {
321     // Strip underscores and lower-case the prefix.
322     for (char character : prefix) {
323       if (character != '_') {
324         prefix_ += ascii_tolower(character);
325       }
326     }
327   }
328 
329   // Tries to remove the enum prefix from this enum value.
330   // If this is not possible, returns the input verbatim.
MaybeRemove(StringPiece str)331   std::string MaybeRemove(StringPiece str) {
332     // We can't just lowercase and strip str and look for a prefix.
333     // We need to properly recognize the difference between:
334     //
335     //   enum Foo {
336     //     FOO_BAR_BAZ = 0;
337     //     FOO_BARBAZ = 1;
338     //   }
339     //
340     // This is acceptable (though perhaps not advisable) because even when
341     // we PascalCase, these two will still be distinct (BarBaz vs. Barbaz).
342     size_t i, j;
343 
344     // Skip past prefix_ in str if we can.
345     for (i = 0, j = 0; i < str.size() && j < prefix_.size(); i++) {
346       if (str[i] == '_') {
347         continue;
348       }
349 
350       if (ascii_tolower(str[i]) != prefix_[j++]) {
351         return std::string(str);
352       }
353     }
354 
355     // If we didn't make it through the prefix, we've failed to strip the
356     // prefix.
357     if (j < prefix_.size()) {
358       return std::string(str);
359     }
360 
361     // Skip underscores between prefix and further characters.
362     while (i < str.size() && str[i] == '_') {
363       i++;
364     }
365 
366     // Enum label can't be the empty string.
367     if (i == str.size()) {
368       return std::string(str);
369     }
370 
371     // We successfully stripped the prefix.
372     str.remove_prefix(i);
373     return std::string(str);
374   }
375 
376  private:
377   std::string prefix_;
378 };
379 
380 // A DescriptorPool contains a bunch of hash-maps to implement the
381 // various Find*By*() methods.  Since hashtable lookups are O(1), it's
382 // most efficient to construct a fixed set of large hash-maps used by
383 // all objects in the pool rather than construct one or more small
384 // hash-maps for each object.
385 //
386 // The keys to these hash-maps are (parent, name) or (parent, number) pairs.
387 
388 typedef std::pair<const void*, StringPiece> PointerStringPair;
389 
390 typedef std::pair<const Descriptor*, int> DescriptorIntPair;
391 typedef std::pair<const EnumDescriptor*, int> EnumIntPair;
392 
393 #define HASH_MAP std::unordered_map
394 #define HASH_SET std::unordered_set
395 #define HASH_FXN hash
396 
397 template <typename PairType>
398 struct PointerIntegerPairHash {
operator ()google::protobuf::__anon4efa60f60211::PointerIntegerPairHash399   size_t operator()(const PairType& p) const {
400     static const size_t prime1 = 16777499;
401     static const size_t prime2 = 16777619;
402     return reinterpret_cast<size_t>(p.first) * prime1 ^
403            static_cast<size_t>(p.second) * prime2;
404   }
405 
406 #ifdef _MSC_VER
407   // Used only by MSVC and platforms where hash_map is not available.
408   static const size_t bucket_size = 4;
409   static const size_t min_buckets = 8;
410 #endif
operator ()google::protobuf::__anon4efa60f60211::PointerIntegerPairHash411   inline bool operator()(const PairType& a, const PairType& b) const {
412     return a < b;
413   }
414 };
415 
416 struct PointerStringPairHash {
operator ()google::protobuf::__anon4efa60f60211::PointerStringPairHash417   size_t operator()(const PointerStringPair& p) const {
418     static const size_t prime = 16777619;
419     hash<StringPiece> string_hash;
420     return reinterpret_cast<size_t>(p.first) * prime ^
421            static_cast<size_t>(string_hash(p.second));
422   }
423 
424 #ifdef _MSC_VER
425   // Used only by MSVC and platforms where hash_map is not available.
426   static const size_t bucket_size = 4;
427   static const size_t min_buckets = 8;
428 #endif
operator ()google::protobuf::__anon4efa60f60211::PointerStringPairHash429   inline bool operator()(const PointerStringPair& a,
430                          const PointerStringPair& b) const {
431     return a < b;
432   }
433 };
434 
435 
436 const Symbol kNullSymbol;
437 
438 typedef HASH_MAP<StringPiece, Symbol, HASH_FXN<StringPiece>>
439     SymbolsByNameMap;
440 
441 typedef HASH_MAP<PointerStringPair, Symbol, PointerStringPairHash>
442     SymbolsByParentMap;
443 
444 typedef HASH_MAP<StringPiece, const FileDescriptor*,
445                  HASH_FXN<StringPiece>>
446     FilesByNameMap;
447 
448 typedef HASH_MAP<PointerStringPair, const FieldDescriptor*,
449                  PointerStringPairHash>
450     FieldsByNameMap;
451 
452 typedef HASH_MAP<DescriptorIntPair, const FieldDescriptor*,
453                  PointerIntegerPairHash<DescriptorIntPair>,
454                  std::equal_to<DescriptorIntPair>>
455     FieldsByNumberMap;
456 
457 typedef HASH_MAP<EnumIntPair, const EnumValueDescriptor*,
458                  PointerIntegerPairHash<EnumIntPair>,
459                  std::equal_to<EnumIntPair>>
460     EnumValuesByNumberMap;
461 // This is a map rather than a hash-map, since we use it to iterate
462 // through all the extensions that extend a given Descriptor, and an
463 // ordered data structure that implements lower_bound is convenient
464 // for that.
465 typedef std::map<DescriptorIntPair, const FieldDescriptor*>
466     ExtensionsGroupedByDescriptorMap;
467 typedef HASH_MAP<std::string, const SourceCodeInfo_Location*>
468     LocationsByPathMap;
469 
NewAllowedProto3Extendee()470 std::set<std::string>* NewAllowedProto3Extendee() {
471   auto allowed_proto3_extendees = new std::set<std::string>;
472   const char* kOptionNames[] = {
473       "FileOptions",      "MessageOptions", "FieldOptions",  "EnumOptions",
474       "EnumValueOptions", "ServiceOptions", "MethodOptions", "OneofOptions"};
475   for (const char* option_name : kOptionNames) {
476     // descriptor.proto has a different package name in opensource. We allow
477     // both so the opensource protocol compiler can also compile internal
478     // proto3 files with custom options. See: b/27567912
479     allowed_proto3_extendees->insert(std::string("google.protobuf.") +
480                                      option_name);
481     // Split the word to trick the opensource processing scripts so they
482     // will keep the original package name.
483     allowed_proto3_extendees->insert(std::string("proto") + "2." + option_name);
484   }
485   return allowed_proto3_extendees;
486 }
487 
488 // Checks whether the extendee type is allowed in proto3.
489 // Only extensions to descriptor options are allowed. We use name comparison
490 // instead of comparing the descriptor directly because the extensions may be
491 // defined in a different pool.
AllowedExtendeeInProto3(const std::string & name)492 bool AllowedExtendeeInProto3(const std::string& name) {
493   static auto allowed_proto3_extendees =
494       internal::OnShutdownDelete(NewAllowedProto3Extendee());
495   return allowed_proto3_extendees->find(name) !=
496          allowed_proto3_extendees->end();
497 }
498 
499 }  // anonymous namespace
500 
501 // ===================================================================
502 // DescriptorPool::Tables
503 
504 class DescriptorPool::Tables {
505  public:
506   Tables();
507   ~Tables();
508 
509   // Record the current state of the tables to the stack of checkpoints.
510   // Each call to AddCheckpoint() must be paired with exactly one call to either
511   // ClearLastCheckpoint() or RollbackToLastCheckpoint().
512   //
513   // This is used when building files, since some kinds of validation errors
514   // cannot be detected until the file's descriptors have already been added to
515   // the tables.
516   //
517   // This supports recursive checkpoints, since building a file may trigger
518   // recursive building of other files. Note that recursive checkpoints are not
519   // normally necessary; explicit dependencies are built prior to checkpointing.
520   // So although we recursively build transitive imports, there is at most one
521   // checkpoint in the stack during dependency building.
522   //
523   // Recursive checkpoints only arise during cross-linking of the descriptors.
524   // Symbol references must be resolved, via DescriptorBuilder::FindSymbol and
525   // friends. If the pending file references an unknown symbol
526   // (e.g., it is not defined in the pending file's explicit dependencies), and
527   // the pool is using a fallback database, and that database contains a file
528   // defining that symbol, and that file has not yet been built by the pool,
529   // the pool builds the file during cross-linking, leading to another
530   // checkpoint.
531   void AddCheckpoint();
532 
533   // Mark the last checkpoint as having cleared successfully, removing it from
534   // the stack. If the stack is empty, all pending symbols will be committed.
535   //
536   // Note that this does not guarantee that the symbols added since the last
537   // checkpoint won't be rolled back: if a checkpoint gets rolled back,
538   // everything past that point gets rolled back, including symbols added after
539   // checkpoints that were pushed onto the stack after it and marked as cleared.
540   void ClearLastCheckpoint();
541 
542   // Roll back the Tables to the state of the checkpoint at the top of the
543   // stack, removing everything that was added after that point.
544   void RollbackToLastCheckpoint();
545 
546   // The stack of files which are currently being built.  Used to detect
547   // cyclic dependencies when loading files from a DescriptorDatabase.  Not
548   // used when fallback_database_ == nullptr.
549   std::vector<std::string> pending_files_;
550 
551   // A set of files which we have tried to load from the fallback database
552   // and encountered errors.  We will not attempt to load them again during
553   // execution of the current public API call, but for compatibility with
554   // legacy clients, this is cleared at the beginning of each public API call.
555   // Not used when fallback_database_ == nullptr.
556   HASH_SET<std::string> known_bad_files_;
557 
558   // A set of symbols which we have tried to load from the fallback database
559   // and encountered errors. We will not attempt to load them again during
560   // execution of the current public API call, but for compatibility with
561   // legacy clients, this is cleared at the beginning of each public API call.
562   HASH_SET<std::string> known_bad_symbols_;
563 
564   // The set of descriptors for which we've already loaded the full
565   // set of extensions numbers from fallback_database_.
566   HASH_SET<const Descriptor*> extensions_loaded_from_db_;
567 
568   // Maps type name to Descriptor::WellKnownType.  This is logically global
569   // and const, but we make it a member here to simplify its construction and
570   // destruction.  This only has 20-ish entries and is one per DescriptorPool,
571   // so the overhead is small.
572   HASH_MAP<std::string, Descriptor::WellKnownType> well_known_types_;
573 
574   // -----------------------------------------------------------------
575   // Finding items.
576 
577   // Find symbols.  This returns a null Symbol (symbol.IsNull() is true)
578   // if not found.
579   inline Symbol FindSymbol(StringPiece key) const;
580 
581   // This implements the body of DescriptorPool::Find*ByName().  It should
582   // really be a private method of DescriptorPool, but that would require
583   // declaring Symbol in descriptor.h, which would drag all kinds of other
584   // stuff into the header.  Yay C++.
585   Symbol FindByNameHelper(const DescriptorPool* pool, StringPiece name);
586 
587   // These return nullptr if not found.
588   inline const FileDescriptor* FindFile(StringPiece key) const;
589   inline const FieldDescriptor* FindExtension(const Descriptor* extendee,
590                                               int number) const;
591   inline void FindAllExtensions(const Descriptor* extendee,
592                                 std::vector<const FieldDescriptor*>* out) const;
593 
594   // -----------------------------------------------------------------
595   // Adding items.
596 
597   // These add items to the corresponding tables.  They return false if
598   // the key already exists in the table.  For AddSymbol(), the string passed
599   // in must be one that was constructed using AllocateString(), as it will
600   // be used as a key in the symbols_by_name_ map without copying.
601   bool AddSymbol(const std::string& full_name, Symbol symbol);
602   bool AddFile(const FileDescriptor* file);
603   bool AddExtension(const FieldDescriptor* field);
604 
605   // -----------------------------------------------------------------
606   // Allocating memory.
607 
608   // Allocate an object which will be reclaimed when the pool is
609   // destroyed.  Note that the object's destructor will never be called,
610   // so its fields must be plain old data (primitive data types and
611   // pointers).  All of the descriptor types are such objects.
612   template <typename Type>
613   Type* Allocate();
614 
615   // Allocate an array of objects which will be reclaimed when the
616   // pool in destroyed.  Again, destructors are never called.
617   template <typename Type>
618   Type* AllocateArray(int count);
619 
620   // Allocate a string which will be destroyed when the pool is destroyed.
621   // The string is initialized to the given value for convenience.
622   std::string* AllocateString(StringPiece value);
623 
624   // Allocate empty string which will be destroyed when the pool is destroyed.
625   std::string* AllocateEmptyString();
626 
627   // Allocate a internal::call_once which will be destroyed when the pool is
628   // destroyed.
629   internal::once_flag* AllocateOnceDynamic();
630 
631   // Allocate a protocol message object.  Some older versions of GCC have
632   // trouble understanding explicit template instantiations in some cases, so
633   // in those cases we have to pass a dummy pointer of the right type as the
634   // parameter instead of specifying the type explicitly.
635   template <typename Type>
636   Type* AllocateMessage(Type* dummy = nullptr);
637 
638   // Allocate a FileDescriptorTables object.
639   FileDescriptorTables* AllocateFileTables();
640 
641  private:
642   // All other memory allocated in the pool.  Must be first as other objects can
643   // point into these.
644   std::vector<std::vector<char>> allocations_;
645   std::vector<std::unique_ptr<std::string>> strings_;
646   std::vector<std::unique_ptr<Message>> messages_;
647   std::vector<std::unique_ptr<internal::once_flag>> once_dynamics_;
648   std::vector<std::unique_ptr<FileDescriptorTables>> file_tables_;
649 
650   SymbolsByNameMap symbols_by_name_;
651   FilesByNameMap files_by_name_;
652   ExtensionsGroupedByDescriptorMap extensions_;
653 
654   struct CheckPoint {
CheckPointgoogle::protobuf::DescriptorPool::Tables::CheckPoint655     explicit CheckPoint(const Tables* tables)
656         : strings_before_checkpoint(tables->strings_.size()),
657           messages_before_checkpoint(tables->messages_.size()),
658           once_dynamics_before_checkpoint(tables->once_dynamics_.size()),
659           file_tables_before_checkpoint(tables->file_tables_.size()),
660           allocations_before_checkpoint(tables->allocations_.size()),
661           pending_symbols_before_checkpoint(
662               tables->symbols_after_checkpoint_.size()),
663           pending_files_before_checkpoint(
664               tables->files_after_checkpoint_.size()),
665           pending_extensions_before_checkpoint(
666               tables->extensions_after_checkpoint_.size()) {}
667     int strings_before_checkpoint;
668     int messages_before_checkpoint;
669     int once_dynamics_before_checkpoint;
670     int file_tables_before_checkpoint;
671     int allocations_before_checkpoint;
672     int pending_symbols_before_checkpoint;
673     int pending_files_before_checkpoint;
674     int pending_extensions_before_checkpoint;
675   };
676   std::vector<CheckPoint> checkpoints_;
677   std::vector<const char*> symbols_after_checkpoint_;
678   std::vector<const char*> files_after_checkpoint_;
679   std::vector<DescriptorIntPair> extensions_after_checkpoint_;
680 
681   // Allocate some bytes which will be reclaimed when the pool is
682   // destroyed.
683   void* AllocateBytes(int size);
684 };
685 
686 // Contains tables specific to a particular file.  These tables are not
687 // modified once the file has been constructed, so they need not be
688 // protected by a mutex.  This makes operations that depend only on the
689 // contents of a single file -- e.g. Descriptor::FindFieldByName() --
690 // lock-free.
691 //
692 // For historical reasons, the definitions of the methods of
693 // FileDescriptorTables and DescriptorPool::Tables are interleaved below.
694 // These used to be a single class.
695 class FileDescriptorTables {
696  public:
697   FileDescriptorTables();
698   ~FileDescriptorTables();
699 
700   // Empty table, used with placeholder files.
701   inline static const FileDescriptorTables& GetEmptyInstance();
702 
703   // -----------------------------------------------------------------
704   // Finding items.
705 
706   // Find symbols.  These return a null Symbol (symbol.IsNull() is true)
707   // if not found.
708   inline Symbol FindNestedSymbol(const void* parent,
709                                  StringPiece name) const;
710   inline Symbol FindNestedSymbolOfType(const void* parent,
711                                        StringPiece name,
712                                        const Symbol::Type type) const;
713 
714   // These return nullptr if not found.
715   inline const FieldDescriptor* FindFieldByNumber(const Descriptor* parent,
716                                                   int number) const;
717   inline const FieldDescriptor* FindFieldByLowercaseName(
718       const void* parent, StringPiece lowercase_name) const;
719   inline const FieldDescriptor* FindFieldByCamelcaseName(
720       const void* parent, StringPiece camelcase_name) const;
721   inline const EnumValueDescriptor* FindEnumValueByNumber(
722       const EnumDescriptor* parent, int number) const;
723   // This creates a new EnumValueDescriptor if not found, in a thread-safe way.
724   inline const EnumValueDescriptor* FindEnumValueByNumberCreatingIfUnknown(
725       const EnumDescriptor* parent, int number) const;
726 
727   // -----------------------------------------------------------------
728   // Adding items.
729 
730   // These add items to the corresponding tables.  They return false if
731   // the key already exists in the table.  For AddAliasUnderParent(), the
732   // string passed in must be one that was constructed using AllocateString(),
733   // as it will be used as a key in the symbols_by_parent_ map without copying.
734   bool AddAliasUnderParent(const void* parent, const std::string& name,
735                            Symbol symbol);
736   bool AddFieldByNumber(const FieldDescriptor* field);
737   bool AddEnumValueByNumber(const EnumValueDescriptor* value);
738 
739   // Adds the field to the lowercase_name and camelcase_name maps.  Never
740   // fails because we allow duplicates; the first field by the name wins.
741   void AddFieldByStylizedNames(const FieldDescriptor* field);
742 
743   // Populates p->first->locations_by_path_ from p->second.
744   // Unusual signature dictated by internal::call_once.
745   static void BuildLocationsByPath(
746       std::pair<const FileDescriptorTables*, const SourceCodeInfo*>* p);
747 
748   // Returns the location denoted by the specified path through info,
749   // or nullptr if not found.
750   // The value of info must be that of the corresponding FileDescriptor.
751   // (Conceptually a pure function, but stateful as an optimisation.)
752   const SourceCodeInfo_Location* GetSourceLocation(
753       const std::vector<int>& path, const SourceCodeInfo* info) const;
754 
755   // Must be called after BuildFileImpl(), even if the build failed and
756   // we are going to roll back to the last checkpoint.
757   void FinalizeTables();
758 
759  private:
760   const void* FindParentForFieldsByMap(const FieldDescriptor* field) const;
761   static void FieldsByLowercaseNamesLazyInitStatic(
762       const FileDescriptorTables* tables);
763   void FieldsByLowercaseNamesLazyInitInternal() const;
764   static void FieldsByCamelcaseNamesLazyInitStatic(
765       const FileDescriptorTables* tables);
766   void FieldsByCamelcaseNamesLazyInitInternal() const;
767 
768   SymbolsByParentMap symbols_by_parent_;
769   mutable FieldsByNameMap fields_by_lowercase_name_;
770   std::unique_ptr<FieldsByNameMap> fields_by_lowercase_name_tmp_;
771   mutable internal::once_flag fields_by_lowercase_name_once_;
772   mutable FieldsByNameMap fields_by_camelcase_name_;
773   std::unique_ptr<FieldsByNameMap> fields_by_camelcase_name_tmp_;
774   mutable internal::once_flag fields_by_camelcase_name_once_;
775   FieldsByNumberMap fields_by_number_;  // Not including extensions.
776   EnumValuesByNumberMap enum_values_by_number_;
777   mutable EnumValuesByNumberMap unknown_enum_values_by_number_
778       PROTOBUF_GUARDED_BY(unknown_enum_values_mu_);
779 
780   // Populated on first request to save space, hence constness games.
781   mutable internal::once_flag locations_by_path_once_;
782   mutable LocationsByPathMap locations_by_path_;
783 
784   // Mutex to protect the unknown-enum-value map due to dynamic
785   // EnumValueDescriptor creation on unknown values.
786   mutable internal::WrappedMutex unknown_enum_values_mu_;
787 };
788 
Tables()789 DescriptorPool::Tables::Tables() {
790   well_known_types_.insert({
791       {"google.protobuf.DoubleValue", Descriptor::WELLKNOWNTYPE_DOUBLEVALUE},
792       {"google.protobuf.FloatValue", Descriptor::WELLKNOWNTYPE_FLOATVALUE},
793       {"google.protobuf.Int64Value", Descriptor::WELLKNOWNTYPE_INT64VALUE},
794       {"google.protobuf.UInt64Value", Descriptor::WELLKNOWNTYPE_UINT64VALUE},
795       {"google.protobuf.Int32Value", Descriptor::WELLKNOWNTYPE_INT32VALUE},
796       {"google.protobuf.UInt32Value", Descriptor::WELLKNOWNTYPE_UINT32VALUE},
797       {"google.protobuf.StringValue", Descriptor::WELLKNOWNTYPE_STRINGVALUE},
798       {"google.protobuf.BytesValue", Descriptor::WELLKNOWNTYPE_BYTESVALUE},
799       {"google.protobuf.BoolValue", Descriptor::WELLKNOWNTYPE_BOOLVALUE},
800       {"google.protobuf.Any", Descriptor::WELLKNOWNTYPE_ANY},
801       {"google.protobuf.FieldMask", Descriptor::WELLKNOWNTYPE_FIELDMASK},
802       {"google.protobuf.Duration", Descriptor::WELLKNOWNTYPE_DURATION},
803       {"google.protobuf.Timestamp", Descriptor::WELLKNOWNTYPE_TIMESTAMP},
804       {"google.protobuf.Value", Descriptor::WELLKNOWNTYPE_VALUE},
805       {"google.protobuf.ListValue", Descriptor::WELLKNOWNTYPE_LISTVALUE},
806       {"google.protobuf.Struct", Descriptor::WELLKNOWNTYPE_STRUCT},
807   });
808 }
809 
~Tables()810 DescriptorPool::Tables::~Tables() { GOOGLE_DCHECK(checkpoints_.empty()); }
811 
FileDescriptorTables()812 FileDescriptorTables::FileDescriptorTables()
813     : fields_by_lowercase_name_tmp_(new FieldsByNameMap()),
814       fields_by_camelcase_name_tmp_(new FieldsByNameMap()) {}
815 
~FileDescriptorTables()816 FileDescriptorTables::~FileDescriptorTables() {}
817 
GetEmptyInstance()818 inline const FileDescriptorTables& FileDescriptorTables::GetEmptyInstance() {
819   static auto file_descriptor_tables =
820       internal::OnShutdownDelete(new FileDescriptorTables());
821   return *file_descriptor_tables;
822 }
823 
AddCheckpoint()824 void DescriptorPool::Tables::AddCheckpoint() {
825   checkpoints_.push_back(CheckPoint(this));
826 }
827 
ClearLastCheckpoint()828 void DescriptorPool::Tables::ClearLastCheckpoint() {
829   GOOGLE_DCHECK(!checkpoints_.empty());
830   checkpoints_.pop_back();
831   if (checkpoints_.empty()) {
832     // All checkpoints have been cleared: we can now commit all of the pending
833     // data.
834     symbols_after_checkpoint_.clear();
835     files_after_checkpoint_.clear();
836     extensions_after_checkpoint_.clear();
837   }
838 }
839 
RollbackToLastCheckpoint()840 void DescriptorPool::Tables::RollbackToLastCheckpoint() {
841   GOOGLE_DCHECK(!checkpoints_.empty());
842   const CheckPoint& checkpoint = checkpoints_.back();
843 
844   for (size_t i = checkpoint.pending_symbols_before_checkpoint;
845        i < symbols_after_checkpoint_.size(); i++) {
846     symbols_by_name_.erase(symbols_after_checkpoint_[i]);
847   }
848   for (size_t i = checkpoint.pending_files_before_checkpoint;
849        i < files_after_checkpoint_.size(); i++) {
850     files_by_name_.erase(files_after_checkpoint_[i]);
851   }
852   for (size_t i = checkpoint.pending_extensions_before_checkpoint;
853        i < extensions_after_checkpoint_.size(); i++) {
854     extensions_.erase(extensions_after_checkpoint_[i]);
855   }
856 
857   symbols_after_checkpoint_.resize(
858       checkpoint.pending_symbols_before_checkpoint);
859   files_after_checkpoint_.resize(checkpoint.pending_files_before_checkpoint);
860   extensions_after_checkpoint_.resize(
861       checkpoint.pending_extensions_before_checkpoint);
862 
863   strings_.resize(checkpoint.strings_before_checkpoint);
864   messages_.resize(checkpoint.messages_before_checkpoint);
865   once_dynamics_.resize(checkpoint.once_dynamics_before_checkpoint);
866   file_tables_.resize(checkpoint.file_tables_before_checkpoint);
867   allocations_.resize(checkpoint.allocations_before_checkpoint);
868   checkpoints_.pop_back();
869 }
870 
871 // -------------------------------------------------------------------
872 
FindSymbol(StringPiece key) const873 inline Symbol DescriptorPool::Tables::FindSymbol(StringPiece key) const {
874   const Symbol* result = FindOrNull(symbols_by_name_, key);
875   if (result == nullptr) {
876     return kNullSymbol;
877   } else {
878     return *result;
879   }
880 }
881 
FindNestedSymbol(const void * parent,StringPiece name) const882 inline Symbol FileDescriptorTables::FindNestedSymbol(
883     const void* parent, StringPiece name) const {
884   const Symbol* result =
885       FindOrNull(symbols_by_parent_, PointerStringPair(parent, name));
886   if (result == nullptr) {
887     return kNullSymbol;
888   } else {
889     return *result;
890   }
891 }
892 
FindNestedSymbolOfType(const void * parent,StringPiece name,const Symbol::Type type) const893 inline Symbol FileDescriptorTables::FindNestedSymbolOfType(
894     const void* parent, StringPiece name, const Symbol::Type type) const {
895   Symbol result = FindNestedSymbol(parent, name);
896   if (result.type != type) return kNullSymbol;
897   return result;
898 }
899 
FindByNameHelper(const DescriptorPool * pool,StringPiece name)900 Symbol DescriptorPool::Tables::FindByNameHelper(const DescriptorPool* pool,
901                                                 StringPiece name) {
902   if (pool->mutex_ != nullptr) {
903     // Fast path: the Symbol is already cached.  This is just a hash lookup.
904     ReaderMutexLock lock(pool->mutex_);
905     if (known_bad_symbols_.empty() && known_bad_files_.empty()) {
906       Symbol result = FindSymbol(name);
907       if (!result.IsNull()) return result;
908     }
909   }
910   MutexLockMaybe lock(pool->mutex_);
911   if (pool->fallback_database_ != nullptr) {
912     known_bad_symbols_.clear();
913     known_bad_files_.clear();
914   }
915   Symbol result = FindSymbol(name);
916 
917   if (result.IsNull() && pool->underlay_ != nullptr) {
918     // Symbol not found; check the underlay.
919     result = pool->underlay_->tables_->FindByNameHelper(pool->underlay_, name);
920   }
921 
922   if (result.IsNull()) {
923     // Symbol still not found, so check fallback database.
924     if (pool->TryFindSymbolInFallbackDatabase(name)) {
925       result = FindSymbol(name);
926     }
927   }
928 
929   return result;
930 }
931 
FindFile(StringPiece key) const932 inline const FileDescriptor* DescriptorPool::Tables::FindFile(
933     StringPiece key) const {
934   return FindPtrOrNull(files_by_name_, key);
935 }
936 
FindFieldByNumber(const Descriptor * parent,int number) const937 inline const FieldDescriptor* FileDescriptorTables::FindFieldByNumber(
938     const Descriptor* parent, int number) const {
939   return FindPtrOrNull(fields_by_number_, std::make_pair(parent, number));
940 }
941 
FindParentForFieldsByMap(const FieldDescriptor * field) const942 const void* FileDescriptorTables::FindParentForFieldsByMap(
943     const FieldDescriptor* field) const {
944   if (field->is_extension()) {
945     if (field->extension_scope() == nullptr) {
946       return field->file();
947     } else {
948       return field->extension_scope();
949     }
950   } else {
951     return field->containing_type();
952   }
953 }
954 
FieldsByLowercaseNamesLazyInitStatic(const FileDescriptorTables * tables)955 void FileDescriptorTables::FieldsByLowercaseNamesLazyInitStatic(
956     const FileDescriptorTables* tables) {
957   tables->FieldsByLowercaseNamesLazyInitInternal();
958 }
959 
FieldsByLowercaseNamesLazyInitInternal() const960 void FileDescriptorTables::FieldsByLowercaseNamesLazyInitInternal() const {
961   for (FieldsByNumberMap::const_iterator it = fields_by_number_.begin();
962        it != fields_by_number_.end(); it++) {
963     PointerStringPair lowercase_key(FindParentForFieldsByMap(it->second),
964                                     it->second->lowercase_name().c_str());
965     InsertIfNotPresent(&fields_by_lowercase_name_, lowercase_key,
966                             it->second);
967   }
968 }
969 
FindFieldByLowercaseName(const void * parent,StringPiece lowercase_name) const970 inline const FieldDescriptor* FileDescriptorTables::FindFieldByLowercaseName(
971     const void* parent, StringPiece lowercase_name) const {
972   internal::call_once(
973       fields_by_lowercase_name_once_,
974       &FileDescriptorTables::FieldsByLowercaseNamesLazyInitStatic, this);
975   return FindPtrOrNull(fields_by_lowercase_name_,
976                             PointerStringPair(parent, lowercase_name));
977 }
978 
FieldsByCamelcaseNamesLazyInitStatic(const FileDescriptorTables * tables)979 void FileDescriptorTables::FieldsByCamelcaseNamesLazyInitStatic(
980     const FileDescriptorTables* tables) {
981   tables->FieldsByCamelcaseNamesLazyInitInternal();
982 }
983 
FieldsByCamelcaseNamesLazyInitInternal() const984 void FileDescriptorTables::FieldsByCamelcaseNamesLazyInitInternal() const {
985   for (FieldsByNumberMap::const_iterator it = fields_by_number_.begin();
986        it != fields_by_number_.end(); it++) {
987     PointerStringPair camelcase_key(FindParentForFieldsByMap(it->second),
988                                     it->second->camelcase_name().c_str());
989     InsertIfNotPresent(&fields_by_camelcase_name_, camelcase_key,
990                             it->second);
991   }
992 }
993 
FindFieldByCamelcaseName(const void * parent,StringPiece camelcase_name) const994 inline const FieldDescriptor* FileDescriptorTables::FindFieldByCamelcaseName(
995     const void* parent, StringPiece camelcase_name) const {
996   internal::call_once(
997       fields_by_camelcase_name_once_,
998       FileDescriptorTables::FieldsByCamelcaseNamesLazyInitStatic, this);
999   return FindPtrOrNull(fields_by_camelcase_name_,
1000                             PointerStringPair(parent, camelcase_name));
1001 }
1002 
FindEnumValueByNumber(const EnumDescriptor * parent,int number) const1003 inline const EnumValueDescriptor* FileDescriptorTables::FindEnumValueByNumber(
1004     const EnumDescriptor* parent, int number) const {
1005   return FindPtrOrNull(enum_values_by_number_,
1006                             std::make_pair(parent, number));
1007 }
1008 
1009 inline const EnumValueDescriptor*
FindEnumValueByNumberCreatingIfUnknown(const EnumDescriptor * parent,int number) const1010 FileDescriptorTables::FindEnumValueByNumberCreatingIfUnknown(
1011     const EnumDescriptor* parent, int number) const {
1012   // First try, with map of compiled-in values.
1013   {
1014     const EnumValueDescriptor* desc = FindPtrOrNull(
1015         enum_values_by_number_, std::make_pair(parent, number));
1016     if (desc != nullptr) {
1017       return desc;
1018     }
1019   }
1020   // Second try, with reader lock held on unknown enum values: common case.
1021   {
1022     ReaderMutexLock l(&unknown_enum_values_mu_);
1023     const EnumValueDescriptor* desc = FindPtrOrNull(
1024         unknown_enum_values_by_number_, std::make_pair(parent, number));
1025     if (desc != nullptr) {
1026       return desc;
1027     }
1028   }
1029   // If not found, try again with writer lock held, and create new descriptor if
1030   // necessary.
1031   {
1032     WriterMutexLock l(&unknown_enum_values_mu_);
1033     const EnumValueDescriptor* desc = FindPtrOrNull(
1034         unknown_enum_values_by_number_, std::make_pair(parent, number));
1035     if (desc != nullptr) {
1036       return desc;
1037     }
1038 
1039     // Create an EnumValueDescriptor dynamically. We don't insert it into the
1040     // EnumDescriptor (it's not a part of the enum as originally defined), but
1041     // we do insert it into the table so that we can return the same pointer
1042     // later.
1043     std::string enum_value_name = StringPrintf("UNKNOWN_ENUM_VALUE_%s_%d",
1044                                                parent->name().c_str(), number);
1045     DescriptorPool::Tables* tables = const_cast<DescriptorPool::Tables*>(
1046         DescriptorPool::generated_pool()->tables_.get());
1047     EnumValueDescriptor* result = tables->Allocate<EnumValueDescriptor>();
1048     result->name_ = tables->AllocateString(enum_value_name);
1049     result->full_name_ =
1050         tables->AllocateString(parent->full_name() + "." + enum_value_name);
1051     result->number_ = number;
1052     result->type_ = parent;
1053     result->options_ = &EnumValueOptions::default_instance();
1054     InsertIfNotPresent(&unknown_enum_values_by_number_,
1055                             std::make_pair(parent, number), result);
1056     return result;
1057   }
1058 }
1059 
FindExtension(const Descriptor * extendee,int number) const1060 inline const FieldDescriptor* DescriptorPool::Tables::FindExtension(
1061     const Descriptor* extendee, int number) const {
1062   return FindPtrOrNull(extensions_, std::make_pair(extendee, number));
1063 }
1064 
FindAllExtensions(const Descriptor * extendee,std::vector<const FieldDescriptor * > * out) const1065 inline void DescriptorPool::Tables::FindAllExtensions(
1066     const Descriptor* extendee,
1067     std::vector<const FieldDescriptor*>* out) const {
1068   ExtensionsGroupedByDescriptorMap::const_iterator it =
1069       extensions_.lower_bound(std::make_pair(extendee, 0));
1070   for (; it != extensions_.end() && it->first.first == extendee; ++it) {
1071     out->push_back(it->second);
1072   }
1073 }
1074 
1075 // -------------------------------------------------------------------
1076 
AddSymbol(const std::string & full_name,Symbol symbol)1077 bool DescriptorPool::Tables::AddSymbol(const std::string& full_name,
1078                                        Symbol symbol) {
1079   if (InsertIfNotPresent(&symbols_by_name_, full_name, symbol)) {
1080     symbols_after_checkpoint_.push_back(full_name.c_str());
1081     return true;
1082   } else {
1083     return false;
1084   }
1085 }
1086 
AddAliasUnderParent(const void * parent,const std::string & name,Symbol symbol)1087 bool FileDescriptorTables::AddAliasUnderParent(const void* parent,
1088                                                const std::string& name,
1089                                                Symbol symbol) {
1090   PointerStringPair by_parent_key(parent, name.c_str());
1091   return InsertIfNotPresent(&symbols_by_parent_, by_parent_key, symbol);
1092 }
1093 
AddFile(const FileDescriptor * file)1094 bool DescriptorPool::Tables::AddFile(const FileDescriptor* file) {
1095   if (InsertIfNotPresent(&files_by_name_, file->name(), file)) {
1096     files_after_checkpoint_.push_back(file->name().c_str());
1097     return true;
1098   } else {
1099     return false;
1100   }
1101 }
1102 
FinalizeTables()1103 void FileDescriptorTables::FinalizeTables() {
1104   // Clean up the temporary maps used by AddFieldByStylizedNames().
1105   fields_by_lowercase_name_tmp_ = nullptr;
1106   fields_by_camelcase_name_tmp_ = nullptr;
1107 }
1108 
AddFieldByStylizedNames(const FieldDescriptor * field)1109 void FileDescriptorTables::AddFieldByStylizedNames(
1110     const FieldDescriptor* field) {
1111   const void* parent = FindParentForFieldsByMap(field);
1112 
1113   // We want fields_by_{lower,camel}case_name_ to be lazily built, but
1114   // cross-link order determines which entry will be present in the case of a
1115   // conflict. So we use the temporary maps that get destroyed after
1116   // BuildFileImpl() to detect the conflicts, and only store the conflicts in
1117   // the map that will persist. We will then lazily populate the rest of the
1118   // entries from fields_by_number_.
1119 
1120   PointerStringPair lowercase_key(parent, field->lowercase_name().c_str());
1121   if (!InsertIfNotPresent(fields_by_lowercase_name_tmp_.get(),
1122                                lowercase_key, field)) {
1123     InsertIfNotPresent(
1124         &fields_by_lowercase_name_, lowercase_key,
1125         FindPtrOrNull(*fields_by_lowercase_name_tmp_, lowercase_key));
1126   }
1127 
1128   PointerStringPair camelcase_key(parent, field->camelcase_name().c_str());
1129   if (!InsertIfNotPresent(fields_by_camelcase_name_tmp_.get(),
1130                                camelcase_key, field)) {
1131     InsertIfNotPresent(
1132         &fields_by_camelcase_name_, camelcase_key,
1133         FindPtrOrNull(*fields_by_camelcase_name_tmp_, camelcase_key));
1134   }
1135 }
1136 
AddFieldByNumber(const FieldDescriptor * field)1137 bool FileDescriptorTables::AddFieldByNumber(const FieldDescriptor* field) {
1138   DescriptorIntPair key(field->containing_type(), field->number());
1139   return InsertIfNotPresent(&fields_by_number_, key, field);
1140 }
1141 
AddEnumValueByNumber(const EnumValueDescriptor * value)1142 bool FileDescriptorTables::AddEnumValueByNumber(
1143     const EnumValueDescriptor* value) {
1144   EnumIntPair key(value->type(), value->number());
1145   return InsertIfNotPresent(&enum_values_by_number_, key, value);
1146 }
1147 
AddExtension(const FieldDescriptor * field)1148 bool DescriptorPool::Tables::AddExtension(const FieldDescriptor* field) {
1149   DescriptorIntPair key(field->containing_type(), field->number());
1150   if (InsertIfNotPresent(&extensions_, key, field)) {
1151     extensions_after_checkpoint_.push_back(key);
1152     return true;
1153   } else {
1154     return false;
1155   }
1156 }
1157 
1158 // -------------------------------------------------------------------
1159 
1160 template <typename Type>
Allocate()1161 Type* DescriptorPool::Tables::Allocate() {
1162   return reinterpret_cast<Type*>(AllocateBytes(sizeof(Type)));
1163 }
1164 
1165 template <typename Type>
AllocateArray(int count)1166 Type* DescriptorPool::Tables::AllocateArray(int count) {
1167   return reinterpret_cast<Type*>(AllocateBytes(sizeof(Type) * count));
1168 }
1169 
AllocateString(StringPiece value)1170 std::string* DescriptorPool::Tables::AllocateString(StringPiece value) {
1171   std::string* result = new std::string(value);
1172   strings_.emplace_back(result);
1173   return result;
1174 }
1175 
AllocateEmptyString()1176 std::string* DescriptorPool::Tables::AllocateEmptyString() {
1177   std::string* result = new std::string();
1178   strings_.emplace_back(result);
1179   return result;
1180 }
1181 
AllocateOnceDynamic()1182 internal::once_flag* DescriptorPool::Tables::AllocateOnceDynamic() {
1183   internal::once_flag* result = new internal::once_flag();
1184   once_dynamics_.emplace_back(result);
1185   return result;
1186 }
1187 
1188 template <typename Type>
AllocateMessage(Type *)1189 Type* DescriptorPool::Tables::AllocateMessage(Type* /* dummy */) {
1190   Type* result = new Type;
1191   messages_.emplace_back(result);
1192   return result;
1193 }
1194 
AllocateFileTables()1195 FileDescriptorTables* DescriptorPool::Tables::AllocateFileTables() {
1196   FileDescriptorTables* result = new FileDescriptorTables;
1197   file_tables_.emplace_back(result);
1198   return result;
1199 }
1200 
AllocateBytes(int size)1201 void* DescriptorPool::Tables::AllocateBytes(int size) {
1202   // TODO(kenton):  Would it be worthwhile to implement this in some more
1203   // sophisticated way?  Probably not for the open source release, but for
1204   // internal use we could easily plug in one of our existing memory pool
1205   // allocators...
1206   if (size == 0) return nullptr;
1207 
1208   allocations_.emplace_back(size);
1209   return allocations_.back().data();
1210 }
1211 
BuildLocationsByPath(std::pair<const FileDescriptorTables *,const SourceCodeInfo * > * p)1212 void FileDescriptorTables::BuildLocationsByPath(
1213     std::pair<const FileDescriptorTables*, const SourceCodeInfo*>* p) {
1214   for (int i = 0, len = p->second->location_size(); i < len; ++i) {
1215     const SourceCodeInfo_Location* loc = &p->second->location().Get(i);
1216     p->first->locations_by_path_[Join(loc->path(), ",")] = loc;
1217   }
1218 }
1219 
GetSourceLocation(const std::vector<int> & path,const SourceCodeInfo * info) const1220 const SourceCodeInfo_Location* FileDescriptorTables::GetSourceLocation(
1221     const std::vector<int>& path, const SourceCodeInfo* info) const {
1222   std::pair<const FileDescriptorTables*, const SourceCodeInfo*> p(
1223       std::make_pair(this, info));
1224   internal::call_once(locations_by_path_once_,
1225                       FileDescriptorTables::BuildLocationsByPath, &p);
1226   return FindPtrOrNull(locations_by_path_, Join(path, ","));
1227 }
1228 
1229 // ===================================================================
1230 // DescriptorPool
1231 
~ErrorCollector()1232 DescriptorPool::ErrorCollector::~ErrorCollector() {}
1233 
DescriptorPool()1234 DescriptorPool::DescriptorPool()
1235     : mutex_(nullptr),
1236       fallback_database_(nullptr),
1237       default_error_collector_(nullptr),
1238       underlay_(nullptr),
1239       tables_(new Tables),
1240       enforce_dependencies_(true),
1241       lazily_build_dependencies_(false),
1242       allow_unknown_(false),
1243       enforce_weak_(false),
1244       disallow_enforce_utf8_(false) {}
1245 
DescriptorPool(DescriptorDatabase * fallback_database,ErrorCollector * error_collector)1246 DescriptorPool::DescriptorPool(DescriptorDatabase* fallback_database,
1247                                ErrorCollector* error_collector)
1248     : mutex_(new internal::WrappedMutex),
1249       fallback_database_(fallback_database),
1250       default_error_collector_(error_collector),
1251       underlay_(nullptr),
1252       tables_(new Tables),
1253       enforce_dependencies_(true),
1254       lazily_build_dependencies_(false),
1255       allow_unknown_(false),
1256       enforce_weak_(false),
1257       disallow_enforce_utf8_(false) {}
1258 
DescriptorPool(const DescriptorPool * underlay)1259 DescriptorPool::DescriptorPool(const DescriptorPool* underlay)
1260     : mutex_(nullptr),
1261       fallback_database_(nullptr),
1262       default_error_collector_(nullptr),
1263       underlay_(underlay),
1264       tables_(new Tables),
1265       enforce_dependencies_(true),
1266       lazily_build_dependencies_(false),
1267       allow_unknown_(false),
1268       enforce_weak_(false),
1269       disallow_enforce_utf8_(false) {}
1270 
~DescriptorPool()1271 DescriptorPool::~DescriptorPool() {
1272   if (mutex_ != nullptr) delete mutex_;
1273 }
1274 
1275 // DescriptorPool::BuildFile() defined later.
1276 // DescriptorPool::BuildFileCollectingErrors() defined later.
1277 
InternalDontEnforceDependencies()1278 void DescriptorPool::InternalDontEnforceDependencies() {
1279   enforce_dependencies_ = false;
1280 }
1281 
AddUnusedImportTrackFile(ConstStringParam file_name,bool is_error)1282 void DescriptorPool::AddUnusedImportTrackFile(ConstStringParam file_name,
1283                                               bool is_error) {
1284   unused_import_track_files_[std::string(file_name)] = is_error;
1285 }
1286 
ClearUnusedImportTrackFiles()1287 void DescriptorPool::ClearUnusedImportTrackFiles() {
1288   unused_import_track_files_.clear();
1289 }
1290 
InternalIsFileLoaded(ConstStringParam filename) const1291 bool DescriptorPool::InternalIsFileLoaded(ConstStringParam filename) const {
1292   MutexLockMaybe lock(mutex_);
1293   return tables_->FindFile(filename) != nullptr;
1294 }
1295 
1296 // generated_pool ====================================================
1297 
1298 namespace {
1299 
1300 
GeneratedDatabase()1301 EncodedDescriptorDatabase* GeneratedDatabase() {
1302   static auto generated_database =
1303       internal::OnShutdownDelete(new EncodedDescriptorDatabase());
1304   return generated_database;
1305 }
1306 
NewGeneratedPool()1307 DescriptorPool* NewGeneratedPool() {
1308   auto generated_pool = new DescriptorPool(GeneratedDatabase());
1309   generated_pool->InternalSetLazilyBuildDependencies();
1310   return generated_pool;
1311 }
1312 
1313 }  // anonymous namespace
1314 
internal_generated_database()1315 DescriptorDatabase* DescriptorPool::internal_generated_database() {
1316   return GeneratedDatabase();
1317 }
1318 
internal_generated_pool()1319 DescriptorPool* DescriptorPool::internal_generated_pool() {
1320   static DescriptorPool* generated_pool =
1321       internal::OnShutdownDelete(NewGeneratedPool());
1322   return generated_pool;
1323 }
1324 
generated_pool()1325 const DescriptorPool* DescriptorPool::generated_pool() {
1326   const DescriptorPool* pool = internal_generated_pool();
1327   // Ensure that descriptor.proto has been registered in the generated pool.
1328   DescriptorProto::descriptor();
1329   return pool;
1330 }
1331 
1332 
InternalAddGeneratedFile(const void * encoded_file_descriptor,int size)1333 void DescriptorPool::InternalAddGeneratedFile(
1334     const void* encoded_file_descriptor, int size) {
1335   // So, this function is called in the process of initializing the
1336   // descriptors for generated proto classes.  Each generated .pb.cc file
1337   // has an internal procedure called AddDescriptors() which is called at
1338   // process startup, and that function calls this one in order to register
1339   // the raw bytes of the FileDescriptorProto representing the file.
1340   //
1341   // We do not actually construct the descriptor objects right away.  We just
1342   // hang on to the bytes until they are actually needed.  We actually construct
1343   // the descriptor the first time one of the following things happens:
1344   // * Someone calls a method like descriptor(), GetDescriptor(), or
1345   //   GetReflection() on the generated types, which requires returning the
1346   //   descriptor or an object based on it.
1347   // * Someone looks up the descriptor in DescriptorPool::generated_pool().
1348   //
1349   // Once one of these happens, the DescriptorPool actually parses the
1350   // FileDescriptorProto and generates a FileDescriptor (and all its children)
1351   // based on it.
1352   //
1353   // Note that FileDescriptorProto is itself a generated protocol message.
1354   // Therefore, when we parse one, we have to be very careful to avoid using
1355   // any descriptor-based operations, since this might cause infinite recursion
1356   // or deadlock.
1357   GOOGLE_CHECK(GeneratedDatabase()->Add(encoded_file_descriptor, size));
1358 }
1359 
1360 
1361 // Find*By* methods ==================================================
1362 
1363 // TODO(kenton):  There's a lot of repeated code here, but I'm not sure if
1364 //   there's any good way to factor it out.  Think about this some time when
1365 //   there's nothing more important to do (read: never).
1366 
FindFileByName(ConstStringParam name) const1367 const FileDescriptor* DescriptorPool::FindFileByName(
1368     ConstStringParam name) const {
1369   MutexLockMaybe lock(mutex_);
1370   if (fallback_database_ != nullptr) {
1371     tables_->known_bad_symbols_.clear();
1372     tables_->known_bad_files_.clear();
1373   }
1374   const FileDescriptor* result = tables_->FindFile(name);
1375   if (result != nullptr) return result;
1376   if (underlay_ != nullptr) {
1377     result = underlay_->FindFileByName(name);
1378     if (result != nullptr) return result;
1379   }
1380   if (TryFindFileInFallbackDatabase(name)) {
1381     result = tables_->FindFile(name);
1382     if (result != nullptr) return result;
1383   }
1384   return nullptr;
1385 }
1386 
FindFileContainingSymbol(ConstStringParam symbol_name) const1387 const FileDescriptor* DescriptorPool::FindFileContainingSymbol(
1388     ConstStringParam symbol_name) const {
1389   MutexLockMaybe lock(mutex_);
1390   if (fallback_database_ != nullptr) {
1391     tables_->known_bad_symbols_.clear();
1392     tables_->known_bad_files_.clear();
1393   }
1394   Symbol result = tables_->FindSymbol(symbol_name);
1395   if (!result.IsNull()) return result.GetFile();
1396   if (underlay_ != nullptr) {
1397     const FileDescriptor* file_result =
1398         underlay_->FindFileContainingSymbol(symbol_name);
1399     if (file_result != nullptr) return file_result;
1400   }
1401   if (TryFindSymbolInFallbackDatabase(symbol_name)) {
1402     result = tables_->FindSymbol(symbol_name);
1403     if (!result.IsNull()) return result.GetFile();
1404   }
1405   return nullptr;
1406 }
1407 
FindMessageTypeByName(ConstStringParam name) const1408 const Descriptor* DescriptorPool::FindMessageTypeByName(
1409     ConstStringParam name) const {
1410   Symbol result = tables_->FindByNameHelper(this, name);
1411   return (result.type == Symbol::MESSAGE) ? result.descriptor : nullptr;
1412 }
1413 
FindFieldByName(ConstStringParam name) const1414 const FieldDescriptor* DescriptorPool::FindFieldByName(
1415     ConstStringParam name) const {
1416   Symbol result = tables_->FindByNameHelper(this, name);
1417   if (result.type == Symbol::FIELD &&
1418       !result.field_descriptor->is_extension()) {
1419     return result.field_descriptor;
1420   } else {
1421     return nullptr;
1422   }
1423 }
1424 
FindExtensionByName(ConstStringParam name) const1425 const FieldDescriptor* DescriptorPool::FindExtensionByName(
1426     ConstStringParam name) const {
1427   Symbol result = tables_->FindByNameHelper(this, name);
1428   if (result.type == Symbol::FIELD && result.field_descriptor->is_extension()) {
1429     return result.field_descriptor;
1430   } else {
1431     return nullptr;
1432   }
1433 }
1434 
FindOneofByName(ConstStringParam name) const1435 const OneofDescriptor* DescriptorPool::FindOneofByName(
1436     ConstStringParam name) const {
1437   Symbol result = tables_->FindByNameHelper(this, name);
1438   return (result.type == Symbol::ONEOF) ? result.oneof_descriptor : nullptr;
1439 }
1440 
FindEnumTypeByName(ConstStringParam name) const1441 const EnumDescriptor* DescriptorPool::FindEnumTypeByName(
1442     ConstStringParam name) const {
1443   Symbol result = tables_->FindByNameHelper(this, name);
1444   return (result.type == Symbol::ENUM) ? result.enum_descriptor : nullptr;
1445 }
1446 
FindEnumValueByName(ConstStringParam name) const1447 const EnumValueDescriptor* DescriptorPool::FindEnumValueByName(
1448     ConstStringParam name) const {
1449   Symbol result = tables_->FindByNameHelper(this, name);
1450   return (result.type == Symbol::ENUM_VALUE) ? result.enum_value_descriptor
1451                                              : nullptr;
1452 }
1453 
FindServiceByName(ConstStringParam name) const1454 const ServiceDescriptor* DescriptorPool::FindServiceByName(
1455     ConstStringParam name) const {
1456   Symbol result = tables_->FindByNameHelper(this, name);
1457   return (result.type == Symbol::SERVICE) ? result.service_descriptor : nullptr;
1458 }
1459 
FindMethodByName(ConstStringParam name) const1460 const MethodDescriptor* DescriptorPool::FindMethodByName(
1461     ConstStringParam name) const {
1462   Symbol result = tables_->FindByNameHelper(this, name);
1463   return (result.type == Symbol::METHOD) ? result.method_descriptor : nullptr;
1464 }
1465 
FindExtensionByNumber(const Descriptor * extendee,int number) const1466 const FieldDescriptor* DescriptorPool::FindExtensionByNumber(
1467     const Descriptor* extendee, int number) const {
1468   if (extendee->extension_range_count() == 0) return nullptr;
1469   // A faster path to reduce lock contention in finding extensions, assuming
1470   // most extensions will be cache hit.
1471   if (mutex_ != nullptr) {
1472     ReaderMutexLock lock(mutex_);
1473     const FieldDescriptor* result = tables_->FindExtension(extendee, number);
1474     if (result != nullptr) {
1475       return result;
1476     }
1477   }
1478   MutexLockMaybe lock(mutex_);
1479   if (fallback_database_ != nullptr) {
1480     tables_->known_bad_symbols_.clear();
1481     tables_->known_bad_files_.clear();
1482   }
1483   const FieldDescriptor* result = tables_->FindExtension(extendee, number);
1484   if (result != nullptr) {
1485     return result;
1486   }
1487   if (underlay_ != nullptr) {
1488     result = underlay_->FindExtensionByNumber(extendee, number);
1489     if (result != nullptr) return result;
1490   }
1491   if (TryFindExtensionInFallbackDatabase(extendee, number)) {
1492     result = tables_->FindExtension(extendee, number);
1493     if (result != nullptr) {
1494       return result;
1495     }
1496   }
1497   return nullptr;
1498 }
1499 
InternalFindExtensionByNumberNoLock(const Descriptor * extendee,int number) const1500 const FieldDescriptor* DescriptorPool::InternalFindExtensionByNumberNoLock(
1501     const Descriptor* extendee, int number) const {
1502   if (extendee->extension_range_count() == 0) return nullptr;
1503 
1504   const FieldDescriptor* result = tables_->FindExtension(extendee, number);
1505   if (result != nullptr) {
1506     return result;
1507   }
1508 
1509   if (underlay_ != nullptr) {
1510     result = underlay_->InternalFindExtensionByNumberNoLock(extendee, number);
1511     if (result != nullptr) return result;
1512   }
1513 
1514   return nullptr;
1515 }
1516 
FindExtensionByPrintableName(const Descriptor * extendee,ConstStringParam printable_name) const1517 const FieldDescriptor* DescriptorPool::FindExtensionByPrintableName(
1518     const Descriptor* extendee, ConstStringParam printable_name) const {
1519   if (extendee->extension_range_count() == 0) return nullptr;
1520   const FieldDescriptor* result = FindExtensionByName(printable_name);
1521   if (result != nullptr && result->containing_type() == extendee) {
1522     return result;
1523   }
1524   if (extendee->options().message_set_wire_format()) {
1525     // MessageSet extensions may be identified by type name.
1526     const Descriptor* type = FindMessageTypeByName(printable_name);
1527     if (type != nullptr) {
1528       // Look for a matching extension in the foreign type's scope.
1529       const int type_extension_count = type->extension_count();
1530       for (int i = 0; i < type_extension_count; i++) {
1531         const FieldDescriptor* extension = type->extension(i);
1532         if (extension->containing_type() == extendee &&
1533             extension->type() == FieldDescriptor::TYPE_MESSAGE &&
1534             extension->is_optional() && extension->message_type() == type) {
1535           // Found it.
1536           return extension;
1537         }
1538       }
1539     }
1540   }
1541   return nullptr;
1542 }
1543 
FindAllExtensions(const Descriptor * extendee,std::vector<const FieldDescriptor * > * out) const1544 void DescriptorPool::FindAllExtensions(
1545     const Descriptor* extendee,
1546     std::vector<const FieldDescriptor*>* out) const {
1547   MutexLockMaybe lock(mutex_);
1548   if (fallback_database_ != nullptr) {
1549     tables_->known_bad_symbols_.clear();
1550     tables_->known_bad_files_.clear();
1551   }
1552 
1553   // Initialize tables_->extensions_ from the fallback database first
1554   // (but do this only once per descriptor).
1555   if (fallback_database_ != nullptr &&
1556       tables_->extensions_loaded_from_db_.count(extendee) == 0) {
1557     std::vector<int> numbers;
1558     if (fallback_database_->FindAllExtensionNumbers(extendee->full_name(),
1559                                                     &numbers)) {
1560       for (int number : numbers) {
1561         if (tables_->FindExtension(extendee, number) == nullptr) {
1562           TryFindExtensionInFallbackDatabase(extendee, number);
1563         }
1564       }
1565       tables_->extensions_loaded_from_db_.insert(extendee);
1566     }
1567   }
1568 
1569   tables_->FindAllExtensions(extendee, out);
1570   if (underlay_ != nullptr) {
1571     underlay_->FindAllExtensions(extendee, out);
1572   }
1573 }
1574 
1575 
1576 // -------------------------------------------------------------------
1577 
FindFieldByNumber(int key) const1578 const FieldDescriptor* Descriptor::FindFieldByNumber(int key) const {
1579   const FieldDescriptor* result = file()->tables_->FindFieldByNumber(this, key);
1580   if (result == nullptr || result->is_extension()) {
1581     return nullptr;
1582   } else {
1583     return result;
1584   }
1585 }
1586 
FindFieldByLowercaseName(ConstStringParam key) const1587 const FieldDescriptor* Descriptor::FindFieldByLowercaseName(
1588     ConstStringParam key) const {
1589   const FieldDescriptor* result =
1590       file()->tables_->FindFieldByLowercaseName(this, key);
1591   if (result == nullptr || result->is_extension()) {
1592     return nullptr;
1593   } else {
1594     return result;
1595   }
1596 }
1597 
FindFieldByCamelcaseName(ConstStringParam key) const1598 const FieldDescriptor* Descriptor::FindFieldByCamelcaseName(
1599     ConstStringParam key) const {
1600   const FieldDescriptor* result =
1601       file()->tables_->FindFieldByCamelcaseName(this, key);
1602   if (result == nullptr || result->is_extension()) {
1603     return nullptr;
1604   } else {
1605     return result;
1606   }
1607 }
1608 
FindFieldByName(ConstStringParam key) const1609 const FieldDescriptor* Descriptor::FindFieldByName(ConstStringParam key) const {
1610   Symbol result =
1611       file()->tables_->FindNestedSymbolOfType(this, key, Symbol::FIELD);
1612   if (!result.IsNull() && !result.field_descriptor->is_extension()) {
1613     return result.field_descriptor;
1614   } else {
1615     return nullptr;
1616   }
1617 }
1618 
FindOneofByName(ConstStringParam key) const1619 const OneofDescriptor* Descriptor::FindOneofByName(ConstStringParam key) const {
1620   Symbol result =
1621       file()->tables_->FindNestedSymbolOfType(this, key, Symbol::ONEOF);
1622   if (!result.IsNull()) {
1623     return result.oneof_descriptor;
1624   } else {
1625     return nullptr;
1626   }
1627 }
1628 
FindExtensionByName(ConstStringParam key) const1629 const FieldDescriptor* Descriptor::FindExtensionByName(
1630     ConstStringParam key) const {
1631   Symbol result =
1632       file()->tables_->FindNestedSymbolOfType(this, key, Symbol::FIELD);
1633   if (!result.IsNull() && result.field_descriptor->is_extension()) {
1634     return result.field_descriptor;
1635   } else {
1636     return nullptr;
1637   }
1638 }
1639 
FindExtensionByLowercaseName(ConstStringParam key) const1640 const FieldDescriptor* Descriptor::FindExtensionByLowercaseName(
1641     ConstStringParam key) const {
1642   const FieldDescriptor* result =
1643       file()->tables_->FindFieldByLowercaseName(this, key);
1644   if (result == nullptr || !result->is_extension()) {
1645     return nullptr;
1646   } else {
1647     return result;
1648   }
1649 }
1650 
FindExtensionByCamelcaseName(ConstStringParam key) const1651 const FieldDescriptor* Descriptor::FindExtensionByCamelcaseName(
1652     ConstStringParam key) const {
1653   const FieldDescriptor* result =
1654       file()->tables_->FindFieldByCamelcaseName(this, key);
1655   if (result == nullptr || !result->is_extension()) {
1656     return nullptr;
1657   } else {
1658     return result;
1659   }
1660 }
1661 
FindNestedTypeByName(ConstStringParam key) const1662 const Descriptor* Descriptor::FindNestedTypeByName(ConstStringParam key) const {
1663   Symbol result =
1664       file()->tables_->FindNestedSymbolOfType(this, key, Symbol::MESSAGE);
1665   if (!result.IsNull()) {
1666     return result.descriptor;
1667   } else {
1668     return nullptr;
1669   }
1670 }
1671 
FindEnumTypeByName(ConstStringParam key) const1672 const EnumDescriptor* Descriptor::FindEnumTypeByName(
1673     ConstStringParam key) const {
1674   Symbol result =
1675       file()->tables_->FindNestedSymbolOfType(this, key, Symbol::ENUM);
1676   if (!result.IsNull()) {
1677     return result.enum_descriptor;
1678   } else {
1679     return nullptr;
1680   }
1681 }
1682 
FindEnumValueByName(ConstStringParam key) const1683 const EnumValueDescriptor* Descriptor::FindEnumValueByName(
1684     ConstStringParam key) const {
1685   Symbol result =
1686       file()->tables_->FindNestedSymbolOfType(this, key, Symbol::ENUM_VALUE);
1687   if (!result.IsNull()) {
1688     return result.enum_value_descriptor;
1689   } else {
1690     return nullptr;
1691   }
1692 }
1693 
map_key() const1694 const FieldDescriptor* Descriptor::map_key() const {
1695   if (!options().map_entry()) return nullptr;
1696   GOOGLE_DCHECK_EQ(field_count(), 2);
1697   return field(0);
1698 }
1699 
map_value() const1700 const FieldDescriptor* Descriptor::map_value() const {
1701   if (!options().map_entry()) return nullptr;
1702   GOOGLE_DCHECK_EQ(field_count(), 2);
1703   return field(1);
1704 }
1705 
FindValueByName(ConstStringParam key) const1706 const EnumValueDescriptor* EnumDescriptor::FindValueByName(
1707     ConstStringParam key) const {
1708   Symbol result =
1709       file()->tables_->FindNestedSymbolOfType(this, key, Symbol::ENUM_VALUE);
1710   if (!result.IsNull()) {
1711     return result.enum_value_descriptor;
1712   } else {
1713     return nullptr;
1714   }
1715 }
1716 
FindValueByNumber(int key) const1717 const EnumValueDescriptor* EnumDescriptor::FindValueByNumber(int key) const {
1718   return file()->tables_->FindEnumValueByNumber(this, key);
1719 }
1720 
FindValueByNumberCreatingIfUnknown(int key) const1721 const EnumValueDescriptor* EnumDescriptor::FindValueByNumberCreatingIfUnknown(
1722     int key) const {
1723   return file()->tables_->FindEnumValueByNumberCreatingIfUnknown(this, key);
1724 }
1725 
FindMethodByName(ConstStringParam key) const1726 const MethodDescriptor* ServiceDescriptor::FindMethodByName(
1727     ConstStringParam key) const {
1728   Symbol result =
1729       file()->tables_->FindNestedSymbolOfType(this, key, Symbol::METHOD);
1730   if (!result.IsNull()) {
1731     return result.method_descriptor;
1732   } else {
1733     return nullptr;
1734   }
1735 }
1736 
FindMessageTypeByName(ConstStringParam key) const1737 const Descriptor* FileDescriptor::FindMessageTypeByName(
1738     ConstStringParam key) const {
1739   Symbol result = tables_->FindNestedSymbolOfType(this, key, Symbol::MESSAGE);
1740   if (!result.IsNull()) {
1741     return result.descriptor;
1742   } else {
1743     return nullptr;
1744   }
1745 }
1746 
FindEnumTypeByName(ConstStringParam key) const1747 const EnumDescriptor* FileDescriptor::FindEnumTypeByName(
1748     ConstStringParam key) const {
1749   Symbol result = tables_->FindNestedSymbolOfType(this, key, Symbol::ENUM);
1750   if (!result.IsNull()) {
1751     return result.enum_descriptor;
1752   } else {
1753     return nullptr;
1754   }
1755 }
1756 
FindEnumValueByName(ConstStringParam key) const1757 const EnumValueDescriptor* FileDescriptor::FindEnumValueByName(
1758     ConstStringParam key) const {
1759   Symbol result =
1760       tables_->FindNestedSymbolOfType(this, key, Symbol::ENUM_VALUE);
1761   if (!result.IsNull()) {
1762     return result.enum_value_descriptor;
1763   } else {
1764     return nullptr;
1765   }
1766 }
1767 
FindServiceByName(ConstStringParam key) const1768 const ServiceDescriptor* FileDescriptor::FindServiceByName(
1769     ConstStringParam key) const {
1770   Symbol result = tables_->FindNestedSymbolOfType(this, key, Symbol::SERVICE);
1771   if (!result.IsNull()) {
1772     return result.service_descriptor;
1773   } else {
1774     return nullptr;
1775   }
1776 }
1777 
FindExtensionByName(ConstStringParam key) const1778 const FieldDescriptor* FileDescriptor::FindExtensionByName(
1779     ConstStringParam key) const {
1780   Symbol result = tables_->FindNestedSymbolOfType(this, key, Symbol::FIELD);
1781   if (!result.IsNull() && result.field_descriptor->is_extension()) {
1782     return result.field_descriptor;
1783   } else {
1784     return nullptr;
1785   }
1786 }
1787 
FindExtensionByLowercaseName(ConstStringParam key) const1788 const FieldDescriptor* FileDescriptor::FindExtensionByLowercaseName(
1789     ConstStringParam key) const {
1790   const FieldDescriptor* result = tables_->FindFieldByLowercaseName(this, key);
1791   if (result == nullptr || !result->is_extension()) {
1792     return nullptr;
1793   } else {
1794     return result;
1795   }
1796 }
1797 
FindExtensionByCamelcaseName(ConstStringParam key) const1798 const FieldDescriptor* FileDescriptor::FindExtensionByCamelcaseName(
1799     ConstStringParam key) const {
1800   const FieldDescriptor* result = tables_->FindFieldByCamelcaseName(this, key);
1801   if (result == nullptr || !result->is_extension()) {
1802     return nullptr;
1803   } else {
1804     return result;
1805   }
1806 }
1807 
CopyTo(DescriptorProto_ExtensionRange * proto) const1808 void Descriptor::ExtensionRange::CopyTo(
1809     DescriptorProto_ExtensionRange* proto) const {
1810   proto->set_start(this->start);
1811   proto->set_end(this->end);
1812   if (options_ != &ExtensionRangeOptions::default_instance()) {
1813     *proto->mutable_options() = *options_;
1814   }
1815 }
1816 
1817 const Descriptor::ExtensionRange*
FindExtensionRangeContainingNumber(int number) const1818 Descriptor::FindExtensionRangeContainingNumber(int number) const {
1819   // Linear search should be fine because we don't expect a message to have
1820   // more than a couple extension ranges.
1821   for (int i = 0; i < extension_range_count(); i++) {
1822     if (number >= extension_range(i)->start &&
1823         number < extension_range(i)->end) {
1824       return extension_range(i);
1825     }
1826   }
1827   return nullptr;
1828 }
1829 
FindReservedRangeContainingNumber(int number) const1830 const Descriptor::ReservedRange* Descriptor::FindReservedRangeContainingNumber(
1831     int number) const {
1832   // TODO(chrisn): Consider a non-linear search.
1833   for (int i = 0; i < reserved_range_count(); i++) {
1834     if (number >= reserved_range(i)->start && number < reserved_range(i)->end) {
1835       return reserved_range(i);
1836     }
1837   }
1838   return nullptr;
1839 }
1840 
1841 const EnumDescriptor::ReservedRange*
FindReservedRangeContainingNumber(int number) const1842 EnumDescriptor::FindReservedRangeContainingNumber(int number) const {
1843   // TODO(chrisn): Consider a non-linear search.
1844   for (int i = 0; i < reserved_range_count(); i++) {
1845     if (number >= reserved_range(i)->start &&
1846         number <= reserved_range(i)->end) {
1847       return reserved_range(i);
1848     }
1849   }
1850   return nullptr;
1851 }
1852 
1853 // -------------------------------------------------------------------
1854 
TryFindFileInFallbackDatabase(StringPiece name) const1855 bool DescriptorPool::TryFindFileInFallbackDatabase(
1856     StringPiece name) const {
1857   if (fallback_database_ == nullptr) return false;
1858 
1859   auto name_string = std::string(name);
1860   if (tables_->known_bad_files_.count(name_string) > 0) return false;
1861 
1862   FileDescriptorProto file_proto;
1863   if (!fallback_database_->FindFileByName(name_string, &file_proto) ||
1864       BuildFileFromDatabase(file_proto) == nullptr) {
1865     tables_->known_bad_files_.insert(std::move(name_string));
1866     return false;
1867   }
1868   return true;
1869 }
1870 
IsSubSymbolOfBuiltType(StringPiece name) const1871 bool DescriptorPool::IsSubSymbolOfBuiltType(StringPiece name) const {
1872   auto prefix = std::string(name);
1873   for (;;) {
1874     std::string::size_type dot_pos = prefix.find_last_of('.');
1875     if (dot_pos == std::string::npos) {
1876       break;
1877     }
1878     prefix = prefix.substr(0, dot_pos);
1879     Symbol symbol = tables_->FindSymbol(prefix);
1880     // If the symbol type is anything other than PACKAGE, then its complete
1881     // definition is already known.
1882     if (!symbol.IsNull() && symbol.type != Symbol::PACKAGE) {
1883       return true;
1884     }
1885   }
1886   if (underlay_ != nullptr) {
1887     // Check to see if any prefix of this symbol exists in the underlay.
1888     return underlay_->IsSubSymbolOfBuiltType(name);
1889   }
1890   return false;
1891 }
1892 
TryFindSymbolInFallbackDatabase(StringPiece name) const1893 bool DescriptorPool::TryFindSymbolInFallbackDatabase(
1894     StringPiece name) const {
1895   if (fallback_database_ == nullptr) return false;
1896 
1897   auto name_string = std::string(name);
1898   if (tables_->known_bad_symbols_.count(name_string) > 0) return false;
1899 
1900   FileDescriptorProto file_proto;
1901   if (  // We skip looking in the fallback database if the name is a sub-symbol
1902         // of any descriptor that already exists in the descriptor pool (except
1903         // for package descriptors).  This is valid because all symbols except
1904         // for packages are defined in a single file, so if the symbol exists
1905         // then we should already have its definition.
1906         //
1907         // The other reason to do this is to support "overriding" type
1908         // definitions by merging two databases that define the same type. (Yes,
1909         // people do this.)  The main difficulty with making this work is that
1910         // FindFileContainingSymbol() is allowed to return both false positives
1911         // (e.g., SimpleDescriptorDatabase, UpgradedDescriptorDatabase) and
1912         // false negatives (e.g. ProtoFileParser, SourceTreeDescriptorDatabase).
1913         // When two such databases are merged, looking up a non-existent
1914         // sub-symbol of a type that already exists in the descriptor pool can
1915         // result in an attempt to load multiple definitions of the same type.
1916         // The check below avoids this.
1917       IsSubSymbolOfBuiltType(name)
1918 
1919       // Look up file containing this symbol in fallback database.
1920       || !fallback_database_->FindFileContainingSymbol(name_string, &file_proto)
1921 
1922       // Check if we've already built this file. If so, it apparently doesn't
1923       // contain the symbol we're looking for.  Some DescriptorDatabases
1924       // return false positives.
1925       || tables_->FindFile(file_proto.name()) != nullptr
1926 
1927       // Build the file.
1928       || BuildFileFromDatabase(file_proto) == nullptr) {
1929     tables_->known_bad_symbols_.insert(std::move(name_string));
1930     return false;
1931   }
1932 
1933   return true;
1934 }
1935 
TryFindExtensionInFallbackDatabase(const Descriptor * containing_type,int field_number) const1936 bool DescriptorPool::TryFindExtensionInFallbackDatabase(
1937     const Descriptor* containing_type, int field_number) const {
1938   if (fallback_database_ == nullptr) return false;
1939 
1940   FileDescriptorProto file_proto;
1941   if (!fallback_database_->FindFileContainingExtension(
1942           containing_type->full_name(), field_number, &file_proto)) {
1943     return false;
1944   }
1945 
1946   if (tables_->FindFile(file_proto.name()) != nullptr) {
1947     // We've already loaded this file, and it apparently doesn't contain the
1948     // extension we're looking for.  Some DescriptorDatabases return false
1949     // positives.
1950     return false;
1951   }
1952 
1953   if (BuildFileFromDatabase(file_proto) == nullptr) {
1954     return false;
1955   }
1956 
1957   return true;
1958 }
1959 
1960 // ===================================================================
1961 
is_map_message_type() const1962 bool FieldDescriptor::is_map_message_type() const {
1963   return message_type_->options().map_entry();
1964 }
1965 
DefaultValueAsString(bool quote_string_type) const1966 std::string FieldDescriptor::DefaultValueAsString(
1967     bool quote_string_type) const {
1968   GOOGLE_CHECK(has_default_value()) << "No default value";
1969   switch (cpp_type()) {
1970     case CPPTYPE_INT32:
1971       return StrCat(default_value_int32());
1972       break;
1973     case CPPTYPE_INT64:
1974       return StrCat(default_value_int64());
1975       break;
1976     case CPPTYPE_UINT32:
1977       return StrCat(default_value_uint32());
1978       break;
1979     case CPPTYPE_UINT64:
1980       return StrCat(default_value_uint64());
1981       break;
1982     case CPPTYPE_FLOAT:
1983       return SimpleFtoa(default_value_float());
1984       break;
1985     case CPPTYPE_DOUBLE:
1986       return SimpleDtoa(default_value_double());
1987       break;
1988     case CPPTYPE_BOOL:
1989       return default_value_bool() ? "true" : "false";
1990       break;
1991     case CPPTYPE_STRING:
1992       if (quote_string_type) {
1993         return "\"" + CEscape(default_value_string()) + "\"";
1994       } else {
1995         if (type() == TYPE_BYTES) {
1996           return CEscape(default_value_string());
1997         } else {
1998           return default_value_string();
1999         }
2000       }
2001       break;
2002     case CPPTYPE_ENUM:
2003       return default_value_enum()->name();
2004       break;
2005     case CPPTYPE_MESSAGE:
2006       GOOGLE_LOG(DFATAL) << "Messages can't have default values!";
2007       break;
2008   }
2009   GOOGLE_LOG(FATAL) << "Can't get here: failed to get default value as string";
2010   return "";
2011 }
2012 
2013 // CopyTo methods ====================================================
2014 
CopyTo(FileDescriptorProto * proto) const2015 void FileDescriptor::CopyTo(FileDescriptorProto* proto) const {
2016   proto->set_name(name());
2017   if (!package().empty()) proto->set_package(package());
2018   // TODO(liujisi): Also populate when syntax="proto2".
2019   if (syntax() == SYNTAX_PROTO3) proto->set_syntax(SyntaxName(syntax()));
2020 
2021   for (int i = 0; i < dependency_count(); i++) {
2022     proto->add_dependency(dependency(i)->name());
2023   }
2024 
2025   for (int i = 0; i < public_dependency_count(); i++) {
2026     proto->add_public_dependency(public_dependencies_[i]);
2027   }
2028 
2029   for (int i = 0; i < weak_dependency_count(); i++) {
2030     proto->add_weak_dependency(weak_dependencies_[i]);
2031   }
2032 
2033   for (int i = 0; i < message_type_count(); i++) {
2034     message_type(i)->CopyTo(proto->add_message_type());
2035   }
2036   for (int i = 0; i < enum_type_count(); i++) {
2037     enum_type(i)->CopyTo(proto->add_enum_type());
2038   }
2039   for (int i = 0; i < service_count(); i++) {
2040     service(i)->CopyTo(proto->add_service());
2041   }
2042   for (int i = 0; i < extension_count(); i++) {
2043     extension(i)->CopyTo(proto->add_extension());
2044   }
2045 
2046   if (&options() != &FileOptions::default_instance()) {
2047     proto->mutable_options()->CopyFrom(options());
2048   }
2049 }
2050 
CopyJsonNameTo(FileDescriptorProto * proto) const2051 void FileDescriptor::CopyJsonNameTo(FileDescriptorProto* proto) const {
2052   if (message_type_count() != proto->message_type_size() ||
2053       extension_count() != proto->extension_size()) {
2054     GOOGLE_LOG(ERROR) << "Cannot copy json_name to a proto of a different size.";
2055     return;
2056   }
2057   for (int i = 0; i < message_type_count(); i++) {
2058     message_type(i)->CopyJsonNameTo(proto->mutable_message_type(i));
2059   }
2060   for (int i = 0; i < extension_count(); i++) {
2061     extension(i)->CopyJsonNameTo(proto->mutable_extension(i));
2062   }
2063 }
2064 
CopySourceCodeInfoTo(FileDescriptorProto * proto) const2065 void FileDescriptor::CopySourceCodeInfoTo(FileDescriptorProto* proto) const {
2066   if (source_code_info_ &&
2067       source_code_info_ != &SourceCodeInfo::default_instance()) {
2068     proto->mutable_source_code_info()->CopyFrom(*source_code_info_);
2069   }
2070 }
2071 
CopyTo(DescriptorProto * proto) const2072 void Descriptor::CopyTo(DescriptorProto* proto) const {
2073   proto->set_name(name());
2074 
2075   for (int i = 0; i < field_count(); i++) {
2076     field(i)->CopyTo(proto->add_field());
2077   }
2078   for (int i = 0; i < oneof_decl_count(); i++) {
2079     oneof_decl(i)->CopyTo(proto->add_oneof_decl());
2080   }
2081   for (int i = 0; i < nested_type_count(); i++) {
2082     nested_type(i)->CopyTo(proto->add_nested_type());
2083   }
2084   for (int i = 0; i < enum_type_count(); i++) {
2085     enum_type(i)->CopyTo(proto->add_enum_type());
2086   }
2087   for (int i = 0; i < extension_range_count(); i++) {
2088     extension_range(i)->CopyTo(proto->add_extension_range());
2089   }
2090   for (int i = 0; i < extension_count(); i++) {
2091     extension(i)->CopyTo(proto->add_extension());
2092   }
2093   for (int i = 0; i < reserved_range_count(); i++) {
2094     DescriptorProto::ReservedRange* range = proto->add_reserved_range();
2095     range->set_start(reserved_range(i)->start);
2096     range->set_end(reserved_range(i)->end);
2097   }
2098   for (int i = 0; i < reserved_name_count(); i++) {
2099     proto->add_reserved_name(reserved_name(i));
2100   }
2101 
2102   if (&options() != &MessageOptions::default_instance()) {
2103     proto->mutable_options()->CopyFrom(options());
2104   }
2105 }
2106 
CopyJsonNameTo(DescriptorProto * proto) const2107 void Descriptor::CopyJsonNameTo(DescriptorProto* proto) const {
2108   if (field_count() != proto->field_size() ||
2109       nested_type_count() != proto->nested_type_size() ||
2110       extension_count() != proto->extension_size()) {
2111     GOOGLE_LOG(ERROR) << "Cannot copy json_name to a proto of a different size.";
2112     return;
2113   }
2114   for (int i = 0; i < field_count(); i++) {
2115     field(i)->CopyJsonNameTo(proto->mutable_field(i));
2116   }
2117   for (int i = 0; i < nested_type_count(); i++) {
2118     nested_type(i)->CopyJsonNameTo(proto->mutable_nested_type(i));
2119   }
2120   for (int i = 0; i < extension_count(); i++) {
2121     extension(i)->CopyJsonNameTo(proto->mutable_extension(i));
2122   }
2123 }
2124 
CopyTo(FieldDescriptorProto * proto) const2125 void FieldDescriptor::CopyTo(FieldDescriptorProto* proto) const {
2126   proto->set_name(name());
2127   proto->set_number(number());
2128   if (has_json_name_) {
2129     proto->set_json_name(json_name());
2130   }
2131   if (proto3_optional_) {
2132     proto->set_proto3_optional(true);
2133   }
2134   // Some compilers do not allow static_cast directly between two enum types,
2135   // so we must cast to int first.
2136   proto->set_label(static_cast<FieldDescriptorProto::Label>(
2137       implicit_cast<int>(label())));
2138   proto->set_type(static_cast<FieldDescriptorProto::Type>(
2139       implicit_cast<int>(type())));
2140 
2141   if (is_extension()) {
2142     if (!containing_type()->is_unqualified_placeholder_) {
2143       proto->set_extendee(".");
2144     }
2145     proto->mutable_extendee()->append(containing_type()->full_name());
2146   }
2147 
2148   if (cpp_type() == CPPTYPE_MESSAGE) {
2149     if (message_type()->is_placeholder_) {
2150       // We don't actually know if the type is a message type.  It could be
2151       // an enum.
2152       proto->clear_type();
2153     }
2154 
2155     if (!message_type()->is_unqualified_placeholder_) {
2156       proto->set_type_name(".");
2157     }
2158     proto->mutable_type_name()->append(message_type()->full_name());
2159   } else if (cpp_type() == CPPTYPE_ENUM) {
2160     if (!enum_type()->is_unqualified_placeholder_) {
2161       proto->set_type_name(".");
2162     }
2163     proto->mutable_type_name()->append(enum_type()->full_name());
2164   }
2165 
2166   if (has_default_value()) {
2167     proto->set_default_value(DefaultValueAsString(false));
2168   }
2169 
2170   if (containing_oneof() != nullptr && !is_extension()) {
2171     proto->set_oneof_index(containing_oneof()->index());
2172   }
2173 
2174   if (&options() != &FieldOptions::default_instance()) {
2175     proto->mutable_options()->CopyFrom(options());
2176   }
2177 }
2178 
CopyJsonNameTo(FieldDescriptorProto * proto) const2179 void FieldDescriptor::CopyJsonNameTo(FieldDescriptorProto* proto) const {
2180   proto->set_json_name(json_name());
2181 }
2182 
CopyTo(OneofDescriptorProto * proto) const2183 void OneofDescriptor::CopyTo(OneofDescriptorProto* proto) const {
2184   proto->set_name(name());
2185   if (&options() != &OneofOptions::default_instance()) {
2186     proto->mutable_options()->CopyFrom(options());
2187   }
2188 }
2189 
CopyTo(EnumDescriptorProto * proto) const2190 void EnumDescriptor::CopyTo(EnumDescriptorProto* proto) const {
2191   proto->set_name(name());
2192 
2193   for (int i = 0; i < value_count(); i++) {
2194     value(i)->CopyTo(proto->add_value());
2195   }
2196   for (int i = 0; i < reserved_range_count(); i++) {
2197     EnumDescriptorProto::EnumReservedRange* range = proto->add_reserved_range();
2198     range->set_start(reserved_range(i)->start);
2199     range->set_end(reserved_range(i)->end);
2200   }
2201   for (int i = 0; i < reserved_name_count(); i++) {
2202     proto->add_reserved_name(reserved_name(i));
2203   }
2204 
2205   if (&options() != &EnumOptions::default_instance()) {
2206     proto->mutable_options()->CopyFrom(options());
2207   }
2208 }
2209 
CopyTo(EnumValueDescriptorProto * proto) const2210 void EnumValueDescriptor::CopyTo(EnumValueDescriptorProto* proto) const {
2211   proto->set_name(name());
2212   proto->set_number(number());
2213 
2214   if (&options() != &EnumValueOptions::default_instance()) {
2215     proto->mutable_options()->CopyFrom(options());
2216   }
2217 }
2218 
CopyTo(ServiceDescriptorProto * proto) const2219 void ServiceDescriptor::CopyTo(ServiceDescriptorProto* proto) const {
2220   proto->set_name(name());
2221 
2222   for (int i = 0; i < method_count(); i++) {
2223     method(i)->CopyTo(proto->add_method());
2224   }
2225 
2226   if (&options() != &ServiceOptions::default_instance()) {
2227     proto->mutable_options()->CopyFrom(options());
2228   }
2229 }
2230 
CopyTo(MethodDescriptorProto * proto) const2231 void MethodDescriptor::CopyTo(MethodDescriptorProto* proto) const {
2232   proto->set_name(name());
2233 
2234   if (!input_type()->is_unqualified_placeholder_) {
2235     proto->set_input_type(".");
2236   }
2237   proto->mutable_input_type()->append(input_type()->full_name());
2238 
2239   if (!output_type()->is_unqualified_placeholder_) {
2240     proto->set_output_type(".");
2241   }
2242   proto->mutable_output_type()->append(output_type()->full_name());
2243 
2244   if (&options() != &MethodOptions::default_instance()) {
2245     proto->mutable_options()->CopyFrom(options());
2246   }
2247 
2248   if (client_streaming_) {
2249     proto->set_client_streaming(true);
2250   }
2251   if (server_streaming_) {
2252     proto->set_server_streaming(true);
2253   }
2254 }
2255 
2256 // DebugString methods ===============================================
2257 
2258 namespace {
2259 
RetrieveOptionsAssumingRightPool(int depth,const Message & options,std::vector<std::string> * option_entries)2260 bool RetrieveOptionsAssumingRightPool(
2261     int depth, const Message& options,
2262     std::vector<std::string>* option_entries) {
2263   option_entries->clear();
2264   const Reflection* reflection = options.GetReflection();
2265   std::vector<const FieldDescriptor*> fields;
2266   reflection->ListFields(options, &fields);
2267   for (const FieldDescriptor* field : fields) {
2268     int count = 1;
2269     bool repeated = false;
2270     if (field->is_repeated()) {
2271       count = reflection->FieldSize(options, field);
2272       repeated = true;
2273     }
2274     for (int j = 0; j < count; j++) {
2275       std::string fieldval;
2276       if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
2277         std::string tmp;
2278         TextFormat::Printer printer;
2279         printer.SetInitialIndentLevel(depth + 1);
2280         printer.PrintFieldValueToString(options, field, repeated ? j : -1,
2281                                         &tmp);
2282         fieldval.append("{\n");
2283         fieldval.append(tmp);
2284         fieldval.append(depth * 2, ' ');
2285         fieldval.append("}");
2286       } else {
2287         TextFormat::PrintFieldValueToString(options, field, repeated ? j : -1,
2288                                             &fieldval);
2289       }
2290       std::string name;
2291       if (field->is_extension()) {
2292         name = "(." + field->full_name() + ")";
2293       } else {
2294         name = field->name();
2295       }
2296       option_entries->push_back(name + " = " + fieldval);
2297     }
2298   }
2299   return !option_entries->empty();
2300 }
2301 
2302 // Used by each of the option formatters.
RetrieveOptions(int depth,const Message & options,const DescriptorPool * pool,std::vector<std::string> * option_entries)2303 bool RetrieveOptions(int depth, const Message& options,
2304                      const DescriptorPool* pool,
2305                      std::vector<std::string>* option_entries) {
2306   // When printing custom options for a descriptor, we must use an options
2307   // message built on top of the same DescriptorPool where the descriptor
2308   // is coming from. This is to ensure we are interpreting custom options
2309   // against the right pool.
2310   if (options.GetDescriptor()->file()->pool() == pool) {
2311     return RetrieveOptionsAssumingRightPool(depth, options, option_entries);
2312   } else {
2313     const Descriptor* option_descriptor =
2314         pool->FindMessageTypeByName(options.GetDescriptor()->full_name());
2315     if (option_descriptor == nullptr) {
2316       // descriptor.proto is not in the pool. This means no custom options are
2317       // used so we are safe to proceed with the compiled options message type.
2318       return RetrieveOptionsAssumingRightPool(depth, options, option_entries);
2319     }
2320     DynamicMessageFactory factory;
2321     std::unique_ptr<Message> dynamic_options(
2322         factory.GetPrototype(option_descriptor)->New());
2323     if (dynamic_options->ParseFromString(options.SerializeAsString())) {
2324       return RetrieveOptionsAssumingRightPool(depth, *dynamic_options,
2325                                               option_entries);
2326     } else {
2327       GOOGLE_LOG(ERROR) << "Found invalid proto option data for: "
2328                  << options.GetDescriptor()->full_name();
2329       return RetrieveOptionsAssumingRightPool(depth, options, option_entries);
2330     }
2331   }
2332 }
2333 
2334 // Formats options that all appear together in brackets. Does not include
2335 // brackets.
FormatBracketedOptions(int depth,const Message & options,const DescriptorPool * pool,std::string * output)2336 bool FormatBracketedOptions(int depth, const Message& options,
2337                             const DescriptorPool* pool, std::string* output) {
2338   std::vector<std::string> all_options;
2339   if (RetrieveOptions(depth, options, pool, &all_options)) {
2340     output->append(Join(all_options, ", "));
2341   }
2342   return !all_options.empty();
2343 }
2344 
2345 // Formats options one per line
FormatLineOptions(int depth,const Message & options,const DescriptorPool * pool,std::string * output)2346 bool FormatLineOptions(int depth, const Message& options,
2347                        const DescriptorPool* pool, std::string* output) {
2348   std::string prefix(depth * 2, ' ');
2349   std::vector<std::string> all_options;
2350   if (RetrieveOptions(depth, options, pool, &all_options)) {
2351     for (const std::string& option : all_options) {
2352       strings::SubstituteAndAppend(output, "$0option $1;\n", prefix, option);
2353     }
2354   }
2355   return !all_options.empty();
2356 }
2357 
2358 class SourceLocationCommentPrinter {
2359  public:
2360   template <typename DescType>
SourceLocationCommentPrinter(const DescType * desc,const std::string & prefix,const DebugStringOptions & options)2361   SourceLocationCommentPrinter(const DescType* desc, const std::string& prefix,
2362                                const DebugStringOptions& options)
2363       : options_(options), prefix_(prefix) {
2364     // Perform the SourceLocation lookup only if we're including user comments,
2365     // because the lookup is fairly expensive.
2366     have_source_loc_ =
2367         options.include_comments && desc->GetSourceLocation(&source_loc_);
2368   }
SourceLocationCommentPrinter(const FileDescriptor * file,const std::vector<int> & path,const std::string & prefix,const DebugStringOptions & options)2369   SourceLocationCommentPrinter(const FileDescriptor* file,
2370                                const std::vector<int>& path,
2371                                const std::string& prefix,
2372                                const DebugStringOptions& options)
2373       : options_(options), prefix_(prefix) {
2374     // Perform the SourceLocation lookup only if we're including user comments,
2375     // because the lookup is fairly expensive.
2376     have_source_loc_ =
2377         options.include_comments && file->GetSourceLocation(path, &source_loc_);
2378   }
AddPreComment(std::string * output)2379   void AddPreComment(std::string* output) {
2380     if (have_source_loc_) {
2381       // Detached leading comments.
2382       for (const std::string& leading_detached_comment :
2383            source_loc_.leading_detached_comments) {
2384         *output += FormatComment(leading_detached_comment);
2385         *output += "\n";
2386       }
2387       // Attached leading comments.
2388       if (!source_loc_.leading_comments.empty()) {
2389         *output += FormatComment(source_loc_.leading_comments);
2390       }
2391     }
2392   }
AddPostComment(std::string * output)2393   void AddPostComment(std::string* output) {
2394     if (have_source_loc_ && source_loc_.trailing_comments.size() > 0) {
2395       *output += FormatComment(source_loc_.trailing_comments);
2396     }
2397   }
2398 
2399   // Format comment such that each line becomes a full-line C++-style comment in
2400   // the DebugString() output.
FormatComment(const std::string & comment_text)2401   std::string FormatComment(const std::string& comment_text) {
2402     std::string stripped_comment = comment_text;
2403     StripWhitespace(&stripped_comment);
2404     std::vector<std::string> lines = Split(stripped_comment, "\n");
2405     std::string output;
2406     for (const std::string& line : lines) {
2407       strings::SubstituteAndAppend(&output, "$0// $1\n", prefix_, line);
2408     }
2409     return output;
2410   }
2411 
2412  private:
2413 
2414   bool have_source_loc_;
2415   SourceLocation source_loc_;
2416   DebugStringOptions options_;
2417   std::string prefix_;
2418 };
2419 
2420 }  // anonymous namespace
2421 
DebugString() const2422 std::string FileDescriptor::DebugString() const {
2423   DebugStringOptions options;  // default options
2424   return DebugStringWithOptions(options);
2425 }
2426 
DebugStringWithOptions(const DebugStringOptions & debug_string_options) const2427 std::string FileDescriptor::DebugStringWithOptions(
2428     const DebugStringOptions& debug_string_options) const {
2429   std::string contents;
2430   {
2431     std::vector<int> path;
2432     path.push_back(FileDescriptorProto::kSyntaxFieldNumber);
2433     SourceLocationCommentPrinter syntax_comment(this, path, "",
2434                                                 debug_string_options);
2435     syntax_comment.AddPreComment(&contents);
2436     strings::SubstituteAndAppend(&contents, "syntax = \"$0\";\n\n",
2437                               SyntaxName(syntax()));
2438     syntax_comment.AddPostComment(&contents);
2439   }
2440 
2441   SourceLocationCommentPrinter comment_printer(this, "", debug_string_options);
2442   comment_printer.AddPreComment(&contents);
2443 
2444   std::set<int> public_dependencies;
2445   std::set<int> weak_dependencies;
2446   public_dependencies.insert(public_dependencies_,
2447                              public_dependencies_ + public_dependency_count_);
2448   weak_dependencies.insert(weak_dependencies_,
2449                            weak_dependencies_ + weak_dependency_count_);
2450 
2451   for (int i = 0; i < dependency_count(); i++) {
2452     if (public_dependencies.count(i) > 0) {
2453       strings::SubstituteAndAppend(&contents, "import public \"$0\";\n",
2454                                 dependency(i)->name());
2455     } else if (weak_dependencies.count(i) > 0) {
2456       strings::SubstituteAndAppend(&contents, "import weak \"$0\";\n",
2457                                 dependency(i)->name());
2458     } else {
2459       strings::SubstituteAndAppend(&contents, "import \"$0\";\n",
2460                                 dependency(i)->name());
2461     }
2462   }
2463 
2464   if (!package().empty()) {
2465     std::vector<int> path;
2466     path.push_back(FileDescriptorProto::kPackageFieldNumber);
2467     SourceLocationCommentPrinter package_comment(this, path, "",
2468                                                  debug_string_options);
2469     package_comment.AddPreComment(&contents);
2470     strings::SubstituteAndAppend(&contents, "package $0;\n\n", package());
2471     package_comment.AddPostComment(&contents);
2472   }
2473 
2474   if (FormatLineOptions(0, options(), pool(), &contents)) {
2475     contents.append("\n");  // add some space if we had options
2476   }
2477 
2478   for (int i = 0; i < enum_type_count(); i++) {
2479     enum_type(i)->DebugString(0, &contents, debug_string_options);
2480     contents.append("\n");
2481   }
2482 
2483   // Find all the 'group' type extensions; we will not output their nested
2484   // definitions (those will be done with their group field descriptor).
2485   std::set<const Descriptor*> groups;
2486   for (int i = 0; i < extension_count(); i++) {
2487     if (extension(i)->type() == FieldDescriptor::TYPE_GROUP) {
2488       groups.insert(extension(i)->message_type());
2489     }
2490   }
2491 
2492   for (int i = 0; i < message_type_count(); i++) {
2493     if (groups.count(message_type(i)) == 0) {
2494       message_type(i)->DebugString(0, &contents, debug_string_options,
2495                                    /* include_opening_clause */ true);
2496       contents.append("\n");
2497     }
2498   }
2499 
2500   for (int i = 0; i < service_count(); i++) {
2501     service(i)->DebugString(&contents, debug_string_options);
2502     contents.append("\n");
2503   }
2504 
2505   const Descriptor* containing_type = nullptr;
2506   for (int i = 0; i < extension_count(); i++) {
2507     if (extension(i)->containing_type() != containing_type) {
2508       if (i > 0) contents.append("}\n\n");
2509       containing_type = extension(i)->containing_type();
2510       strings::SubstituteAndAppend(&contents, "extend .$0 {\n",
2511                                 containing_type->full_name());
2512     }
2513     extension(i)->DebugString(1, &contents, debug_string_options);
2514   }
2515   if (extension_count() > 0) contents.append("}\n\n");
2516 
2517   comment_printer.AddPostComment(&contents);
2518 
2519   return contents;
2520 }
2521 
DebugString() const2522 std::string Descriptor::DebugString() const {
2523   DebugStringOptions options;  // default options
2524   return DebugStringWithOptions(options);
2525 }
2526 
DebugStringWithOptions(const DebugStringOptions & options) const2527 std::string Descriptor::DebugStringWithOptions(
2528     const DebugStringOptions& options) const {
2529   std::string contents;
2530   DebugString(0, &contents, options, /* include_opening_clause */ true);
2531   return contents;
2532 }
2533 
DebugString(int depth,std::string * contents,const DebugStringOptions & debug_string_options,bool include_opening_clause) const2534 void Descriptor::DebugString(int depth, std::string* contents,
2535                              const DebugStringOptions& debug_string_options,
2536                              bool include_opening_clause) const {
2537   if (options().map_entry()) {
2538     // Do not generate debug string for auto-generated map-entry type.
2539     return;
2540   }
2541   std::string prefix(depth * 2, ' ');
2542   ++depth;
2543 
2544   SourceLocationCommentPrinter comment_printer(this, prefix,
2545                                                debug_string_options);
2546   comment_printer.AddPreComment(contents);
2547 
2548   if (include_opening_clause) {
2549     strings::SubstituteAndAppend(contents, "$0message $1", prefix, name());
2550   }
2551   contents->append(" {\n");
2552 
2553   FormatLineOptions(depth, options(), file()->pool(), contents);
2554 
2555   // Find all the 'group' types for fields and extensions; we will not output
2556   // their nested definitions (those will be done with their group field
2557   // descriptor).
2558   std::set<const Descriptor*> groups;
2559   for (int i = 0; i < field_count(); i++) {
2560     if (field(i)->type() == FieldDescriptor::TYPE_GROUP) {
2561       groups.insert(field(i)->message_type());
2562     }
2563   }
2564   for (int i = 0; i < extension_count(); i++) {
2565     if (extension(i)->type() == FieldDescriptor::TYPE_GROUP) {
2566       groups.insert(extension(i)->message_type());
2567     }
2568   }
2569 
2570   for (int i = 0; i < nested_type_count(); i++) {
2571     if (groups.count(nested_type(i)) == 0) {
2572       nested_type(i)->DebugString(depth, contents, debug_string_options,
2573                                   /* include_opening_clause */ true);
2574     }
2575   }
2576   for (int i = 0; i < enum_type_count(); i++) {
2577     enum_type(i)->DebugString(depth, contents, debug_string_options);
2578   }
2579   for (int i = 0; i < field_count(); i++) {
2580     if (field(i)->real_containing_oneof() == nullptr) {
2581       field(i)->DebugString(depth, contents, debug_string_options);
2582     } else if (field(i)->containing_oneof()->field(0) == field(i)) {
2583       // This is the first field in this oneof, so print the whole oneof.
2584       field(i)->containing_oneof()->DebugString(depth, contents,
2585                                                 debug_string_options);
2586     }
2587   }
2588 
2589   for (int i = 0; i < extension_range_count(); i++) {
2590     strings::SubstituteAndAppend(contents, "$0  extensions $1 to $2;\n", prefix,
2591                               extension_range(i)->start,
2592                               extension_range(i)->end - 1);
2593   }
2594 
2595   // Group extensions by what they extend, so they can be printed out together.
2596   const Descriptor* containing_type = nullptr;
2597   for (int i = 0; i < extension_count(); i++) {
2598     if (extension(i)->containing_type() != containing_type) {
2599       if (i > 0) strings::SubstituteAndAppend(contents, "$0  }\n", prefix);
2600       containing_type = extension(i)->containing_type();
2601       strings::SubstituteAndAppend(contents, "$0  extend .$1 {\n", prefix,
2602                                 containing_type->full_name());
2603     }
2604     extension(i)->DebugString(depth + 1, contents, debug_string_options);
2605   }
2606   if (extension_count() > 0)
2607     strings::SubstituteAndAppend(contents, "$0  }\n", prefix);
2608 
2609   if (reserved_range_count() > 0) {
2610     strings::SubstituteAndAppend(contents, "$0  reserved ", prefix);
2611     for (int i = 0; i < reserved_range_count(); i++) {
2612       const Descriptor::ReservedRange* range = reserved_range(i);
2613       if (range->end == range->start + 1) {
2614         strings::SubstituteAndAppend(contents, "$0, ", range->start);
2615       } else if (range->end > FieldDescriptor::kMaxNumber) {
2616         strings::SubstituteAndAppend(contents, "$0 to max, ", range->start);
2617       } else {
2618         strings::SubstituteAndAppend(contents, "$0 to $1, ", range->start,
2619                                   range->end - 1);
2620       }
2621     }
2622     contents->replace(contents->size() - 2, 2, ";\n");
2623   }
2624 
2625   if (reserved_name_count() > 0) {
2626     strings::SubstituteAndAppend(contents, "$0  reserved ", prefix);
2627     for (int i = 0; i < reserved_name_count(); i++) {
2628       strings::SubstituteAndAppend(contents, "\"$0\", ",
2629                                 CEscape(reserved_name(i)));
2630     }
2631     contents->replace(contents->size() - 2, 2, ";\n");
2632   }
2633 
2634   strings::SubstituteAndAppend(contents, "$0}\n", prefix);
2635   comment_printer.AddPostComment(contents);
2636 }
2637 
DebugString() const2638 std::string FieldDescriptor::DebugString() const {
2639   DebugStringOptions options;  // default options
2640   return DebugStringWithOptions(options);
2641 }
2642 
DebugStringWithOptions(const DebugStringOptions & debug_string_options) const2643 std::string FieldDescriptor::DebugStringWithOptions(
2644     const DebugStringOptions& debug_string_options) const {
2645   std::string contents;
2646   int depth = 0;
2647   if (is_extension()) {
2648     strings::SubstituteAndAppend(&contents, "extend .$0 {\n",
2649                               containing_type()->full_name());
2650     depth = 1;
2651   }
2652   DebugString(depth, &contents, debug_string_options);
2653   if (is_extension()) {
2654     contents.append("}\n");
2655   }
2656   return contents;
2657 }
2658 
2659 // The field type string used in FieldDescriptor::DebugString()
FieldTypeNameDebugString() const2660 std::string FieldDescriptor::FieldTypeNameDebugString() const {
2661   switch (type()) {
2662     case TYPE_MESSAGE:
2663       return "." + message_type()->full_name();
2664     case TYPE_ENUM:
2665       return "." + enum_type()->full_name();
2666     default:
2667       return kTypeToName[type()];
2668   }
2669 }
2670 
DebugString(int depth,std::string * contents,const DebugStringOptions & debug_string_options) const2671 void FieldDescriptor::DebugString(
2672     int depth, std::string* contents,
2673     const DebugStringOptions& debug_string_options) const {
2674   std::string prefix(depth * 2, ' ');
2675   std::string field_type;
2676 
2677   // Special case map fields.
2678   if (is_map()) {
2679     strings::SubstituteAndAppend(
2680         &field_type, "map<$0, $1>",
2681         message_type()->field(0)->FieldTypeNameDebugString(),
2682         message_type()->field(1)->FieldTypeNameDebugString());
2683   } else {
2684     field_type = FieldTypeNameDebugString();
2685   }
2686 
2687   std::string label = StrCat(kLabelToName[this->label()], " ");
2688 
2689   // Label is omitted for maps, oneof, and plain proto3 fields.
2690   if (is_map() || real_containing_oneof() ||
2691       (is_optional() && !has_optional_keyword())) {
2692     label.clear();
2693   }
2694 
2695   SourceLocationCommentPrinter comment_printer(this, prefix,
2696                                                debug_string_options);
2697   comment_printer.AddPreComment(contents);
2698 
2699   strings::SubstituteAndAppend(
2700       contents, "$0$1$2 $3 = $4", prefix, label, field_type,
2701       type() == TYPE_GROUP ? message_type()->name() : name(), number());
2702 
2703   bool bracketed = false;
2704   if (has_default_value()) {
2705     bracketed = true;
2706     strings::SubstituteAndAppend(contents, " [default = $0",
2707                               DefaultValueAsString(true));
2708   }
2709   if (has_json_name_) {
2710     if (!bracketed) {
2711       bracketed = true;
2712       contents->append(" [");
2713     } else {
2714       contents->append(", ");
2715     }
2716     contents->append("json_name = \"");
2717     contents->append(CEscape(json_name()));
2718     contents->append("\"");
2719   }
2720 
2721   std::string formatted_options;
2722   if (FormatBracketedOptions(depth, options(), file()->pool(),
2723                              &formatted_options)) {
2724     contents->append(bracketed ? ", " : " [");
2725     bracketed = true;
2726     contents->append(formatted_options);
2727   }
2728 
2729   if (bracketed) {
2730     contents->append("]");
2731   }
2732 
2733   if (type() == TYPE_GROUP) {
2734     if (debug_string_options.elide_group_body) {
2735       contents->append(" { ... };\n");
2736     } else {
2737       message_type()->DebugString(depth, contents, debug_string_options,
2738                                   /* include_opening_clause */ false);
2739     }
2740   } else {
2741     contents->append(";\n");
2742   }
2743 
2744   comment_printer.AddPostComment(contents);
2745 }
2746 
DebugString() const2747 std::string OneofDescriptor::DebugString() const {
2748   DebugStringOptions options;  // default values
2749   return DebugStringWithOptions(options);
2750 }
2751 
DebugStringWithOptions(const DebugStringOptions & options) const2752 std::string OneofDescriptor::DebugStringWithOptions(
2753     const DebugStringOptions& options) const {
2754   std::string contents;
2755   DebugString(0, &contents, options);
2756   return contents;
2757 }
2758 
DebugString(int depth,std::string * contents,const DebugStringOptions & debug_string_options) const2759 void OneofDescriptor::DebugString(
2760     int depth, std::string* contents,
2761     const DebugStringOptions& debug_string_options) const {
2762   std::string prefix(depth * 2, ' ');
2763   ++depth;
2764   SourceLocationCommentPrinter comment_printer(this, prefix,
2765                                                debug_string_options);
2766   comment_printer.AddPreComment(contents);
2767   strings::SubstituteAndAppend(contents, "$0oneof $1 {", prefix, name());
2768 
2769   FormatLineOptions(depth, options(), containing_type()->file()->pool(),
2770                     contents);
2771 
2772   if (debug_string_options.elide_oneof_body) {
2773     contents->append(" ... }\n");
2774   } else {
2775     contents->append("\n");
2776     for (int i = 0; i < field_count(); i++) {
2777       field(i)->DebugString(depth, contents, debug_string_options);
2778     }
2779     strings::SubstituteAndAppend(contents, "$0}\n", prefix);
2780   }
2781   comment_printer.AddPostComment(contents);
2782 }
2783 
DebugString() const2784 std::string EnumDescriptor::DebugString() const {
2785   DebugStringOptions options;  // default values
2786   return DebugStringWithOptions(options);
2787 }
2788 
DebugStringWithOptions(const DebugStringOptions & options) const2789 std::string EnumDescriptor::DebugStringWithOptions(
2790     const DebugStringOptions& options) const {
2791   std::string contents;
2792   DebugString(0, &contents, options);
2793   return contents;
2794 }
2795 
DebugString(int depth,std::string * contents,const DebugStringOptions & debug_string_options) const2796 void EnumDescriptor::DebugString(
2797     int depth, std::string* contents,
2798     const DebugStringOptions& debug_string_options) const {
2799   std::string prefix(depth * 2, ' ');
2800   ++depth;
2801 
2802   SourceLocationCommentPrinter comment_printer(this, prefix,
2803                                                debug_string_options);
2804   comment_printer.AddPreComment(contents);
2805 
2806   strings::SubstituteAndAppend(contents, "$0enum $1 {\n", prefix, name());
2807 
2808   FormatLineOptions(depth, options(), file()->pool(), contents);
2809 
2810   for (int i = 0; i < value_count(); i++) {
2811     value(i)->DebugString(depth, contents, debug_string_options);
2812   }
2813 
2814   if (reserved_range_count() > 0) {
2815     strings::SubstituteAndAppend(contents, "$0  reserved ", prefix);
2816     for (int i = 0; i < reserved_range_count(); i++) {
2817       const EnumDescriptor::ReservedRange* range = reserved_range(i);
2818       if (range->end == range->start) {
2819         strings::SubstituteAndAppend(contents, "$0, ", range->start);
2820       } else if (range->end == INT_MAX) {
2821         strings::SubstituteAndAppend(contents, "$0 to max, ", range->start);
2822       } else {
2823         strings::SubstituteAndAppend(contents, "$0 to $1, ", range->start,
2824                                   range->end);
2825       }
2826     }
2827     contents->replace(contents->size() - 2, 2, ";\n");
2828   }
2829 
2830   if (reserved_name_count() > 0) {
2831     strings::SubstituteAndAppend(contents, "$0  reserved ", prefix);
2832     for (int i = 0; i < reserved_name_count(); i++) {
2833       strings::SubstituteAndAppend(contents, "\"$0\", ",
2834                                 CEscape(reserved_name(i)));
2835     }
2836     contents->replace(contents->size() - 2, 2, ";\n");
2837   }
2838 
2839   strings::SubstituteAndAppend(contents, "$0}\n", prefix);
2840 
2841   comment_printer.AddPostComment(contents);
2842 }
2843 
DebugString() const2844 std::string EnumValueDescriptor::DebugString() const {
2845   DebugStringOptions options;  // default values
2846   return DebugStringWithOptions(options);
2847 }
2848 
DebugStringWithOptions(const DebugStringOptions & options) const2849 std::string EnumValueDescriptor::DebugStringWithOptions(
2850     const DebugStringOptions& options) const {
2851   std::string contents;
2852   DebugString(0, &contents, options);
2853   return contents;
2854 }
2855 
DebugString(int depth,std::string * contents,const DebugStringOptions & debug_string_options) const2856 void EnumValueDescriptor::DebugString(
2857     int depth, std::string* contents,
2858     const DebugStringOptions& debug_string_options) const {
2859   std::string prefix(depth * 2, ' ');
2860 
2861   SourceLocationCommentPrinter comment_printer(this, prefix,
2862                                                debug_string_options);
2863   comment_printer.AddPreComment(contents);
2864 
2865   strings::SubstituteAndAppend(contents, "$0$1 = $2", prefix, name(), number());
2866 
2867   std::string formatted_options;
2868   if (FormatBracketedOptions(depth, options(), type()->file()->pool(),
2869                              &formatted_options)) {
2870     strings::SubstituteAndAppend(contents, " [$0]", formatted_options);
2871   }
2872   contents->append(";\n");
2873 
2874   comment_printer.AddPostComment(contents);
2875 }
2876 
DebugString() const2877 std::string ServiceDescriptor::DebugString() const {
2878   DebugStringOptions options;  // default values
2879   return DebugStringWithOptions(options);
2880 }
2881 
DebugStringWithOptions(const DebugStringOptions & options) const2882 std::string ServiceDescriptor::DebugStringWithOptions(
2883     const DebugStringOptions& options) const {
2884   std::string contents;
2885   DebugString(&contents, options);
2886   return contents;
2887 }
2888 
DebugString(std::string * contents,const DebugStringOptions & debug_string_options) const2889 void ServiceDescriptor::DebugString(
2890     std::string* contents,
2891     const DebugStringOptions& debug_string_options) const {
2892   SourceLocationCommentPrinter comment_printer(this, /* prefix */ "",
2893                                                debug_string_options);
2894   comment_printer.AddPreComment(contents);
2895 
2896   strings::SubstituteAndAppend(contents, "service $0 {\n", name());
2897 
2898   FormatLineOptions(1, options(), file()->pool(), contents);
2899 
2900   for (int i = 0; i < method_count(); i++) {
2901     method(i)->DebugString(1, contents, debug_string_options);
2902   }
2903 
2904   contents->append("}\n");
2905 
2906   comment_printer.AddPostComment(contents);
2907 }
2908 
DebugString() const2909 std::string MethodDescriptor::DebugString() const {
2910   DebugStringOptions options;  // default values
2911   return DebugStringWithOptions(options);
2912 }
2913 
DebugStringWithOptions(const DebugStringOptions & options) const2914 std::string MethodDescriptor::DebugStringWithOptions(
2915     const DebugStringOptions& options) const {
2916   std::string contents;
2917   DebugString(0, &contents, options);
2918   return contents;
2919 }
2920 
DebugString(int depth,std::string * contents,const DebugStringOptions & debug_string_options) const2921 void MethodDescriptor::DebugString(
2922     int depth, std::string* contents,
2923     const DebugStringOptions& debug_string_options) const {
2924   std::string prefix(depth * 2, ' ');
2925   ++depth;
2926 
2927   SourceLocationCommentPrinter comment_printer(this, prefix,
2928                                                debug_string_options);
2929   comment_printer.AddPreComment(contents);
2930 
2931   strings::SubstituteAndAppend(
2932       contents, "$0rpc $1($4.$2) returns ($5.$3)", prefix, name(),
2933       input_type()->full_name(), output_type()->full_name(),
2934       client_streaming() ? "stream " : "", server_streaming() ? "stream " : "");
2935 
2936   std::string formatted_options;
2937   if (FormatLineOptions(depth, options(), service()->file()->pool(),
2938                         &formatted_options)) {
2939     strings::SubstituteAndAppend(contents, " {\n$0$1}\n", formatted_options,
2940                               prefix);
2941   } else {
2942     contents->append(";\n");
2943   }
2944 
2945   comment_printer.AddPostComment(contents);
2946 }
2947 
2948 
2949 // Location methods ===============================================
2950 
GetSourceLocation(const std::vector<int> & path,SourceLocation * out_location) const2951 bool FileDescriptor::GetSourceLocation(const std::vector<int>& path,
2952                                        SourceLocation* out_location) const {
2953   GOOGLE_CHECK(out_location != nullptr);
2954   if (source_code_info_) {
2955     if (const SourceCodeInfo_Location* loc =
2956             tables_->GetSourceLocation(path, source_code_info_)) {
2957       const RepeatedField<int32>& span = loc->span();
2958       if (span.size() == 3 || span.size() == 4) {
2959         out_location->start_line = span.Get(0);
2960         out_location->start_column = span.Get(1);
2961         out_location->end_line = span.Get(span.size() == 3 ? 0 : 2);
2962         out_location->end_column = span.Get(span.size() - 1);
2963 
2964         out_location->leading_comments = loc->leading_comments();
2965         out_location->trailing_comments = loc->trailing_comments();
2966         out_location->leading_detached_comments.assign(
2967             loc->leading_detached_comments().begin(),
2968             loc->leading_detached_comments().end());
2969         return true;
2970       }
2971     }
2972   }
2973   return false;
2974 }
2975 
GetSourceLocation(SourceLocation * out_location) const2976 bool FileDescriptor::GetSourceLocation(SourceLocation* out_location) const {
2977   std::vector<int> path;  // empty path for root FileDescriptor
2978   return GetSourceLocation(path, out_location);
2979 }
2980 
is_packed() const2981 bool FieldDescriptor::is_packed() const {
2982   if (!is_packable()) return false;
2983   if (file_->syntax() == FileDescriptor::SYNTAX_PROTO2) {
2984     return (options_ != nullptr) && options_->packed();
2985   } else {
2986     return options_ == nullptr || !options_->has_packed() || options_->packed();
2987   }
2988 }
2989 
GetSourceLocation(SourceLocation * out_location) const2990 bool Descriptor::GetSourceLocation(SourceLocation* out_location) const {
2991   std::vector<int> path;
2992   GetLocationPath(&path);
2993   return file()->GetSourceLocation(path, out_location);
2994 }
2995 
GetSourceLocation(SourceLocation * out_location) const2996 bool FieldDescriptor::GetSourceLocation(SourceLocation* out_location) const {
2997   std::vector<int> path;
2998   GetLocationPath(&path);
2999   return file()->GetSourceLocation(path, out_location);
3000 }
3001 
GetSourceLocation(SourceLocation * out_location) const3002 bool OneofDescriptor::GetSourceLocation(SourceLocation* out_location) const {
3003   std::vector<int> path;
3004   GetLocationPath(&path);
3005   return containing_type()->file()->GetSourceLocation(path, out_location);
3006 }
3007 
GetSourceLocation(SourceLocation * out_location) const3008 bool EnumDescriptor::GetSourceLocation(SourceLocation* out_location) const {
3009   std::vector<int> path;
3010   GetLocationPath(&path);
3011   return file()->GetSourceLocation(path, out_location);
3012 }
3013 
GetSourceLocation(SourceLocation * out_location) const3014 bool MethodDescriptor::GetSourceLocation(SourceLocation* out_location) const {
3015   std::vector<int> path;
3016   GetLocationPath(&path);
3017   return service()->file()->GetSourceLocation(path, out_location);
3018 }
3019 
GetSourceLocation(SourceLocation * out_location) const3020 bool ServiceDescriptor::GetSourceLocation(SourceLocation* out_location) const {
3021   std::vector<int> path;
3022   GetLocationPath(&path);
3023   return file()->GetSourceLocation(path, out_location);
3024 }
3025 
GetSourceLocation(SourceLocation * out_location) const3026 bool EnumValueDescriptor::GetSourceLocation(
3027     SourceLocation* out_location) const {
3028   std::vector<int> path;
3029   GetLocationPath(&path);
3030   return type()->file()->GetSourceLocation(path, out_location);
3031 }
3032 
GetLocationPath(std::vector<int> * output) const3033 void Descriptor::GetLocationPath(std::vector<int>* output) const {
3034   if (containing_type()) {
3035     containing_type()->GetLocationPath(output);
3036     output->push_back(DescriptorProto::kNestedTypeFieldNumber);
3037     output->push_back(index());
3038   } else {
3039     output->push_back(FileDescriptorProto::kMessageTypeFieldNumber);
3040     output->push_back(index());
3041   }
3042 }
3043 
GetLocationPath(std::vector<int> * output) const3044 void FieldDescriptor::GetLocationPath(std::vector<int>* output) const {
3045   if (is_extension()) {
3046     if (extension_scope() == nullptr) {
3047       output->push_back(FileDescriptorProto::kExtensionFieldNumber);
3048       output->push_back(index());
3049     } else {
3050       extension_scope()->GetLocationPath(output);
3051       output->push_back(DescriptorProto::kExtensionFieldNumber);
3052       output->push_back(index());
3053     }
3054   } else {
3055     containing_type()->GetLocationPath(output);
3056     output->push_back(DescriptorProto::kFieldFieldNumber);
3057     output->push_back(index());
3058   }
3059 }
3060 
GetLocationPath(std::vector<int> * output) const3061 void OneofDescriptor::GetLocationPath(std::vector<int>* output) const {
3062   containing_type()->GetLocationPath(output);
3063   output->push_back(DescriptorProto::kOneofDeclFieldNumber);
3064   output->push_back(index());
3065 }
3066 
GetLocationPath(std::vector<int> * output) const3067 void EnumDescriptor::GetLocationPath(std::vector<int>* output) const {
3068   if (containing_type()) {
3069     containing_type()->GetLocationPath(output);
3070     output->push_back(DescriptorProto::kEnumTypeFieldNumber);
3071     output->push_back(index());
3072   } else {
3073     output->push_back(FileDescriptorProto::kEnumTypeFieldNumber);
3074     output->push_back(index());
3075   }
3076 }
3077 
GetLocationPath(std::vector<int> * output) const3078 void EnumValueDescriptor::GetLocationPath(std::vector<int>* output) const {
3079   type()->GetLocationPath(output);
3080   output->push_back(EnumDescriptorProto::kValueFieldNumber);
3081   output->push_back(index());
3082 }
3083 
GetLocationPath(std::vector<int> * output) const3084 void ServiceDescriptor::GetLocationPath(std::vector<int>* output) const {
3085   output->push_back(FileDescriptorProto::kServiceFieldNumber);
3086   output->push_back(index());
3087 }
3088 
GetLocationPath(std::vector<int> * output) const3089 void MethodDescriptor::GetLocationPath(std::vector<int>* output) const {
3090   service()->GetLocationPath(output);
3091   output->push_back(ServiceDescriptorProto::kMethodFieldNumber);
3092   output->push_back(index());
3093 }
3094 
3095 // ===================================================================
3096 
3097 namespace {
3098 
3099 // Represents an options message to interpret. Extension names in the option
3100 // name are resolved relative to name_scope. element_name and orig_opt are
3101 // used only for error reporting (since the parser records locations against
3102 // pointers in the original options, not the mutable copy). The Message must be
3103 // one of the Options messages in descriptor.proto.
3104 struct OptionsToInterpret {
OptionsToInterpretgoogle::protobuf::__anon4efa60f60511::OptionsToInterpret3105   OptionsToInterpret(const std::string& ns, const std::string& el,
3106                      const std::vector<int>& path, const Message* orig_opt,
3107                      Message* opt)
3108       : name_scope(ns),
3109         element_name(el),
3110         element_path(path),
3111         original_options(orig_opt),
3112         options(opt) {}
3113   std::string name_scope;
3114   std::string element_name;
3115   std::vector<int> element_path;
3116   const Message* original_options;
3117   Message* options;
3118 };
3119 
3120 }  // namespace
3121 
3122 class DescriptorBuilder {
3123  public:
3124   DescriptorBuilder(const DescriptorPool* pool, DescriptorPool::Tables* tables,
3125                     DescriptorPool::ErrorCollector* error_collector);
3126   ~DescriptorBuilder();
3127 
3128   const FileDescriptor* BuildFile(const FileDescriptorProto& proto);
3129 
3130  private:
3131   friend class OptionInterpreter;
3132 
3133   // Non-recursive part of BuildFile functionality.
3134   FileDescriptor* BuildFileImpl(const FileDescriptorProto& proto);
3135 
3136   const DescriptorPool* pool_;
3137   DescriptorPool::Tables* tables_;  // for convenience
3138   DescriptorPool::ErrorCollector* error_collector_;
3139 
3140   // As we build descriptors we store copies of the options messages in
3141   // them. We put pointers to those copies in this vector, as we build, so we
3142   // can later (after cross-linking) interpret those options.
3143   std::vector<OptionsToInterpret> options_to_interpret_;
3144 
3145   bool had_errors_;
3146   std::string filename_;
3147   FileDescriptor* file_;
3148   FileDescriptorTables* file_tables_;
3149   std::set<const FileDescriptor*> dependencies_;
3150 
3151   // unused_dependency_ is used to record the unused imported files.
3152   // Note: public import is not considered.
3153   std::set<const FileDescriptor*> unused_dependency_;
3154 
3155   // If LookupSymbol() finds a symbol that is in a file which is not a declared
3156   // dependency of this file, it will fail, but will set
3157   // possible_undeclared_dependency_ to point at that file.  This is only used
3158   // by AddNotDefinedError() to report a more useful error message.
3159   // possible_undeclared_dependency_name_ is the name of the symbol that was
3160   // actually found in possible_undeclared_dependency_, which may be a parent
3161   // of the symbol actually looked for.
3162   const FileDescriptor* possible_undeclared_dependency_;
3163   std::string possible_undeclared_dependency_name_;
3164 
3165   // If LookupSymbol() could resolve a symbol which is not defined,
3166   // record the resolved name.  This is only used by AddNotDefinedError()
3167   // to report a more useful error message.
3168   std::string undefine_resolved_name_;
3169 
3170   void AddError(const std::string& element_name, const Message& descriptor,
3171                 DescriptorPool::ErrorCollector::ErrorLocation location,
3172                 const std::string& error);
3173   void AddError(const std::string& element_name, const Message& descriptor,
3174                 DescriptorPool::ErrorCollector::ErrorLocation location,
3175                 const char* error);
3176   void AddRecursiveImportError(const FileDescriptorProto& proto, int from_here);
3177   void AddTwiceListedError(const FileDescriptorProto& proto, int index);
3178   void AddImportError(const FileDescriptorProto& proto, int index);
3179 
3180   // Adds an error indicating that undefined_symbol was not defined.  Must
3181   // only be called after LookupSymbol() fails.
3182   void AddNotDefinedError(
3183       const std::string& element_name, const Message& descriptor,
3184       DescriptorPool::ErrorCollector::ErrorLocation location,
3185       const std::string& undefined_symbol);
3186 
3187   void AddWarning(const std::string& element_name, const Message& descriptor,
3188                   DescriptorPool::ErrorCollector::ErrorLocation location,
3189                   const std::string& error);
3190 
3191   // Silly helper which determines if the given file is in the given package.
3192   // I.e., either file->package() == package_name or file->package() is a
3193   // nested package within package_name.
3194   bool IsInPackage(const FileDescriptor* file, const std::string& package_name);
3195 
3196   // Helper function which finds all public dependencies of the given file, and
3197   // stores the them in the dependencies_ set in the builder.
3198   void RecordPublicDependencies(const FileDescriptor* file);
3199 
3200   // Like tables_->FindSymbol(), but additionally:
3201   // - Search the pool's underlay if not found in tables_.
3202   // - Insure that the resulting Symbol is from one of the file's declared
3203   //   dependencies.
3204   Symbol FindSymbol(const std::string& name, bool build_it = true);
3205 
3206   // Like FindSymbol() but does not require that the symbol is in one of the
3207   // file's declared dependencies.
3208   Symbol FindSymbolNotEnforcingDeps(const std::string& name,
3209                                     bool build_it = true);
3210 
3211   // This implements the body of FindSymbolNotEnforcingDeps().
3212   Symbol FindSymbolNotEnforcingDepsHelper(const DescriptorPool* pool,
3213                                           const std::string& name,
3214                                           bool build_it = true);
3215 
3216   // Like FindSymbol(), but looks up the name relative to some other symbol
3217   // name.  This first searches siblings of relative_to, then siblings of its
3218   // parents, etc.  For example, LookupSymbol("foo.bar", "baz.qux.corge") makes
3219   // the following calls, returning the first non-null result:
3220   // FindSymbol("baz.qux.foo.bar"), FindSymbol("baz.foo.bar"),
3221   // FindSymbol("foo.bar").  If AllowUnknownDependencies() has been called
3222   // on the DescriptorPool, this will generate a placeholder type if
3223   // the name is not found (unless the name itself is malformed).  The
3224   // placeholder_type parameter indicates what kind of placeholder should be
3225   // constructed in this case.  The resolve_mode parameter determines whether
3226   // any symbol is returned, or only symbols that are types.  Note, however,
3227   // that LookupSymbol may still return a non-type symbol in LOOKUP_TYPES mode,
3228   // if it believes that's all it could refer to.  The caller should always
3229   // check that it receives the type of symbol it was expecting.
3230   enum ResolveMode { LOOKUP_ALL, LOOKUP_TYPES };
3231   Symbol LookupSymbol(const std::string& name, const std::string& relative_to,
3232                       DescriptorPool::PlaceholderType placeholder_type =
3233                           DescriptorPool::PLACEHOLDER_MESSAGE,
3234                       ResolveMode resolve_mode = LOOKUP_ALL,
3235                       bool build_it = true);
3236 
3237   // Like LookupSymbol() but will not return a placeholder even if
3238   // AllowUnknownDependencies() has been used.
3239   Symbol LookupSymbolNoPlaceholder(const std::string& name,
3240                                    const std::string& relative_to,
3241                                    ResolveMode resolve_mode = LOOKUP_ALL,
3242                                    bool build_it = true);
3243 
3244   // Calls tables_->AddSymbol() and records an error if it fails.  Returns
3245   // true if successful or false if failed, though most callers can ignore
3246   // the return value since an error has already been recorded.
3247   bool AddSymbol(const std::string& full_name, const void* parent,
3248                  const std::string& name, const Message& proto, Symbol symbol);
3249 
3250   // Like AddSymbol(), but succeeds if the symbol is already defined as long
3251   // as the existing definition is also a package (because it's OK to define
3252   // the same package in two different files).  Also adds all parents of the
3253   // package to the symbol table (e.g. AddPackage("foo.bar", ...) will add
3254   // "foo.bar" and "foo" to the table).
3255   void AddPackage(const std::string& name, const Message& proto,
3256                   const FileDescriptor* file);
3257 
3258   // Checks that the symbol name contains only alphanumeric characters and
3259   // underscores.  Records an error otherwise.
3260   void ValidateSymbolName(const std::string& name, const std::string& full_name,
3261                           const Message& proto);
3262 
3263   // Used by BUILD_ARRAY macro (below) to avoid having to have the type
3264   // specified as a macro parameter.
3265   template <typename Type>
AllocateArray(int size,Type ** output)3266   inline void AllocateArray(int size, Type** output) {
3267     *output = tables_->AllocateArray<Type>(size);
3268   }
3269 
3270   // Allocates a copy of orig_options in tables_ and stores it in the
3271   // descriptor. Remembers its uninterpreted options, to be interpreted
3272   // later. DescriptorT must be one of the Descriptor messages from
3273   // descriptor.proto.
3274   template <class DescriptorT>
3275   void AllocateOptions(const typename DescriptorT::OptionsType& orig_options,
3276                        DescriptorT* descriptor, int options_field_tag,
3277                        const std::string& option_name);
3278   // Specialization for FileOptions.
3279   void AllocateOptions(const FileOptions& orig_options,
3280                        FileDescriptor* descriptor);
3281 
3282   // Implementation for AllocateOptions(). Don't call this directly.
3283   template <class DescriptorT>
3284   void AllocateOptionsImpl(
3285       const std::string& name_scope, const std::string& element_name,
3286       const typename DescriptorT::OptionsType& orig_options,
3287       DescriptorT* descriptor, const std::vector<int>& options_path,
3288       const std::string& option_name);
3289 
3290   // Allocate string on the string pool and initialize it to full proto name.
3291   // Full proto name is "scope.proto_name" if scope is non-empty and
3292   // "proto_name" otherwise.
3293   std::string* AllocateNameString(const std::string& scope,
3294                                   const std::string& proto_name);
3295 
3296   // These methods all have the same signature for the sake of the BUILD_ARRAY
3297   // macro, below.
3298   void BuildMessage(const DescriptorProto& proto, const Descriptor* parent,
3299                     Descriptor* result);
3300   void BuildFieldOrExtension(const FieldDescriptorProto& proto,
3301                              Descriptor* parent, FieldDescriptor* result,
3302                              bool is_extension);
BuildField(const FieldDescriptorProto & proto,Descriptor * parent,FieldDescriptor * result)3303   void BuildField(const FieldDescriptorProto& proto, Descriptor* parent,
3304                   FieldDescriptor* result) {
3305     BuildFieldOrExtension(proto, parent, result, false);
3306   }
BuildExtension(const FieldDescriptorProto & proto,Descriptor * parent,FieldDescriptor * result)3307   void BuildExtension(const FieldDescriptorProto& proto, Descriptor* parent,
3308                       FieldDescriptor* result) {
3309     BuildFieldOrExtension(proto, parent, result, true);
3310   }
3311   void BuildExtensionRange(const DescriptorProto::ExtensionRange& proto,
3312                            const Descriptor* parent,
3313                            Descriptor::ExtensionRange* result);
3314   void BuildReservedRange(const DescriptorProto::ReservedRange& proto,
3315                           const Descriptor* parent,
3316                           Descriptor::ReservedRange* result);
3317   void BuildReservedRange(const EnumDescriptorProto::EnumReservedRange& proto,
3318                           const EnumDescriptor* parent,
3319                           EnumDescriptor::ReservedRange* result);
3320   void BuildOneof(const OneofDescriptorProto& proto, Descriptor* parent,
3321                   OneofDescriptor* result);
3322   void CheckEnumValueUniqueness(const EnumDescriptorProto& proto,
3323                                 const EnumDescriptor* result);
3324   void BuildEnum(const EnumDescriptorProto& proto, const Descriptor* parent,
3325                  EnumDescriptor* result);
3326   void BuildEnumValue(const EnumValueDescriptorProto& proto,
3327                       const EnumDescriptor* parent,
3328                       EnumValueDescriptor* result);
3329   void BuildService(const ServiceDescriptorProto& proto, const void* dummy,
3330                     ServiceDescriptor* result);
3331   void BuildMethod(const MethodDescriptorProto& proto,
3332                    const ServiceDescriptor* parent, MethodDescriptor* result);
3333 
3334   void LogUnusedDependency(const FileDescriptorProto& proto,
3335                            const FileDescriptor* result);
3336 
3337   // Must be run only after building.
3338   //
3339   // NOTE: Options will not be available during cross-linking, as they
3340   // have not yet been interpreted. Defer any handling of options to the
3341   // Validate*Options methods.
3342   void CrossLinkFile(FileDescriptor* file, const FileDescriptorProto& proto);
3343   void CrossLinkMessage(Descriptor* message, const DescriptorProto& proto);
3344   void CrossLinkField(FieldDescriptor* field,
3345                       const FieldDescriptorProto& proto);
3346   void CrossLinkExtensionRange(Descriptor::ExtensionRange* range,
3347                                const DescriptorProto::ExtensionRange& proto);
3348   void CrossLinkEnum(EnumDescriptor* enum_type,
3349                      const EnumDescriptorProto& proto);
3350   void CrossLinkEnumValue(EnumValueDescriptor* enum_value,
3351                           const EnumValueDescriptorProto& proto);
3352   void CrossLinkService(ServiceDescriptor* service,
3353                         const ServiceDescriptorProto& proto);
3354   void CrossLinkMethod(MethodDescriptor* method,
3355                        const MethodDescriptorProto& proto);
3356 
3357   // Must be run only after cross-linking.
3358   void InterpretOptions();
3359 
3360   // A helper class for interpreting options.
3361   class OptionInterpreter {
3362    public:
3363     // Creates an interpreter that operates in the context of the pool of the
3364     // specified builder, which must not be nullptr. We don't take ownership of
3365     // the builder.
3366     explicit OptionInterpreter(DescriptorBuilder* builder);
3367 
3368     ~OptionInterpreter();
3369 
3370     // Interprets the uninterpreted options in the specified Options message.
3371     // On error, calls AddError() on the underlying builder and returns false.
3372     // Otherwise returns true.
3373     bool InterpretOptions(OptionsToInterpret* options_to_interpret);
3374 
3375     // Updates the given source code info by re-writing uninterpreted option
3376     // locations to refer to the corresponding interpreted option.
3377     void UpdateSourceCodeInfo(SourceCodeInfo* info);
3378 
3379     class AggregateOptionFinder;
3380 
3381    private:
3382     // Interprets uninterpreted_option_ on the specified message, which
3383     // must be the mutable copy of the original options message to which
3384     // uninterpreted_option_ belongs. The given src_path is the source
3385     // location path to the uninterpreted option, and options_path is the
3386     // source location path to the options message. The location paths are
3387     // recorded and then used in UpdateSourceCodeInfo.
3388     bool InterpretSingleOption(Message* options,
3389                                const std::vector<int>& src_path,
3390                                const std::vector<int>& options_path);
3391 
3392     // Adds the uninterpreted_option to the given options message verbatim.
3393     // Used when AllowUnknownDependencies() is in effect and we can't find
3394     // the option's definition.
3395     void AddWithoutInterpreting(const UninterpretedOption& uninterpreted_option,
3396                                 Message* options);
3397 
3398     // A recursive helper function that drills into the intermediate fields
3399     // in unknown_fields to check if field innermost_field is set on the
3400     // innermost message. Returns false and sets an error if so.
3401     bool ExamineIfOptionIsSet(
3402         std::vector<const FieldDescriptor*>::const_iterator
3403             intermediate_fields_iter,
3404         std::vector<const FieldDescriptor*>::const_iterator
3405             intermediate_fields_end,
3406         const FieldDescriptor* innermost_field,
3407         const std::string& debug_msg_name,
3408         const UnknownFieldSet& unknown_fields);
3409 
3410     // Validates the value for the option field of the currently interpreted
3411     // option and then sets it on the unknown_field.
3412     bool SetOptionValue(const FieldDescriptor* option_field,
3413                         UnknownFieldSet* unknown_fields);
3414 
3415     // Parses an aggregate value for a CPPTYPE_MESSAGE option and
3416     // saves it into *unknown_fields.
3417     bool SetAggregateOption(const FieldDescriptor* option_field,
3418                             UnknownFieldSet* unknown_fields);
3419 
3420     // Convenience functions to set an int field the right way, depending on
3421     // its wire type (a single int CppType can represent multiple wire types).
3422     void SetInt32(int number, int32 value, FieldDescriptor::Type type,
3423                   UnknownFieldSet* unknown_fields);
3424     void SetInt64(int number, int64 value, FieldDescriptor::Type type,
3425                   UnknownFieldSet* unknown_fields);
3426     void SetUInt32(int number, uint32 value, FieldDescriptor::Type type,
3427                    UnknownFieldSet* unknown_fields);
3428     void SetUInt64(int number, uint64 value, FieldDescriptor::Type type,
3429                    UnknownFieldSet* unknown_fields);
3430 
3431     // A helper function that adds an error at the specified location of the
3432     // option we're currently interpreting, and returns false.
AddOptionError(DescriptorPool::ErrorCollector::ErrorLocation location,const std::string & msg)3433     bool AddOptionError(DescriptorPool::ErrorCollector::ErrorLocation location,
3434                         const std::string& msg) {
3435       builder_->AddError(options_to_interpret_->element_name,
3436                          *uninterpreted_option_, location, msg);
3437       return false;
3438     }
3439 
3440     // A helper function that adds an error at the location of the option name
3441     // and returns false.
AddNameError(const std::string & msg)3442     bool AddNameError(const std::string& msg) {
3443       return AddOptionError(DescriptorPool::ErrorCollector::OPTION_NAME, msg);
3444     }
3445 
3446     // A helper function that adds an error at the location of the option name
3447     // and returns false.
AddValueError(const std::string & msg)3448     bool AddValueError(const std::string& msg) {
3449       return AddOptionError(DescriptorPool::ErrorCollector::OPTION_VALUE, msg);
3450     }
3451 
3452     // We interpret against this builder's pool. Is never nullptr. We don't own
3453     // this pointer.
3454     DescriptorBuilder* builder_;
3455 
3456     // The options we're currently interpreting, or nullptr if we're not in a
3457     // call to InterpretOptions.
3458     const OptionsToInterpret* options_to_interpret_;
3459 
3460     // The option we're currently interpreting within options_to_interpret_, or
3461     // nullptr if we're not in a call to InterpretOptions(). This points to a
3462     // submessage of the original option, not the mutable copy. Therefore we
3463     // can use it to find locations recorded by the parser.
3464     const UninterpretedOption* uninterpreted_option_;
3465 
3466     // This maps the element path of uninterpreted options to the element path
3467     // of the resulting interpreted option. This is used to modify a file's
3468     // source code info to account for option interpretation.
3469     std::map<std::vector<int>, std::vector<int>> interpreted_paths_;
3470 
3471     // This maps the path to a repeated option field to the known number of
3472     // elements the field contains. This is used to track the compute the
3473     // index portion of the element path when interpreting a single option.
3474     std::map<std::vector<int>, int> repeated_option_counts_;
3475 
3476     // Factory used to create the dynamic messages we need to parse
3477     // any aggregate option values we encounter.
3478     DynamicMessageFactory dynamic_factory_;
3479 
3480     GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(OptionInterpreter);
3481   };
3482 
3483   // Work-around for broken compilers:  According to the C++ standard,
3484   // OptionInterpreter should have access to the private members of any class
3485   // which has declared DescriptorBuilder as a friend.  Unfortunately some old
3486   // versions of GCC and other compilers do not implement this correctly.  So,
3487   // we have to have these intermediate methods to provide access.  We also
3488   // redundantly declare OptionInterpreter a friend just to make things extra
3489   // clear for these bad compilers.
3490   friend class OptionInterpreter;
3491   friend class OptionInterpreter::AggregateOptionFinder;
3492 
get_allow_unknown(const DescriptorPool * pool)3493   static inline bool get_allow_unknown(const DescriptorPool* pool) {
3494     return pool->allow_unknown_;
3495   }
get_enforce_weak(const DescriptorPool * pool)3496   static inline bool get_enforce_weak(const DescriptorPool* pool) {
3497     return pool->enforce_weak_;
3498   }
get_is_placeholder(const Descriptor * descriptor)3499   static inline bool get_is_placeholder(const Descriptor* descriptor) {
3500     return descriptor != nullptr && descriptor->is_placeholder_;
3501   }
assert_mutex_held(const DescriptorPool * pool)3502   static inline void assert_mutex_held(const DescriptorPool* pool) {
3503     if (pool->mutex_ != nullptr) {
3504       pool->mutex_->AssertHeld();
3505     }
3506   }
3507 
3508   // Must be run only after options have been interpreted.
3509   //
3510   // NOTE: Validation code must only reference the options in the mutable
3511   // descriptors, which are the ones that have been interpreted. The const
3512   // proto references are passed in only so they can be provided to calls to
3513   // AddError(). Do not look at their options, which have not been interpreted.
3514   void ValidateFileOptions(FileDescriptor* file,
3515                            const FileDescriptorProto& proto);
3516   void ValidateMessageOptions(Descriptor* message,
3517                               const DescriptorProto& proto);
3518   void ValidateFieldOptions(FieldDescriptor* field,
3519                             const FieldDescriptorProto& proto);
3520   void ValidateEnumOptions(EnumDescriptor* enm,
3521                            const EnumDescriptorProto& proto);
3522   void ValidateEnumValueOptions(EnumValueDescriptor* enum_value,
3523                                 const EnumValueDescriptorProto& proto);
3524   void ValidateExtensionRangeOptions(
3525       const std::string& full_name, Descriptor::ExtensionRange* extension_range,
3526       const DescriptorProto_ExtensionRange& proto);
3527   void ValidateServiceOptions(ServiceDescriptor* service,
3528                               const ServiceDescriptorProto& proto);
3529   void ValidateMethodOptions(MethodDescriptor* method,
3530                              const MethodDescriptorProto& proto);
3531   void ValidateProto3(FileDescriptor* file, const FileDescriptorProto& proto);
3532   void ValidateProto3Message(Descriptor* message, const DescriptorProto& proto);
3533   void ValidateProto3Field(FieldDescriptor* field,
3534                            const FieldDescriptorProto& proto);
3535   void ValidateProto3Enum(EnumDescriptor* enm,
3536                           const EnumDescriptorProto& proto);
3537 
3538   // Returns true if the map entry message is compatible with the
3539   // auto-generated entry message from map fields syntax.
3540   bool ValidateMapEntry(FieldDescriptor* field,
3541                         const FieldDescriptorProto& proto);
3542 
3543   // Recursively detects naming conflicts with map entry types for a
3544   // better error message.
3545   void DetectMapConflicts(const Descriptor* message,
3546                           const DescriptorProto& proto);
3547 
3548   void ValidateJSType(FieldDescriptor* field,
3549                       const FieldDescriptorProto& proto);
3550 };
3551 
BuildFile(const FileDescriptorProto & proto)3552 const FileDescriptor* DescriptorPool::BuildFile(
3553     const FileDescriptorProto& proto) {
3554   GOOGLE_CHECK(fallback_database_ == nullptr)
3555       << "Cannot call BuildFile on a DescriptorPool that uses a "
3556          "DescriptorDatabase.  You must instead find a way to get your file "
3557          "into the underlying database.";
3558   GOOGLE_CHECK(mutex_ == nullptr);  // Implied by the above GOOGLE_CHECK.
3559   tables_->known_bad_symbols_.clear();
3560   tables_->known_bad_files_.clear();
3561   return DescriptorBuilder(this, tables_.get(), nullptr).BuildFile(proto);
3562 }
3563 
BuildFileCollectingErrors(const FileDescriptorProto & proto,ErrorCollector * error_collector)3564 const FileDescriptor* DescriptorPool::BuildFileCollectingErrors(
3565     const FileDescriptorProto& proto, ErrorCollector* error_collector) {
3566   GOOGLE_CHECK(fallback_database_ == nullptr)
3567       << "Cannot call BuildFile on a DescriptorPool that uses a "
3568          "DescriptorDatabase.  You must instead find a way to get your file "
3569          "into the underlying database.";
3570   GOOGLE_CHECK(mutex_ == nullptr);  // Implied by the above GOOGLE_CHECK.
3571   tables_->known_bad_symbols_.clear();
3572   tables_->known_bad_files_.clear();
3573   return DescriptorBuilder(this, tables_.get(), error_collector)
3574       .BuildFile(proto);
3575 }
3576 
BuildFileFromDatabase(const FileDescriptorProto & proto) const3577 const FileDescriptor* DescriptorPool::BuildFileFromDatabase(
3578     const FileDescriptorProto& proto) const {
3579   mutex_->AssertHeld();
3580   if (tables_->known_bad_files_.count(proto.name()) > 0) {
3581     return nullptr;
3582   }
3583   const FileDescriptor* result =
3584       DescriptorBuilder(this, tables_.get(), default_error_collector_)
3585           .BuildFile(proto);
3586   if (result == nullptr) {
3587     tables_->known_bad_files_.insert(proto.name());
3588   }
3589   return result;
3590 }
3591 
DescriptorBuilder(const DescriptorPool * pool,DescriptorPool::Tables * tables,DescriptorPool::ErrorCollector * error_collector)3592 DescriptorBuilder::DescriptorBuilder(
3593     const DescriptorPool* pool, DescriptorPool::Tables* tables,
3594     DescriptorPool::ErrorCollector* error_collector)
3595     : pool_(pool),
3596       tables_(tables),
3597       error_collector_(error_collector),
3598       had_errors_(false),
3599       possible_undeclared_dependency_(nullptr),
3600       undefine_resolved_name_("") {}
3601 
~DescriptorBuilder()3602 DescriptorBuilder::~DescriptorBuilder() {}
3603 
AddError(const std::string & element_name,const Message & descriptor,DescriptorPool::ErrorCollector::ErrorLocation location,const std::string & error)3604 void DescriptorBuilder::AddError(
3605     const std::string& element_name, const Message& descriptor,
3606     DescriptorPool::ErrorCollector::ErrorLocation location,
3607     const std::string& error) {
3608   if (error_collector_ == nullptr) {
3609     if (!had_errors_) {
3610       GOOGLE_LOG(ERROR) << "Invalid proto descriptor for file \"" << filename_
3611                  << "\":";
3612     }
3613     GOOGLE_LOG(ERROR) << "  " << element_name << ": " << error;
3614   } else {
3615     error_collector_->AddError(filename_, element_name, &descriptor, location,
3616                                error);
3617   }
3618   had_errors_ = true;
3619 }
3620 
AddError(const std::string & element_name,const Message & descriptor,DescriptorPool::ErrorCollector::ErrorLocation location,const char * error)3621 void DescriptorBuilder::AddError(
3622     const std::string& element_name, const Message& descriptor,
3623     DescriptorPool::ErrorCollector::ErrorLocation location, const char* error) {
3624   AddError(element_name, descriptor, location, std::string(error));
3625 }
3626 
AddNotDefinedError(const std::string & element_name,const Message & descriptor,DescriptorPool::ErrorCollector::ErrorLocation location,const std::string & undefined_symbol)3627 void DescriptorBuilder::AddNotDefinedError(
3628     const std::string& element_name, const Message& descriptor,
3629     DescriptorPool::ErrorCollector::ErrorLocation location,
3630     const std::string& undefined_symbol) {
3631   if (possible_undeclared_dependency_ == nullptr &&
3632       undefine_resolved_name_.empty()) {
3633     AddError(element_name, descriptor, location,
3634              "\"" + undefined_symbol + "\" is not defined.");
3635   } else {
3636     if (possible_undeclared_dependency_ != nullptr) {
3637       AddError(element_name, descriptor, location,
3638                "\"" + possible_undeclared_dependency_name_ +
3639                    "\" seems to be defined in \"" +
3640                    possible_undeclared_dependency_->name() +
3641                    "\", which is not "
3642                    "imported by \"" +
3643                    filename_ +
3644                    "\".  To use it here, please "
3645                    "add the necessary import.");
3646     }
3647     if (!undefine_resolved_name_.empty()) {
3648       AddError(element_name, descriptor, location,
3649                "\"" + undefined_symbol + "\" is resolved to \"" +
3650                    undefine_resolved_name_ +
3651                    "\", which is not defined. "
3652                    "The innermost scope is searched first in name resolution. "
3653                    "Consider using a leading '.'(i.e., \"." +
3654                    undefined_symbol + "\") to start from the outermost scope.");
3655     }
3656   }
3657 }
3658 
AddWarning(const std::string & element_name,const Message & descriptor,DescriptorPool::ErrorCollector::ErrorLocation location,const std::string & error)3659 void DescriptorBuilder::AddWarning(
3660     const std::string& element_name, const Message& descriptor,
3661     DescriptorPool::ErrorCollector::ErrorLocation location,
3662     const std::string& error) {
3663   if (error_collector_ == nullptr) {
3664     GOOGLE_LOG(WARNING) << filename_ << " " << element_name << ": " << error;
3665   } else {
3666     error_collector_->AddWarning(filename_, element_name, &descriptor, location,
3667                                  error);
3668   }
3669 }
3670 
IsInPackage(const FileDescriptor * file,const std::string & package_name)3671 bool DescriptorBuilder::IsInPackage(const FileDescriptor* file,
3672                                     const std::string& package_name) {
3673   return HasPrefixString(file->package(), package_name) &&
3674          (file->package().size() == package_name.size() ||
3675           file->package()[package_name.size()] == '.');
3676 }
3677 
RecordPublicDependencies(const FileDescriptor * file)3678 void DescriptorBuilder::RecordPublicDependencies(const FileDescriptor* file) {
3679   if (file == nullptr || !dependencies_.insert(file).second) return;
3680   for (int i = 0; file != nullptr && i < file->public_dependency_count(); i++) {
3681     RecordPublicDependencies(file->public_dependency(i));
3682   }
3683 }
3684 
FindSymbolNotEnforcingDepsHelper(const DescriptorPool * pool,const std::string & name,bool build_it)3685 Symbol DescriptorBuilder::FindSymbolNotEnforcingDepsHelper(
3686     const DescriptorPool* pool, const std::string& name, bool build_it) {
3687   // If we are looking at an underlay, we must lock its mutex_, since we are
3688   // accessing the underlay's tables_ directly.
3689   MutexLockMaybe lock((pool == pool_) ? nullptr : pool->mutex_);
3690 
3691   Symbol result = pool->tables_->FindSymbol(name);
3692   if (result.IsNull() && pool->underlay_ != nullptr) {
3693     // Symbol not found; check the underlay.
3694     result = FindSymbolNotEnforcingDepsHelper(pool->underlay_, name);
3695   }
3696 
3697   if (result.IsNull()) {
3698     // With lazily_build_dependencies_, a symbol lookup at cross link time is
3699     // not guaranteed to be successful. In most cases, build_it will be false,
3700     // which intentionally prevents us from building an import until it's
3701     // actually needed. In some cases, like registering an extension, we want
3702     // to build the file containing the symbol, and build_it will be set.
3703     // Also, build_it will be true when !lazily_build_dependencies_, to provide
3704     // better error reporting of missing dependencies.
3705     if (build_it && pool->TryFindSymbolInFallbackDatabase(name)) {
3706       result = pool->tables_->FindSymbol(name);
3707     }
3708   }
3709 
3710   return result;
3711 }
3712 
FindSymbolNotEnforcingDeps(const std::string & name,bool build_it)3713 Symbol DescriptorBuilder::FindSymbolNotEnforcingDeps(const std::string& name,
3714                                                      bool build_it) {
3715   Symbol result = FindSymbolNotEnforcingDepsHelper(pool_, name, build_it);
3716   // Only find symbols which were defined in this file or one of its
3717   // dependencies.
3718   const FileDescriptor* file = result.GetFile();
3719   if (file == file_ || dependencies_.count(file) > 0) {
3720     unused_dependency_.erase(file);
3721   }
3722   return result;
3723 }
3724 
FindSymbol(const std::string & name,bool build_it)3725 Symbol DescriptorBuilder::FindSymbol(const std::string& name, bool build_it) {
3726   Symbol result = FindSymbolNotEnforcingDeps(name, build_it);
3727 
3728   if (result.IsNull()) return result;
3729 
3730   if (!pool_->enforce_dependencies_) {
3731     // Hack for CompilerUpgrader, and also used for lazily_build_dependencies_
3732     return result;
3733   }
3734 
3735   // Only find symbols which were defined in this file or one of its
3736   // dependencies.
3737   const FileDescriptor* file = result.GetFile();
3738   if (file == file_ || dependencies_.count(file) > 0) {
3739     return result;
3740   }
3741 
3742   if (result.type == Symbol::PACKAGE) {
3743     // Arg, this is overcomplicated.  The symbol is a package name.  It could
3744     // be that the package was defined in multiple files.  result.GetFile()
3745     // returns the first file we saw that used this package.  We've determined
3746     // that that file is not a direct dependency of the file we are currently
3747     // building, but it could be that some other file which *is* a direct
3748     // dependency also defines the same package.  We can't really rule out this
3749     // symbol unless none of the dependencies define it.
3750     if (IsInPackage(file_, name)) return result;
3751     for (std::set<const FileDescriptor*>::const_iterator it =
3752              dependencies_.begin();
3753          it != dependencies_.end(); ++it) {
3754       // Note:  A dependency may be nullptr if it was not found or had errors.
3755       if (*it != nullptr && IsInPackage(*it, name)) return result;
3756     }
3757   }
3758 
3759   possible_undeclared_dependency_ = file;
3760   possible_undeclared_dependency_name_ = name;
3761   return kNullSymbol;
3762 }
3763 
LookupSymbolNoPlaceholder(const std::string & name,const std::string & relative_to,ResolveMode resolve_mode,bool build_it)3764 Symbol DescriptorBuilder::LookupSymbolNoPlaceholder(
3765     const std::string& name, const std::string& relative_to,
3766     ResolveMode resolve_mode, bool build_it) {
3767   possible_undeclared_dependency_ = nullptr;
3768   undefine_resolved_name_.clear();
3769 
3770   if (!name.empty() && name[0] == '.') {
3771     // Fully-qualified name.
3772     return FindSymbol(name.substr(1), build_it);
3773   }
3774 
3775   // If name is something like "Foo.Bar.baz", and symbols named "Foo" are
3776   // defined in multiple parent scopes, we only want to find "Bar.baz" in the
3777   // innermost one.  E.g., the following should produce an error:
3778   //   message Bar { message Baz {} }
3779   //   message Foo {
3780   //     message Bar {
3781   //     }
3782   //     optional Bar.Baz baz = 1;
3783   //   }
3784   // So, we look for just "Foo" first, then look for "Bar.baz" within it if
3785   // found.
3786   std::string::size_type name_dot_pos = name.find_first_of('.');
3787   std::string first_part_of_name;
3788   if (name_dot_pos == std::string::npos) {
3789     first_part_of_name = name;
3790   } else {
3791     first_part_of_name = name.substr(0, name_dot_pos);
3792   }
3793 
3794   std::string scope_to_try(relative_to);
3795 
3796   while (true) {
3797     // Chop off the last component of the scope.
3798     std::string::size_type dot_pos = scope_to_try.find_last_of('.');
3799     if (dot_pos == std::string::npos) {
3800       return FindSymbol(name, build_it);
3801     } else {
3802       scope_to_try.erase(dot_pos);
3803     }
3804 
3805     // Append ".first_part_of_name" and try to find.
3806     std::string::size_type old_size = scope_to_try.size();
3807     scope_to_try.append(1, '.');
3808     scope_to_try.append(first_part_of_name);
3809     Symbol result = FindSymbol(scope_to_try, build_it);
3810     if (!result.IsNull()) {
3811       if (first_part_of_name.size() < name.size()) {
3812         // name is a compound symbol, of which we only found the first part.
3813         // Now try to look up the rest of it.
3814         if (result.IsAggregate()) {
3815           scope_to_try.append(name, first_part_of_name.size(),
3816                               name.size() - first_part_of_name.size());
3817           result = FindSymbol(scope_to_try, build_it);
3818           if (result.IsNull()) {
3819             undefine_resolved_name_ = scope_to_try;
3820           }
3821           return result;
3822         } else {
3823           // We found a symbol but it's not an aggregate.  Continue the loop.
3824         }
3825       } else {
3826         if (resolve_mode == LOOKUP_TYPES && !result.IsType()) {
3827           // We found a symbol but it's not a type.  Continue the loop.
3828         } else {
3829           return result;
3830         }
3831       }
3832     }
3833 
3834     // Not found.  Remove the name so we can try again.
3835     scope_to_try.erase(old_size);
3836   }
3837 }
3838 
LookupSymbol(const std::string & name,const std::string & relative_to,DescriptorPool::PlaceholderType placeholder_type,ResolveMode resolve_mode,bool build_it)3839 Symbol DescriptorBuilder::LookupSymbol(
3840     const std::string& name, const std::string& relative_to,
3841     DescriptorPool::PlaceholderType placeholder_type, ResolveMode resolve_mode,
3842     bool build_it) {
3843   Symbol result =
3844       LookupSymbolNoPlaceholder(name, relative_to, resolve_mode, build_it);
3845   if (result.IsNull() && pool_->allow_unknown_) {
3846     // Not found, but AllowUnknownDependencies() is enabled.  Return a
3847     // placeholder instead.
3848     result = pool_->NewPlaceholderWithMutexHeld(name, placeholder_type);
3849   }
3850   return result;
3851 }
3852 
ValidateQualifiedName(StringPiece name)3853 static bool ValidateQualifiedName(StringPiece name) {
3854   bool last_was_period = false;
3855 
3856   for (char character : name) {
3857     // I don't trust isalnum() due to locales.  :(
3858     if (('a' <= character && character <= 'z') ||
3859         ('A' <= character && character <= 'Z') ||
3860         ('0' <= character && character <= '9') || (character == '_')) {
3861       last_was_period = false;
3862     } else if (character == '.') {
3863       if (last_was_period) return false;
3864       last_was_period = true;
3865     } else {
3866       return false;
3867     }
3868   }
3869 
3870   return !name.empty() && !last_was_period;
3871 }
3872 
NewPlaceholder(StringPiece name,PlaceholderType placeholder_type) const3873 Symbol DescriptorPool::NewPlaceholder(StringPiece name,
3874                                       PlaceholderType placeholder_type) const {
3875   MutexLockMaybe lock(mutex_);
3876   return NewPlaceholderWithMutexHeld(name, placeholder_type);
3877 }
3878 
NewPlaceholderWithMutexHeld(StringPiece name,PlaceholderType placeholder_type) const3879 Symbol DescriptorPool::NewPlaceholderWithMutexHeld(
3880     StringPiece name, PlaceholderType placeholder_type) const {
3881   if (mutex_) {
3882     mutex_->AssertHeld();
3883   }
3884   // Compute names.
3885   const std::string* placeholder_full_name;
3886   const std::string* placeholder_name;
3887   const std::string* placeholder_package;
3888 
3889   if (!ValidateQualifiedName(name)) return kNullSymbol;
3890   if (name[0] == '.') {
3891     // Fully-qualified.
3892     placeholder_full_name = tables_->AllocateString(name.substr(1));
3893   } else {
3894     placeholder_full_name = tables_->AllocateString(name);
3895   }
3896 
3897   std::string::size_type dotpos = placeholder_full_name->find_last_of('.');
3898   if (dotpos != std::string::npos) {
3899     placeholder_package =
3900         tables_->AllocateString(placeholder_full_name->substr(0, dotpos));
3901     placeholder_name =
3902         tables_->AllocateString(placeholder_full_name->substr(dotpos + 1));
3903   } else {
3904     placeholder_package = &internal::GetEmptyString();
3905     placeholder_name = placeholder_full_name;
3906   }
3907 
3908   // Create the placeholders.
3909   FileDescriptor* placeholder_file = NewPlaceholderFileWithMutexHeld(
3910       *placeholder_full_name + ".placeholder.proto");
3911   placeholder_file->package_ = placeholder_package;
3912 
3913   if (placeholder_type == PLACEHOLDER_ENUM) {
3914     placeholder_file->enum_type_count_ = 1;
3915     placeholder_file->enum_types_ = tables_->AllocateArray<EnumDescriptor>(1);
3916 
3917     EnumDescriptor* placeholder_enum = &placeholder_file->enum_types_[0];
3918     memset(static_cast<void*>(placeholder_enum), 0, sizeof(*placeholder_enum));
3919 
3920     placeholder_enum->full_name_ = placeholder_full_name;
3921     placeholder_enum->name_ = placeholder_name;
3922     placeholder_enum->file_ = placeholder_file;
3923     placeholder_enum->options_ = &EnumOptions::default_instance();
3924     placeholder_enum->is_placeholder_ = true;
3925     placeholder_enum->is_unqualified_placeholder_ = (name[0] != '.');
3926 
3927     // Enums must have at least one value.
3928     placeholder_enum->value_count_ = 1;
3929     placeholder_enum->values_ = tables_->AllocateArray<EnumValueDescriptor>(1);
3930 
3931     EnumValueDescriptor* placeholder_value = &placeholder_enum->values_[0];
3932     memset(static_cast<void*>(placeholder_value), 0,
3933            sizeof(*placeholder_value));
3934 
3935     placeholder_value->name_ = tables_->AllocateString("PLACEHOLDER_VALUE");
3936     // Note that enum value names are siblings of their type, not children.
3937     placeholder_value->full_name_ =
3938         placeholder_package->empty()
3939             ? placeholder_value->name_
3940             : tables_->AllocateString(*placeholder_package +
3941                                       ".PLACEHOLDER_VALUE");
3942 
3943     placeholder_value->number_ = 0;
3944     placeholder_value->type_ = placeholder_enum;
3945     placeholder_value->options_ = &EnumValueOptions::default_instance();
3946 
3947     return Symbol(placeholder_enum);
3948   } else {
3949     placeholder_file->message_type_count_ = 1;
3950     placeholder_file->message_types_ = tables_->AllocateArray<Descriptor>(1);
3951 
3952     Descriptor* placeholder_message = &placeholder_file->message_types_[0];
3953     memset(static_cast<void*>(placeholder_message), 0,
3954            sizeof(*placeholder_message));
3955 
3956     placeholder_message->full_name_ = placeholder_full_name;
3957     placeholder_message->name_ = placeholder_name;
3958     placeholder_message->file_ = placeholder_file;
3959     placeholder_message->options_ = &MessageOptions::default_instance();
3960     placeholder_message->is_placeholder_ = true;
3961     placeholder_message->is_unqualified_placeholder_ = (name[0] != '.');
3962 
3963     if (placeholder_type == PLACEHOLDER_EXTENDABLE_MESSAGE) {
3964       placeholder_message->extension_range_count_ = 1;
3965       placeholder_message->extension_ranges_ =
3966           tables_->AllocateArray<Descriptor::ExtensionRange>(1);
3967       placeholder_message->extension_ranges_->start = 1;
3968       // kMaxNumber + 1 because ExtensionRange::end is exclusive.
3969       placeholder_message->extension_ranges_->end =
3970           FieldDescriptor::kMaxNumber + 1;
3971     }
3972 
3973     return Symbol(placeholder_message);
3974   }
3975 }
3976 
NewPlaceholderFile(StringPiece name) const3977 FileDescriptor* DescriptorPool::NewPlaceholderFile(
3978     StringPiece name) const {
3979   MutexLockMaybe lock(mutex_);
3980   return NewPlaceholderFileWithMutexHeld(name);
3981 }
3982 
NewPlaceholderFileWithMutexHeld(StringPiece name) const3983 FileDescriptor* DescriptorPool::NewPlaceholderFileWithMutexHeld(
3984     StringPiece name) const {
3985   if (mutex_) {
3986     mutex_->AssertHeld();
3987   }
3988   FileDescriptor* placeholder = tables_->Allocate<FileDescriptor>();
3989   memset(static_cast<void*>(placeholder), 0, sizeof(*placeholder));
3990 
3991   placeholder->name_ = tables_->AllocateString(name);
3992   placeholder->package_ = &internal::GetEmptyString();
3993   placeholder->pool_ = this;
3994   placeholder->options_ = &FileOptions::default_instance();
3995   placeholder->tables_ = &FileDescriptorTables::GetEmptyInstance();
3996   placeholder->source_code_info_ = &SourceCodeInfo::default_instance();
3997   placeholder->is_placeholder_ = true;
3998   placeholder->syntax_ = FileDescriptor::SYNTAX_UNKNOWN;
3999   placeholder->finished_building_ = true;
4000   // All other fields are zero or nullptr.
4001 
4002   return placeholder;
4003 }
4004 
AddSymbol(const std::string & full_name,const void * parent,const std::string & name,const Message & proto,Symbol symbol)4005 bool DescriptorBuilder::AddSymbol(const std::string& full_name,
4006                                   const void* parent, const std::string& name,
4007                                   const Message& proto, Symbol symbol) {
4008   // If the caller passed nullptr for the parent, the symbol is at file scope.
4009   // Use its file as the parent instead.
4010   if (parent == nullptr) parent = file_;
4011 
4012   if (full_name.find('\0') != std::string::npos) {
4013     AddError(full_name, proto, DescriptorPool::ErrorCollector::NAME,
4014              "\"" + full_name + "\" contains null character.");
4015     return false;
4016   }
4017   if (tables_->AddSymbol(full_name, symbol)) {
4018     if (!file_tables_->AddAliasUnderParent(parent, name, symbol)) {
4019       // This is only possible if there was already an error adding something of
4020       // the same name.
4021       if (!had_errors_) {
4022         GOOGLE_LOG(DFATAL) << "\"" << full_name
4023                     << "\" not previously defined in "
4024                        "symbols_by_name_, but was defined in "
4025                        "symbols_by_parent_; this shouldn't be possible.";
4026       }
4027       return false;
4028     }
4029     return true;
4030   } else {
4031     const FileDescriptor* other_file = tables_->FindSymbol(full_name).GetFile();
4032     if (other_file == file_) {
4033       std::string::size_type dot_pos = full_name.find_last_of('.');
4034       if (dot_pos == std::string::npos) {
4035         AddError(full_name, proto, DescriptorPool::ErrorCollector::NAME,
4036                  "\"" + full_name + "\" is already defined.");
4037       } else {
4038         AddError(full_name, proto, DescriptorPool::ErrorCollector::NAME,
4039                  "\"" + full_name.substr(dot_pos + 1) +
4040                      "\" is already defined in \"" +
4041                      full_name.substr(0, dot_pos) + "\".");
4042       }
4043     } else {
4044       // Symbol seems to have been defined in a different file.
4045       AddError(full_name, proto, DescriptorPool::ErrorCollector::NAME,
4046                "\"" + full_name + "\" is already defined in file \"" +
4047                    (other_file == nullptr ? "null" : other_file->name()) +
4048                    "\".");
4049     }
4050     return false;
4051   }
4052 }
4053 
AddPackage(const std::string & name,const Message & proto,const FileDescriptor * file)4054 void DescriptorBuilder::AddPackage(const std::string& name,
4055                                    const Message& proto,
4056                                    const FileDescriptor* file) {
4057   if (name.find('\0') != std::string::npos) {
4058     AddError(name, proto, DescriptorPool::ErrorCollector::NAME,
4059              "\"" + name + "\" contains null character.");
4060     return;
4061   }
4062   if (tables_->AddSymbol(name, Symbol(file))) {
4063     // Success.  Also add parent package, if any.
4064     std::string::size_type dot_pos = name.find_last_of('.');
4065     if (dot_pos == std::string::npos) {
4066       // No parents.
4067       ValidateSymbolName(name, name, proto);
4068     } else {
4069       // Has parent.
4070       std::string* parent_name =
4071           tables_->AllocateString(name.substr(0, dot_pos));
4072       AddPackage(*parent_name, proto, file);
4073       ValidateSymbolName(name.substr(dot_pos + 1), name, proto);
4074     }
4075   } else {
4076     Symbol existing_symbol = tables_->FindSymbol(name);
4077     // It's OK to redefine a package.
4078     if (existing_symbol.type != Symbol::PACKAGE) {
4079       // Symbol seems to have been defined in a different file.
4080       AddError(name, proto, DescriptorPool::ErrorCollector::NAME,
4081                "\"" + name +
4082                    "\" is already defined (as something other than "
4083                    "a package) in file \"" +
4084                    existing_symbol.GetFile()->name() + "\".");
4085     }
4086   }
4087 }
4088 
ValidateSymbolName(const std::string & name,const std::string & full_name,const Message & proto)4089 void DescriptorBuilder::ValidateSymbolName(const std::string& name,
4090                                            const std::string& full_name,
4091                                            const Message& proto) {
4092   if (name.empty()) {
4093     AddError(full_name, proto, DescriptorPool::ErrorCollector::NAME,
4094              "Missing name.");
4095   } else {
4096     for (char character : name) {
4097       // I don't trust isalnum() due to locales.  :(
4098       if ((character < 'a' || 'z' < character) &&
4099           (character < 'A' || 'Z' < character) &&
4100           (character < '0' || '9' < character) && (character != '_')) {
4101         AddError(full_name, proto, DescriptorPool::ErrorCollector::NAME,
4102                  "\"" + name + "\" is not a valid identifier.");
4103       }
4104     }
4105   }
4106 }
4107 
4108 // -------------------------------------------------------------------
4109 
4110 // This generic implementation is good for all descriptors except
4111 // FileDescriptor.
4112 template <class DescriptorT>
AllocateOptions(const typename DescriptorT::OptionsType & orig_options,DescriptorT * descriptor,int options_field_tag,const std::string & option_name)4113 void DescriptorBuilder::AllocateOptions(
4114     const typename DescriptorT::OptionsType& orig_options,
4115     DescriptorT* descriptor, int options_field_tag,
4116     const std::string& option_name) {
4117   std::vector<int> options_path;
4118   descriptor->GetLocationPath(&options_path);
4119   options_path.push_back(options_field_tag);
4120   AllocateOptionsImpl(descriptor->full_name(), descriptor->full_name(),
4121                       orig_options, descriptor, options_path, option_name);
4122 }
4123 
4124 // We specialize for FileDescriptor.
AllocateOptions(const FileOptions & orig_options,FileDescriptor * descriptor)4125 void DescriptorBuilder::AllocateOptions(const FileOptions& orig_options,
4126                                         FileDescriptor* descriptor) {
4127   std::vector<int> options_path;
4128   options_path.push_back(FileDescriptorProto::kOptionsFieldNumber);
4129   // We add the dummy token so that LookupSymbol does the right thing.
4130   AllocateOptionsImpl(descriptor->package() + ".dummy", descriptor->name(),
4131                       orig_options, descriptor, options_path,
4132                       "google.protobuf.FileOptions");
4133 }
4134 
4135 template <class DescriptorT>
AllocateOptionsImpl(const std::string & name_scope,const std::string & element_name,const typename DescriptorT::OptionsType & orig_options,DescriptorT * descriptor,const std::vector<int> & options_path,const std::string & option_name)4136 void DescriptorBuilder::AllocateOptionsImpl(
4137     const std::string& name_scope, const std::string& element_name,
4138     const typename DescriptorT::OptionsType& orig_options,
4139     DescriptorT* descriptor, const std::vector<int>& options_path,
4140     const std::string& option_name) {
4141   // We need to use a dummy pointer to work around a bug in older versions of
4142   // GCC.  Otherwise, the following two lines could be replaced with:
4143   //   typename DescriptorT::OptionsType* options =
4144   //       tables_->AllocateMessage<typename DescriptorT::OptionsType>();
4145   typename DescriptorT::OptionsType* const dummy = nullptr;
4146   typename DescriptorT::OptionsType* options = tables_->AllocateMessage(dummy);
4147 
4148   if (!orig_options.IsInitialized()) {
4149     AddError(name_scope + "." + element_name, orig_options,
4150              DescriptorPool::ErrorCollector::OPTION_NAME,
4151              "Uninterpreted option is missing name or value.");
4152     return;
4153   }
4154 
4155   // Avoid using MergeFrom()/CopyFrom() in this class to make it -fno-rtti
4156   // friendly. Without RTTI, MergeFrom() and CopyFrom() will fallback to the
4157   // reflection based method, which requires the Descriptor. However, we are in
4158   // the middle of building the descriptors, thus the deadlock.
4159   options->ParseFromString(orig_options.SerializeAsString());
4160   descriptor->options_ = options;
4161 
4162   // Don't add to options_to_interpret_ unless there were uninterpreted
4163   // options.  This not only avoids unnecessary work, but prevents a
4164   // bootstrapping problem when building descriptors for descriptor.proto.
4165   // descriptor.proto does not contain any uninterpreted options, but
4166   // attempting to interpret options anyway will cause
4167   // OptionsType::GetDescriptor() to be called which may then deadlock since
4168   // we're still trying to build it.
4169   if (options->uninterpreted_option_size() > 0) {
4170     options_to_interpret_.push_back(OptionsToInterpret(
4171         name_scope, element_name, options_path, &orig_options, options));
4172   }
4173 
4174   // If the custom option is in unknown fields, no need to interpret it.
4175   // Remove the dependency file from unused_dependency.
4176   const UnknownFieldSet& unknown_fields = orig_options.unknown_fields();
4177   if (!unknown_fields.empty()) {
4178     // Can not use options->GetDescriptor() which may case deadlock.
4179     Symbol msg_symbol = tables_->FindSymbol(option_name);
4180     if (msg_symbol.type == Symbol::MESSAGE) {
4181       for (int i = 0; i < unknown_fields.field_count(); ++i) {
4182         assert_mutex_held(pool_);
4183         const FieldDescriptor* field =
4184             pool_->InternalFindExtensionByNumberNoLock(
4185                 msg_symbol.descriptor, unknown_fields.field(i).number());
4186         if (field) {
4187           unused_dependency_.erase(field->file());
4188         }
4189       }
4190     }
4191   }
4192 }
4193 
4194 // A common pattern:  We want to convert a repeated field in the descriptor
4195 // to an array of values, calling some method to build each value.
4196 #define BUILD_ARRAY(INPUT, OUTPUT, NAME, METHOD, PARENT) \
4197   OUTPUT->NAME##_count_ = INPUT.NAME##_size();           \
4198   AllocateArray(INPUT.NAME##_size(), &OUTPUT->NAME##s_); \
4199   for (int i = 0; i < INPUT.NAME##_size(); i++) {        \
4200     METHOD(INPUT.NAME(i), PARENT, OUTPUT->NAME##s_ + i); \
4201   }
4202 
AddRecursiveImportError(const FileDescriptorProto & proto,int from_here)4203 void DescriptorBuilder::AddRecursiveImportError(
4204     const FileDescriptorProto& proto, int from_here) {
4205   std::string error_message("File recursively imports itself: ");
4206   for (size_t i = from_here; i < tables_->pending_files_.size(); i++) {
4207     error_message.append(tables_->pending_files_[i]);
4208     error_message.append(" -> ");
4209   }
4210   error_message.append(proto.name());
4211 
4212   if (static_cast<size_t>(from_here) < tables_->pending_files_.size() - 1) {
4213     AddError(tables_->pending_files_[from_here + 1], proto,
4214              DescriptorPool::ErrorCollector::IMPORT, error_message);
4215   } else {
4216     AddError(proto.name(), proto, DescriptorPool::ErrorCollector::IMPORT,
4217              error_message);
4218   }
4219 }
4220 
AddTwiceListedError(const FileDescriptorProto & proto,int index)4221 void DescriptorBuilder::AddTwiceListedError(const FileDescriptorProto& proto,
4222                                             int index) {
4223   AddError(proto.dependency(index), proto,
4224            DescriptorPool::ErrorCollector::IMPORT,
4225            "Import \"" + proto.dependency(index) + "\" was listed twice.");
4226 }
4227 
AddImportError(const FileDescriptorProto & proto,int index)4228 void DescriptorBuilder::AddImportError(const FileDescriptorProto& proto,
4229                                        int index) {
4230   std::string message;
4231   if (pool_->fallback_database_ == nullptr) {
4232     message = "Import \"" + proto.dependency(index) + "\" has not been loaded.";
4233   } else {
4234     message = "Import \"" + proto.dependency(index) +
4235               "\" was not found or had errors.";
4236   }
4237   AddError(proto.dependency(index), proto,
4238            DescriptorPool::ErrorCollector::IMPORT, message);
4239 }
4240 
ExistingFileMatchesProto(const FileDescriptor * existing_file,const FileDescriptorProto & proto)4241 static bool ExistingFileMatchesProto(const FileDescriptor* existing_file,
4242                                      const FileDescriptorProto& proto) {
4243   FileDescriptorProto existing_proto;
4244   existing_file->CopyTo(&existing_proto);
4245   // TODO(liujisi): Remove it when CopyTo supports copying syntax params when
4246   // syntax="proto2".
4247   if (existing_file->syntax() == FileDescriptor::SYNTAX_PROTO2 &&
4248       proto.has_syntax()) {
4249     existing_proto.set_syntax(
4250         existing_file->SyntaxName(existing_file->syntax()));
4251   }
4252 
4253   return existing_proto.SerializeAsString() == proto.SerializeAsString();
4254 }
4255 
BuildFile(const FileDescriptorProto & proto)4256 const FileDescriptor* DescriptorBuilder::BuildFile(
4257     const FileDescriptorProto& proto) {
4258   filename_ = proto.name();
4259 
4260   // Check if the file already exists and is identical to the one being built.
4261   // Note:  This only works if the input is canonical -- that is, it
4262   //   fully-qualifies all type names, has no UninterpretedOptions, etc.
4263   //   This is fine, because this idempotency "feature" really only exists to
4264   //   accommodate one hack in the proto1->proto2 migration layer.
4265   const FileDescriptor* existing_file = tables_->FindFile(filename_);
4266   if (existing_file != nullptr) {
4267     // File already in pool.  Compare the existing one to the input.
4268     if (ExistingFileMatchesProto(existing_file, proto)) {
4269       // They're identical.  Return the existing descriptor.
4270       return existing_file;
4271     }
4272 
4273     // Not a match.  The error will be detected and handled later.
4274   }
4275 
4276   // Check to see if this file is already on the pending files list.
4277   // TODO(kenton):  Allow recursive imports?  It may not work with some
4278   //   (most?) programming languages.  E.g., in C++, a forward declaration
4279   //   of a type is not sufficient to allow it to be used even in a
4280   //   generated header file due to inlining.  This could perhaps be
4281   //   worked around using tricks involving inserting #include statements
4282   //   mid-file, but that's pretty ugly, and I'm pretty sure there are
4283   //   some languages out there that do not allow recursive dependencies
4284   //   at all.
4285   for (size_t i = 0; i < tables_->pending_files_.size(); i++) {
4286     if (tables_->pending_files_[i] == proto.name()) {
4287       AddRecursiveImportError(proto, i);
4288       return nullptr;
4289     }
4290   }
4291 
4292   // If we have a fallback_database_, and we aren't doing lazy import building,
4293   // attempt to load all dependencies now, before checkpointing tables_.  This
4294   // avoids confusion with recursive checkpoints.
4295   if (!pool_->lazily_build_dependencies_) {
4296     if (pool_->fallback_database_ != nullptr) {
4297       tables_->pending_files_.push_back(proto.name());
4298       for (int i = 0; i < proto.dependency_size(); i++) {
4299         if (tables_->FindFile(proto.dependency(i)) == nullptr &&
4300             (pool_->underlay_ == nullptr ||
4301              pool_->underlay_->FindFileByName(proto.dependency(i)) ==
4302                  nullptr)) {
4303           // We don't care what this returns since we'll find out below anyway.
4304           pool_->TryFindFileInFallbackDatabase(proto.dependency(i));
4305         }
4306       }
4307       tables_->pending_files_.pop_back();
4308     }
4309   }
4310 
4311   // Checkpoint the tables so that we can roll back if something goes wrong.
4312   tables_->AddCheckpoint();
4313 
4314   FileDescriptor* result = BuildFileImpl(proto);
4315 
4316   file_tables_->FinalizeTables();
4317   if (result) {
4318     tables_->ClearLastCheckpoint();
4319     result->finished_building_ = true;
4320   } else {
4321     tables_->RollbackToLastCheckpoint();
4322   }
4323 
4324   return result;
4325 }
4326 
BuildFileImpl(const FileDescriptorProto & proto)4327 FileDescriptor* DescriptorBuilder::BuildFileImpl(
4328     const FileDescriptorProto& proto) {
4329   FileDescriptor* result = tables_->Allocate<FileDescriptor>();
4330   file_ = result;
4331 
4332   result->is_placeholder_ = false;
4333   result->finished_building_ = false;
4334   SourceCodeInfo* info = nullptr;
4335   if (proto.has_source_code_info()) {
4336     info = tables_->AllocateMessage<SourceCodeInfo>();
4337     info->CopyFrom(proto.source_code_info());
4338     result->source_code_info_ = info;
4339   } else {
4340     result->source_code_info_ = &SourceCodeInfo::default_instance();
4341   }
4342 
4343   file_tables_ = tables_->AllocateFileTables();
4344   file_->tables_ = file_tables_;
4345 
4346   if (!proto.has_name()) {
4347     AddError("", proto, DescriptorPool::ErrorCollector::OTHER,
4348              "Missing field: FileDescriptorProto.name.");
4349   }
4350 
4351   // TODO(liujisi): Report error when the syntax is empty after all the protos
4352   // have added the syntax statement.
4353   if (proto.syntax().empty() || proto.syntax() == "proto2") {
4354     file_->syntax_ = FileDescriptor::SYNTAX_PROTO2;
4355   } else if (proto.syntax() == "proto3") {
4356     file_->syntax_ = FileDescriptor::SYNTAX_PROTO3;
4357   } else {
4358     file_->syntax_ = FileDescriptor::SYNTAX_UNKNOWN;
4359     AddError(proto.name(), proto, DescriptorPool::ErrorCollector::OTHER,
4360              "Unrecognized syntax: " + proto.syntax());
4361   }
4362 
4363   result->name_ = tables_->AllocateString(proto.name());
4364   if (proto.has_package()) {
4365     result->package_ = tables_->AllocateString(proto.package());
4366   } else {
4367     // We cannot rely on proto.package() returning a valid string if
4368     // proto.has_package() is false, because we might be running at static
4369     // initialization time, in which case default values have not yet been
4370     // initialized.
4371     result->package_ = tables_->AllocateString("");
4372   }
4373   result->pool_ = pool_;
4374 
4375   if (result->name().find('\0') != std::string::npos) {
4376     AddError(result->name(), proto, DescriptorPool::ErrorCollector::NAME,
4377              "\"" + result->name() + "\" contains null character.");
4378     return nullptr;
4379   }
4380 
4381   // Add to tables.
4382   if (!tables_->AddFile(result)) {
4383     AddError(proto.name(), proto, DescriptorPool::ErrorCollector::OTHER,
4384              "A file with this name is already in the pool.");
4385     // Bail out early so that if this is actually the exact same file, we
4386     // don't end up reporting that every single symbol is already defined.
4387     return nullptr;
4388   }
4389   if (!result->package().empty()) {
4390     AddPackage(result->package(), proto, result);
4391   }
4392 
4393   // Make sure all dependencies are loaded.
4394   std::set<std::string> seen_dependencies;
4395   result->dependency_count_ = proto.dependency_size();
4396   result->dependencies_ =
4397       tables_->AllocateArray<const FileDescriptor*>(proto.dependency_size());
4398   if (pool_->lazily_build_dependencies_) {
4399     result->dependencies_once_ = tables_->AllocateOnceDynamic();
4400     result->dependencies_names_ =
4401         tables_->AllocateArray<const std::string*>(proto.dependency_size());
4402     if (proto.dependency_size() > 0) {
4403       memset(result->dependencies_names_, 0,
4404              sizeof(*result->dependencies_names_) * proto.dependency_size());
4405     }
4406   } else {
4407     result->dependencies_once_ = nullptr;
4408     result->dependencies_names_ = nullptr;
4409   }
4410   unused_dependency_.clear();
4411   std::set<int> weak_deps;
4412   for (int i = 0; i < proto.weak_dependency_size(); ++i) {
4413     weak_deps.insert(proto.weak_dependency(i));
4414   }
4415   for (int i = 0; i < proto.dependency_size(); i++) {
4416     if (!seen_dependencies.insert(proto.dependency(i)).second) {
4417       AddTwiceListedError(proto, i);
4418     }
4419 
4420     const FileDescriptor* dependency = tables_->FindFile(proto.dependency(i));
4421     if (dependency == nullptr && pool_->underlay_ != nullptr) {
4422       dependency = pool_->underlay_->FindFileByName(proto.dependency(i));
4423     }
4424 
4425     if (dependency == result) {
4426       // Recursive import.  dependency/result is not fully initialized, and it's
4427       // dangerous to try to do anything with it.  The recursive import error
4428       // will be detected and reported in DescriptorBuilder::BuildFile().
4429       return nullptr;
4430     }
4431 
4432     if (dependency == nullptr) {
4433       if (!pool_->lazily_build_dependencies_) {
4434         if (pool_->allow_unknown_ ||
4435             (!pool_->enforce_weak_ && weak_deps.find(i) != weak_deps.end())) {
4436           dependency =
4437               pool_->NewPlaceholderFileWithMutexHeld(proto.dependency(i));
4438         } else {
4439           AddImportError(proto, i);
4440         }
4441       }
4442     } else {
4443       // Add to unused_dependency_ to track unused imported files.
4444       // Note: do not track unused imported files for public import.
4445       if (pool_->enforce_dependencies_ &&
4446           (pool_->unused_import_track_files_.find(proto.name()) !=
4447            pool_->unused_import_track_files_.end()) &&
4448           (dependency->public_dependency_count() == 0)) {
4449         unused_dependency_.insert(dependency);
4450       }
4451     }
4452 
4453     result->dependencies_[i] = dependency;
4454     if (pool_->lazily_build_dependencies_ && !dependency) {
4455       result->dependencies_names_[i] =
4456           tables_->AllocateString(proto.dependency(i));
4457     }
4458   }
4459 
4460   // Check public dependencies.
4461   int public_dependency_count = 0;
4462   result->public_dependencies_ =
4463       tables_->AllocateArray<int>(proto.public_dependency_size());
4464   for (int i = 0; i < proto.public_dependency_size(); i++) {
4465     // Only put valid public dependency indexes.
4466     int index = proto.public_dependency(i);
4467     if (index >= 0 && index < proto.dependency_size()) {
4468       result->public_dependencies_[public_dependency_count++] = index;
4469       // Do not track unused imported files for public import.
4470       // Calling dependency(i) builds that file when doing lazy imports,
4471       // need to avoid doing this. Unused dependency detection isn't done
4472       // when building lazily, anyways.
4473       if (!pool_->lazily_build_dependencies_) {
4474         unused_dependency_.erase(result->dependency(index));
4475       }
4476     } else {
4477       AddError(proto.name(), proto, DescriptorPool::ErrorCollector::OTHER,
4478                "Invalid public dependency index.");
4479     }
4480   }
4481   result->public_dependency_count_ = public_dependency_count;
4482 
4483   // Build dependency set
4484   dependencies_.clear();
4485   // We don't/can't do proper dependency error checking when
4486   // lazily_build_dependencies_, and calling dependency(i) will force
4487   // a dependency to be built, which we don't want.
4488   if (!pool_->lazily_build_dependencies_) {
4489     for (int i = 0; i < result->dependency_count(); i++) {
4490       RecordPublicDependencies(result->dependency(i));
4491     }
4492   }
4493 
4494   // Check weak dependencies.
4495   int weak_dependency_count = 0;
4496   result->weak_dependencies_ =
4497       tables_->AllocateArray<int>(proto.weak_dependency_size());
4498   for (int i = 0; i < proto.weak_dependency_size(); i++) {
4499     int index = proto.weak_dependency(i);
4500     if (index >= 0 && index < proto.dependency_size()) {
4501       result->weak_dependencies_[weak_dependency_count++] = index;
4502     } else {
4503       AddError(proto.name(), proto, DescriptorPool::ErrorCollector::OTHER,
4504                "Invalid weak dependency index.");
4505     }
4506   }
4507   result->weak_dependency_count_ = weak_dependency_count;
4508 
4509   // Convert children.
4510   BUILD_ARRAY(proto, result, message_type, BuildMessage, nullptr);
4511   BUILD_ARRAY(proto, result, enum_type, BuildEnum, nullptr);
4512   BUILD_ARRAY(proto, result, service, BuildService, nullptr);
4513   BUILD_ARRAY(proto, result, extension, BuildExtension, nullptr);
4514 
4515   // Copy options.
4516   result->options_ = nullptr;  // Set to default_instance later if necessary.
4517   if (proto.has_options()) {
4518     AllocateOptions(proto.options(), result);
4519   }
4520 
4521   // Note that the following steps must occur in exactly the specified order.
4522 
4523   // Cross-link.
4524   CrossLinkFile(result, proto);
4525 
4526   // Interpret any remaining uninterpreted options gathered into
4527   // options_to_interpret_ during descriptor building.  Cross-linking has made
4528   // extension options known, so all interpretations should now succeed.
4529   if (!had_errors_) {
4530     OptionInterpreter option_interpreter(this);
4531     for (std::vector<OptionsToInterpret>::iterator iter =
4532              options_to_interpret_.begin();
4533          iter != options_to_interpret_.end(); ++iter) {
4534       option_interpreter.InterpretOptions(&(*iter));
4535     }
4536     options_to_interpret_.clear();
4537     if (info != nullptr) {
4538       option_interpreter.UpdateSourceCodeInfo(info);
4539     }
4540   }
4541 
4542   // Validate options. See comments at InternalSetLazilyBuildDependencies about
4543   // error checking and lazy import building.
4544   if (!had_errors_ && !pool_->lazily_build_dependencies_) {
4545     ValidateFileOptions(result, proto);
4546   }
4547 
4548   // Additional naming conflict check for map entry types. Only need to check
4549   // this if there are already errors.
4550   if (had_errors_) {
4551     for (int i = 0; i < proto.message_type_size(); ++i) {
4552       DetectMapConflicts(result->message_type(i), proto.message_type(i));
4553     }
4554   }
4555 
4556 
4557   // Again, see comments at InternalSetLazilyBuildDependencies about error
4558   // checking. Also, don't log unused dependencies if there were previous
4559   // errors, since the results might be inaccurate.
4560   if (!had_errors_ && !unused_dependency_.empty() &&
4561       !pool_->lazily_build_dependencies_) {
4562     LogUnusedDependency(proto, result);
4563   }
4564 
4565   if (had_errors_) {
4566     return nullptr;
4567   } else {
4568     return result;
4569   }
4570 }
4571 
4572 
AllocateNameString(const std::string & scope,const std::string & proto_name)4573 std::string* DescriptorBuilder::AllocateNameString(
4574     const std::string& scope, const std::string& proto_name) {
4575   std::string* full_name;
4576   if (scope.empty()) {
4577     full_name = tables_->AllocateString(proto_name);
4578   } else {
4579     full_name = tables_->AllocateEmptyString();
4580     *full_name = StrCat(scope, ".", proto_name);
4581   }
4582   return full_name;
4583 }
4584 
BuildMessage(const DescriptorProto & proto,const Descriptor * parent,Descriptor * result)4585 void DescriptorBuilder::BuildMessage(const DescriptorProto& proto,
4586                                      const Descriptor* parent,
4587                                      Descriptor* result) {
4588   const std::string& scope =
4589       (parent == nullptr) ? file_->package() : parent->full_name();
4590   std::string* full_name = AllocateNameString(scope, proto.name());
4591   ValidateSymbolName(proto.name(), *full_name, proto);
4592 
4593   result->name_ = tables_->AllocateString(proto.name());
4594   result->full_name_ = full_name;
4595   result->file_ = file_;
4596   result->containing_type_ = parent;
4597   result->is_placeholder_ = false;
4598   result->is_unqualified_placeholder_ = false;
4599   result->well_known_type_ = Descriptor::WELLKNOWNTYPE_UNSPECIFIED;
4600 
4601   auto it = pool_->tables_->well_known_types_.find(*full_name);
4602   if (it != pool_->tables_->well_known_types_.end()) {
4603     result->well_known_type_ = it->second;
4604   }
4605 
4606   // Build oneofs first so that fields and extension ranges can refer to them.
4607   BUILD_ARRAY(proto, result, oneof_decl, BuildOneof, result);
4608   BUILD_ARRAY(proto, result, field, BuildField, result);
4609   BUILD_ARRAY(proto, result, nested_type, BuildMessage, result);
4610   BUILD_ARRAY(proto, result, enum_type, BuildEnum, result);
4611   BUILD_ARRAY(proto, result, extension_range, BuildExtensionRange, result);
4612   BUILD_ARRAY(proto, result, extension, BuildExtension, result);
4613   BUILD_ARRAY(proto, result, reserved_range, BuildReservedRange, result);
4614 
4615   // Copy reserved names.
4616   int reserved_name_count = proto.reserved_name_size();
4617   result->reserved_name_count_ = reserved_name_count;
4618   result->reserved_names_ =
4619       tables_->AllocateArray<const std::string*>(reserved_name_count);
4620   for (int i = 0; i < reserved_name_count; ++i) {
4621     result->reserved_names_[i] =
4622         tables_->AllocateString(proto.reserved_name(i));
4623   }
4624 
4625   // Copy options.
4626   result->options_ = nullptr;  // Set to default_instance later if necessary.
4627   if (proto.has_options()) {
4628     AllocateOptions(proto.options(), result,
4629                     DescriptorProto::kOptionsFieldNumber,
4630                     "google.protobuf.MessageOptions");
4631   }
4632 
4633   AddSymbol(result->full_name(), parent, result->name(), proto, Symbol(result));
4634 
4635   for (int i = 0; i < proto.reserved_range_size(); i++) {
4636     const DescriptorProto_ReservedRange& range1 = proto.reserved_range(i);
4637     for (int j = i + 1; j < proto.reserved_range_size(); j++) {
4638       const DescriptorProto_ReservedRange& range2 = proto.reserved_range(j);
4639       if (range1.end() > range2.start() && range2.end() > range1.start()) {
4640         AddError(result->full_name(), proto.reserved_range(i),
4641                  DescriptorPool::ErrorCollector::NUMBER,
4642                  strings::Substitute("Reserved range $0 to $1 overlaps with "
4643                                   "already-defined range $2 to $3.",
4644                                   range2.start(), range2.end() - 1,
4645                                   range1.start(), range1.end() - 1));
4646       }
4647     }
4648   }
4649 
4650   HASH_SET<std::string> reserved_name_set;
4651   for (int i = 0; i < proto.reserved_name_size(); i++) {
4652     const std::string& name = proto.reserved_name(i);
4653     if (reserved_name_set.find(name) == reserved_name_set.end()) {
4654       reserved_name_set.insert(name);
4655     } else {
4656       AddError(name, proto, DescriptorPool::ErrorCollector::NAME,
4657                strings::Substitute("Field name \"$0\" is reserved multiple times.",
4658                                 name));
4659     }
4660   }
4661 
4662 
4663   for (int i = 0; i < result->field_count(); i++) {
4664     const FieldDescriptor* field = result->field(i);
4665     for (int j = 0; j < result->extension_range_count(); j++) {
4666       const Descriptor::ExtensionRange* range = result->extension_range(j);
4667       if (range->start <= field->number() && field->number() < range->end) {
4668         AddError(
4669             field->full_name(), proto.extension_range(j),
4670             DescriptorPool::ErrorCollector::NUMBER,
4671             strings::Substitute(
4672                 "Extension range $0 to $1 includes field \"$2\" ($3).",
4673                 range->start, range->end - 1, field->name(), field->number()));
4674       }
4675     }
4676     for (int j = 0; j < result->reserved_range_count(); j++) {
4677       const Descriptor::ReservedRange* range = result->reserved_range(j);
4678       if (range->start <= field->number() && field->number() < range->end) {
4679         AddError(field->full_name(), proto.reserved_range(j),
4680                  DescriptorPool::ErrorCollector::NUMBER,
4681                  strings::Substitute("Field \"$0\" uses reserved number $1.",
4682                                   field->name(), field->number()));
4683       }
4684     }
4685     if (reserved_name_set.find(field->name()) != reserved_name_set.end()) {
4686       AddError(
4687           field->full_name(), proto.field(i),
4688           DescriptorPool::ErrorCollector::NAME,
4689           strings::Substitute("Field name \"$0\" is reserved.", field->name()));
4690     }
4691 
4692   }
4693 
4694   // Check that extension ranges don't overlap and don't include
4695   // reserved field numbers or names.
4696   for (int i = 0; i < result->extension_range_count(); i++) {
4697     const Descriptor::ExtensionRange* range1 = result->extension_range(i);
4698     for (int j = 0; j < result->reserved_range_count(); j++) {
4699       const Descriptor::ReservedRange* range2 = result->reserved_range(j);
4700       if (range1->end > range2->start && range2->end > range1->start) {
4701         AddError(result->full_name(), proto.extension_range(i),
4702                  DescriptorPool::ErrorCollector::NUMBER,
4703                  strings::Substitute("Extension range $0 to $1 overlaps with "
4704                                   "reserved range $2 to $3.",
4705                                   range1->start, range1->end - 1, range2->start,
4706                                   range2->end - 1));
4707       }
4708     }
4709     for (int j = i + 1; j < result->extension_range_count(); j++) {
4710       const Descriptor::ExtensionRange* range2 = result->extension_range(j);
4711       if (range1->end > range2->start && range2->end > range1->start) {
4712         AddError(result->full_name(), proto.extension_range(i),
4713                  DescriptorPool::ErrorCollector::NUMBER,
4714                  strings::Substitute("Extension range $0 to $1 overlaps with "
4715                                   "already-defined range $2 to $3.",
4716                                   range2->start, range2->end - 1, range1->start,
4717                                   range1->end - 1));
4718       }
4719     }
4720   }
4721 }
4722 
BuildFieldOrExtension(const FieldDescriptorProto & proto,Descriptor * parent,FieldDescriptor * result,bool is_extension)4723 void DescriptorBuilder::BuildFieldOrExtension(const FieldDescriptorProto& proto,
4724                                               Descriptor* parent,
4725                                               FieldDescriptor* result,
4726                                               bool is_extension) {
4727   const std::string& scope =
4728       (parent == nullptr) ? file_->package() : parent->full_name();
4729   std::string* full_name = AllocateNameString(scope, proto.name());
4730   ValidateSymbolName(proto.name(), *full_name, proto);
4731 
4732   result->name_ = tables_->AllocateString(proto.name());
4733   result->full_name_ = full_name;
4734   result->file_ = file_;
4735   result->number_ = proto.number();
4736   result->is_extension_ = is_extension;
4737   result->proto3_optional_ = proto.proto3_optional();
4738 
4739   if (proto.proto3_optional() &&
4740       file_->syntax() != FileDescriptor::SYNTAX_PROTO3) {
4741     AddError(result->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
4742              "The [proto3_optional=true] option may only be set on proto3"
4743              "fields, not " +
4744                  result->full_name());
4745   }
4746 
4747   // If .proto files follow the style guide then the name should already be
4748   // lower-cased.  If that's the case we can just reuse the string we
4749   // already allocated rather than allocate a new one.
4750   std::string lowercase_name(proto.name());
4751   LowerString(&lowercase_name);
4752   if (lowercase_name == proto.name()) {
4753     result->lowercase_name_ = result->name_;
4754   } else {
4755     result->lowercase_name_ = tables_->AllocateString(lowercase_name);
4756   }
4757 
4758   // Don't bother with the above optimization for camel-case names since
4759   // .proto files that follow the guide shouldn't be using names in this
4760   // format, so the optimization wouldn't help much.
4761   result->camelcase_name_ =
4762       tables_->AllocateString(ToCamelCase(proto.name(),
4763                                           /* lower_first = */ true));
4764 
4765   if (proto.has_json_name()) {
4766     result->has_json_name_ = true;
4767     result->json_name_ = tables_->AllocateString(proto.json_name());
4768   } else {
4769     result->has_json_name_ = false;
4770     result->json_name_ = tables_->AllocateString(ToJsonName(proto.name()));
4771   }
4772 
4773   // Some compilers do not allow static_cast directly between two enum types,
4774   // so we must cast to int first.
4775   result->type_ = static_cast<FieldDescriptor::Type>(
4776       implicit_cast<int>(proto.type()));
4777   result->label_ = static_cast<FieldDescriptor::Label>(
4778       implicit_cast<int>(proto.label()));
4779 
4780   if (result->label_ == FieldDescriptor::LABEL_REQUIRED) {
4781     // An extension cannot have a required field (b/13365836).
4782     if (result->is_extension_) {
4783       AddError(result->full_name(), proto,
4784                // Error location `TYPE`: we would really like to indicate
4785                // `LABEL`, but the `ErrorLocation` enum has no entry for this,
4786                // and we don't necessarily know about all implementations of the
4787                // `ErrorCollector` interface to extend them to handle the new
4788                // error location type properly.
4789                DescriptorPool::ErrorCollector::TYPE,
4790                "The extension " + result->full_name() + " cannot be required.");
4791     }
4792   }
4793 
4794   // Some of these may be filled in when cross-linking.
4795   result->containing_type_ = nullptr;
4796   result->extension_scope_ = nullptr;
4797   result->message_type_ = nullptr;
4798   result->enum_type_ = nullptr;
4799   result->type_name_ = nullptr;
4800   result->type_once_ = nullptr;
4801   result->default_value_enum_ = nullptr;
4802   result->default_value_enum_name_ = nullptr;
4803 
4804   result->has_default_value_ = proto.has_default_value();
4805   if (proto.has_default_value() && result->is_repeated()) {
4806     AddError(result->full_name(), proto,
4807              DescriptorPool::ErrorCollector::DEFAULT_VALUE,
4808              "Repeated fields can't have default values.");
4809   }
4810 
4811   if (proto.has_type()) {
4812     if (proto.has_default_value()) {
4813       char* end_pos = nullptr;
4814       switch (result->cpp_type()) {
4815         case FieldDescriptor::CPPTYPE_INT32:
4816           result->default_value_int32_ =
4817               strtol(proto.default_value().c_str(), &end_pos, 0);
4818           break;
4819         case FieldDescriptor::CPPTYPE_INT64:
4820           result->default_value_int64_ =
4821               strto64(proto.default_value().c_str(), &end_pos, 0);
4822           break;
4823         case FieldDescriptor::CPPTYPE_UINT32:
4824           result->default_value_uint32_ =
4825               strtoul(proto.default_value().c_str(), &end_pos, 0);
4826           break;
4827         case FieldDescriptor::CPPTYPE_UINT64:
4828           result->default_value_uint64_ =
4829               strtou64(proto.default_value().c_str(), &end_pos, 0);
4830           break;
4831         case FieldDescriptor::CPPTYPE_FLOAT:
4832           if (proto.default_value() == "inf") {
4833             result->default_value_float_ =
4834                 std::numeric_limits<float>::infinity();
4835           } else if (proto.default_value() == "-inf") {
4836             result->default_value_float_ =
4837                 -std::numeric_limits<float>::infinity();
4838           } else if (proto.default_value() == "nan") {
4839             result->default_value_float_ =
4840                 std::numeric_limits<float>::quiet_NaN();
4841           } else {
4842             result->default_value_float_ = io::SafeDoubleToFloat(
4843                 io::NoLocaleStrtod(proto.default_value().c_str(), &end_pos));
4844           }
4845           break;
4846         case FieldDescriptor::CPPTYPE_DOUBLE:
4847           if (proto.default_value() == "inf") {
4848             result->default_value_double_ =
4849                 std::numeric_limits<double>::infinity();
4850           } else if (proto.default_value() == "-inf") {
4851             result->default_value_double_ =
4852                 -std::numeric_limits<double>::infinity();
4853           } else if (proto.default_value() == "nan") {
4854             result->default_value_double_ =
4855                 std::numeric_limits<double>::quiet_NaN();
4856           } else {
4857             result->default_value_double_ =
4858                 io::NoLocaleStrtod(proto.default_value().c_str(), &end_pos);
4859           }
4860           break;
4861         case FieldDescriptor::CPPTYPE_BOOL:
4862           if (proto.default_value() == "true") {
4863             result->default_value_bool_ = true;
4864           } else if (proto.default_value() == "false") {
4865             result->default_value_bool_ = false;
4866           } else {
4867             AddError(result->full_name(), proto,
4868                      DescriptorPool::ErrorCollector::DEFAULT_VALUE,
4869                      "Boolean default must be true or false.");
4870           }
4871           break;
4872         case FieldDescriptor::CPPTYPE_ENUM:
4873           // This will be filled in when cross-linking.
4874           result->default_value_enum_ = nullptr;
4875           break;
4876         case FieldDescriptor::CPPTYPE_STRING:
4877           if (result->type() == FieldDescriptor::TYPE_BYTES) {
4878             result->default_value_string_ = tables_->AllocateString(
4879                 UnescapeCEscapeString(proto.default_value()));
4880           } else {
4881             result->default_value_string_ =
4882                 tables_->AllocateString(proto.default_value());
4883           }
4884           break;
4885         case FieldDescriptor::CPPTYPE_MESSAGE:
4886           AddError(result->full_name(), proto,
4887                    DescriptorPool::ErrorCollector::DEFAULT_VALUE,
4888                    "Messages can't have default values.");
4889           result->has_default_value_ = false;
4890           result->default_generated_instance_ = nullptr;
4891           break;
4892       }
4893 
4894       if (end_pos != nullptr) {
4895         // end_pos is only set non-null by the parsers for numeric types,
4896         // above. This checks that the default was non-empty and had no extra
4897         // junk after the end of the number.
4898         if (proto.default_value().empty() || *end_pos != '\0') {
4899           AddError(result->full_name(), proto,
4900                    DescriptorPool::ErrorCollector::DEFAULT_VALUE,
4901                    "Couldn't parse default value \"" + proto.default_value() +
4902                        "\".");
4903         }
4904       }
4905     } else {
4906       // No explicit default value
4907       switch (result->cpp_type()) {
4908         case FieldDescriptor::CPPTYPE_INT32:
4909           result->default_value_int32_ = 0;
4910           break;
4911         case FieldDescriptor::CPPTYPE_INT64:
4912           result->default_value_int64_ = 0;
4913           break;
4914         case FieldDescriptor::CPPTYPE_UINT32:
4915           result->default_value_uint32_ = 0;
4916           break;
4917         case FieldDescriptor::CPPTYPE_UINT64:
4918           result->default_value_uint64_ = 0;
4919           break;
4920         case FieldDescriptor::CPPTYPE_FLOAT:
4921           result->default_value_float_ = 0.0f;
4922           break;
4923         case FieldDescriptor::CPPTYPE_DOUBLE:
4924           result->default_value_double_ = 0.0;
4925           break;
4926         case FieldDescriptor::CPPTYPE_BOOL:
4927           result->default_value_bool_ = false;
4928           break;
4929         case FieldDescriptor::CPPTYPE_ENUM:
4930           // This will be filled in when cross-linking.
4931           result->default_value_enum_ = nullptr;
4932           break;
4933         case FieldDescriptor::CPPTYPE_STRING:
4934           result->default_value_string_ = &internal::GetEmptyString();
4935           break;
4936         case FieldDescriptor::CPPTYPE_MESSAGE:
4937           result->default_generated_instance_ = nullptr;
4938           break;
4939       }
4940     }
4941   }
4942 
4943   if (result->number() <= 0) {
4944     AddError(result->full_name(), proto, DescriptorPool::ErrorCollector::NUMBER,
4945              "Field numbers must be positive integers.");
4946   } else if (!is_extension && result->number() > FieldDescriptor::kMaxNumber) {
4947     // Only validate that the number is within the valid field range if it is
4948     // not an extension. Since extension numbers are validated with the
4949     // extendee's valid set of extension numbers, and those are in turn
4950     // validated against the max allowed number, the check is unnecessary for
4951     // extension fields.
4952     // This avoids cross-linking issues that arise when attempting to check if
4953     // the extendee is a message_set_wire_format message, which has a higher max
4954     // on extension numbers.
4955     AddError(result->full_name(), proto, DescriptorPool::ErrorCollector::NUMBER,
4956              strings::Substitute("Field numbers cannot be greater than $0.",
4957                               FieldDescriptor::kMaxNumber));
4958   } else if (result->number() >= FieldDescriptor::kFirstReservedNumber &&
4959              result->number() <= FieldDescriptor::kLastReservedNumber) {
4960     AddError(result->full_name(), proto, DescriptorPool::ErrorCollector::NUMBER,
4961              strings::Substitute(
4962                  "Field numbers $0 through $1 are reserved for the protocol "
4963                  "buffer library implementation.",
4964                  FieldDescriptor::kFirstReservedNumber,
4965                  FieldDescriptor::kLastReservedNumber));
4966   }
4967 
4968   if (is_extension) {
4969     if (!proto.has_extendee()) {
4970       AddError(result->full_name(), proto,
4971                DescriptorPool::ErrorCollector::EXTENDEE,
4972                "FieldDescriptorProto.extendee not set for extension field.");
4973     }
4974 
4975     result->extension_scope_ = parent;
4976 
4977     if (proto.has_oneof_index()) {
4978       AddError(result->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
4979                "FieldDescriptorProto.oneof_index should not be set for "
4980                "extensions.");
4981     }
4982 
4983     // Fill in later (maybe).
4984     result->containing_oneof_ = nullptr;
4985   } else {
4986     if (proto.has_extendee()) {
4987       AddError(result->full_name(), proto,
4988                DescriptorPool::ErrorCollector::EXTENDEE,
4989                "FieldDescriptorProto.extendee set for non-extension field.");
4990     }
4991 
4992     result->containing_type_ = parent;
4993 
4994     if (proto.has_oneof_index()) {
4995       if (proto.oneof_index() < 0 ||
4996           proto.oneof_index() >= parent->oneof_decl_count()) {
4997         AddError(result->full_name(), proto,
4998                  DescriptorPool::ErrorCollector::TYPE,
4999                  strings::Substitute("FieldDescriptorProto.oneof_index $0 is "
5000                                   "out of range for type \"$1\".",
5001                                   proto.oneof_index(), parent->name()));
5002         result->containing_oneof_ = nullptr;
5003       } else {
5004         result->containing_oneof_ = parent->oneof_decl(proto.oneof_index());
5005       }
5006     } else {
5007       result->containing_oneof_ = nullptr;
5008     }
5009   }
5010 
5011   // Copy options.
5012   result->options_ = nullptr;  // Set to default_instance later if necessary.
5013   if (proto.has_options()) {
5014     AllocateOptions(proto.options(), result,
5015                     FieldDescriptorProto::kOptionsFieldNumber,
5016                     "google.protobuf.FieldOptions");
5017   }
5018 
5019 
5020   AddSymbol(result->full_name(), parent, result->name(), proto, Symbol(result));
5021 }
5022 
BuildExtensionRange(const DescriptorProto::ExtensionRange & proto,const Descriptor * parent,Descriptor::ExtensionRange * result)5023 void DescriptorBuilder::BuildExtensionRange(
5024     const DescriptorProto::ExtensionRange& proto, const Descriptor* parent,
5025     Descriptor::ExtensionRange* result) {
5026   result->start = proto.start();
5027   result->end = proto.end();
5028   if (result->start <= 0) {
5029     AddError(parent->full_name(), proto, DescriptorPool::ErrorCollector::NUMBER,
5030              "Extension numbers must be positive integers.");
5031   }
5032 
5033   // Checking of the upper bound of the extension range is deferred until after
5034   // options interpreting. This allows messages with message_set_wire_format to
5035   // have extensions beyond FieldDescriptor::kMaxNumber, since the extension
5036   // numbers are actually used as int32s in the message_set_wire_format.
5037 
5038   if (result->start >= result->end) {
5039     AddError(parent->full_name(), proto, DescriptorPool::ErrorCollector::NUMBER,
5040              "Extension range end number must be greater than start number.");
5041   }
5042 
5043   result->options_ = nullptr;  // Set to default_instance later if necessary.
5044   if (proto.has_options()) {
5045     std::vector<int> options_path;
5046     parent->GetLocationPath(&options_path);
5047     options_path.push_back(DescriptorProto::kExtensionRangeFieldNumber);
5048     // find index of this extension range in order to compute path
5049     int index;
5050     for (index = 0; parent->extension_ranges_ + index != result; index++) {
5051     }
5052     options_path.push_back(index);
5053     options_path.push_back(DescriptorProto_ExtensionRange::kOptionsFieldNumber);
5054     AllocateOptionsImpl(parent->full_name(), parent->full_name(),
5055                         proto.options(), result, options_path,
5056                         "google.protobuf.ExtensionRangeOptions");
5057   }
5058 }
5059 
BuildReservedRange(const DescriptorProto::ReservedRange & proto,const Descriptor * parent,Descriptor::ReservedRange * result)5060 void DescriptorBuilder::BuildReservedRange(
5061     const DescriptorProto::ReservedRange& proto, const Descriptor* parent,
5062     Descriptor::ReservedRange* result) {
5063   result->start = proto.start();
5064   result->end = proto.end();
5065   if (result->start <= 0) {
5066     AddError(parent->full_name(), proto, DescriptorPool::ErrorCollector::NUMBER,
5067              "Reserved numbers must be positive integers.");
5068   }
5069 }
5070 
BuildReservedRange(const EnumDescriptorProto::EnumReservedRange & proto,const EnumDescriptor * parent,EnumDescriptor::ReservedRange * result)5071 void DescriptorBuilder::BuildReservedRange(
5072     const EnumDescriptorProto::EnumReservedRange& proto,
5073     const EnumDescriptor* parent, EnumDescriptor::ReservedRange* result) {
5074   result->start = proto.start();
5075   result->end = proto.end();
5076 
5077   if (result->start > result->end) {
5078     AddError(parent->full_name(), proto, DescriptorPool::ErrorCollector::NUMBER,
5079              "Reserved range end number must be greater than start number.");
5080   }
5081 }
5082 
BuildOneof(const OneofDescriptorProto & proto,Descriptor * parent,OneofDescriptor * result)5083 void DescriptorBuilder::BuildOneof(const OneofDescriptorProto& proto,
5084                                    Descriptor* parent,
5085                                    OneofDescriptor* result) {
5086   std::string* full_name =
5087       AllocateNameString(parent->full_name(), proto.name());
5088   ValidateSymbolName(proto.name(), *full_name, proto);
5089 
5090   result->name_ = tables_->AllocateString(proto.name());
5091   result->full_name_ = full_name;
5092 
5093   result->containing_type_ = parent;
5094 
5095   // We need to fill these in later.
5096   result->field_count_ = 0;
5097   result->fields_ = nullptr;
5098   result->options_ = nullptr;
5099 
5100   // Copy options.
5101   if (proto.has_options()) {
5102     AllocateOptions(proto.options(), result,
5103                     OneofDescriptorProto::kOptionsFieldNumber,
5104                     "google.protobuf.OneofOptions");
5105   }
5106 
5107   AddSymbol(result->full_name(), parent, result->name(), proto, Symbol(result));
5108 }
5109 
CheckEnumValueUniqueness(const EnumDescriptorProto & proto,const EnumDescriptor * result)5110 void DescriptorBuilder::CheckEnumValueUniqueness(
5111     const EnumDescriptorProto& proto, const EnumDescriptor* result) {
5112 
5113   // Check that enum labels are still unique when we remove the enum prefix from
5114   // values that have it.
5115   //
5116   // This will fail for something like:
5117   //
5118   //   enum MyEnum {
5119   //     MY_ENUM_FOO = 0;
5120   //     FOO = 1;
5121   //   }
5122   //
5123   // By enforcing this reasonable constraint, we allow code generators to strip
5124   // the prefix and/or PascalCase it without creating conflicts.  This can lead
5125   // to much nicer language-specific enums like:
5126   //
5127   //   enum NameType {
5128   //     FirstName = 1,
5129   //     LastName = 2,
5130   //   }
5131   //
5132   // Instead of:
5133   //
5134   //   enum NameType {
5135   //     NAME_TYPE_FIRST_NAME = 1,
5136   //     NAME_TYPE_LAST_NAME = 2,
5137   //   }
5138   PrefixRemover remover(result->name());
5139   std::map<std::string, const EnumValueDescriptor*> values;
5140   for (int i = 0; i < result->value_count(); i++) {
5141     const EnumValueDescriptor* value = result->value(i);
5142     std::string stripped =
5143         EnumValueToPascalCase(remover.MaybeRemove(value->name()));
5144     std::pair<std::map<std::string, const EnumValueDescriptor*>::iterator, bool>
5145         insert_result = values.insert(std::make_pair(stripped, value));
5146     bool inserted = insert_result.second;
5147 
5148     // We don't throw the error if the two conflicting symbols are identical, or
5149     // if they map to the same number.  In the former case, the normal symbol
5150     // duplication error will fire so we don't need to (and its error message
5151     // will make more sense). We allow the latter case so users can create
5152     // aliases which add or remove the prefix (code generators that do prefix
5153     // stripping should de-dup the labels in this case).
5154     if (!inserted && insert_result.first->second->name() != value->name() &&
5155         insert_result.first->second->number() != value->number()) {
5156       std::string error_message =
5157           "Enum name " + value->name() + " has the same name as " +
5158           values[stripped]->name() +
5159           " if you ignore case and strip out the enum name prefix (if any). "
5160           "This is error-prone and can lead to undefined behavior. "
5161           "Please avoid doing this. If you are using allow_alias, please "
5162           "assign the same numeric value to both enums.";
5163       // There are proto2 enums out there with conflicting names, so to preserve
5164       // compatibility we issue only a warning for proto2.
5165       if (result->file()->syntax() == FileDescriptor::SYNTAX_PROTO2) {
5166         AddWarning(value->full_name(), proto.value(i),
5167                    DescriptorPool::ErrorCollector::NAME, error_message);
5168       } else {
5169         AddError(value->full_name(), proto.value(i),
5170                  DescriptorPool::ErrorCollector::NAME, error_message);
5171       }
5172     }
5173   }
5174 }
5175 
BuildEnum(const EnumDescriptorProto & proto,const Descriptor * parent,EnumDescriptor * result)5176 void DescriptorBuilder::BuildEnum(const EnumDescriptorProto& proto,
5177                                   const Descriptor* parent,
5178                                   EnumDescriptor* result) {
5179   const std::string& scope =
5180       (parent == nullptr) ? file_->package() : parent->full_name();
5181   std::string* full_name = AllocateNameString(scope, proto.name());
5182   ValidateSymbolName(proto.name(), *full_name, proto);
5183 
5184   result->name_ = tables_->AllocateString(proto.name());
5185   result->full_name_ = full_name;
5186   result->file_ = file_;
5187   result->containing_type_ = parent;
5188   result->is_placeholder_ = false;
5189   result->is_unqualified_placeholder_ = false;
5190 
5191   if (proto.value_size() == 0) {
5192     // We cannot allow enums with no values because this would mean there
5193     // would be no valid default value for fields of this type.
5194     AddError(result->full_name(), proto, DescriptorPool::ErrorCollector::NAME,
5195              "Enums must contain at least one value.");
5196   }
5197 
5198   BUILD_ARRAY(proto, result, value, BuildEnumValue, result);
5199   BUILD_ARRAY(proto, result, reserved_range, BuildReservedRange, result);
5200 
5201   // Copy reserved names.
5202   int reserved_name_count = proto.reserved_name_size();
5203   result->reserved_name_count_ = reserved_name_count;
5204   result->reserved_names_ =
5205       tables_->AllocateArray<const std::string*>(reserved_name_count);
5206   for (int i = 0; i < reserved_name_count; ++i) {
5207     result->reserved_names_[i] =
5208         tables_->AllocateString(proto.reserved_name(i));
5209   }
5210 
5211   CheckEnumValueUniqueness(proto, result);
5212 
5213   // Copy options.
5214   result->options_ = nullptr;  // Set to default_instance later if necessary.
5215   if (proto.has_options()) {
5216     AllocateOptions(proto.options(), result,
5217                     EnumDescriptorProto::kOptionsFieldNumber,
5218                     "google.protobuf.EnumOptions");
5219   }
5220 
5221   AddSymbol(result->full_name(), parent, result->name(), proto, Symbol(result));
5222 
5223   for (int i = 0; i < proto.reserved_range_size(); i++) {
5224     const EnumDescriptorProto_EnumReservedRange& range1 =
5225         proto.reserved_range(i);
5226     for (int j = i + 1; j < proto.reserved_range_size(); j++) {
5227       const EnumDescriptorProto_EnumReservedRange& range2 =
5228           proto.reserved_range(j);
5229       if (range1.end() >= range2.start() && range2.end() >= range1.start()) {
5230         AddError(result->full_name(), proto.reserved_range(i),
5231                  DescriptorPool::ErrorCollector::NUMBER,
5232                  strings::Substitute("Reserved range $0 to $1 overlaps with "
5233                                   "already-defined range $2 to $3.",
5234                                   range2.start(), range2.end(), range1.start(),
5235                                   range1.end()));
5236       }
5237     }
5238   }
5239 
5240   HASH_SET<std::string> reserved_name_set;
5241   for (int i = 0; i < proto.reserved_name_size(); i++) {
5242     const std::string& name = proto.reserved_name(i);
5243     if (reserved_name_set.find(name) == reserved_name_set.end()) {
5244       reserved_name_set.insert(name);
5245     } else {
5246       AddError(name, proto, DescriptorPool::ErrorCollector::NAME,
5247                strings::Substitute("Enum value \"$0\" is reserved multiple times.",
5248                                 name));
5249     }
5250   }
5251 
5252   for (int i = 0; i < result->value_count(); i++) {
5253     const EnumValueDescriptor* value = result->value(i);
5254     for (int j = 0; j < result->reserved_range_count(); j++) {
5255       const EnumDescriptor::ReservedRange* range = result->reserved_range(j);
5256       if (range->start <= value->number() && value->number() <= range->end) {
5257         AddError(value->full_name(), proto.reserved_range(j),
5258                  DescriptorPool::ErrorCollector::NUMBER,
5259                  strings::Substitute("Enum value \"$0\" uses reserved number $1.",
5260                                   value->name(), value->number()));
5261       }
5262     }
5263     if (reserved_name_set.find(value->name()) != reserved_name_set.end()) {
5264       AddError(
5265           value->full_name(), proto.value(i),
5266           DescriptorPool::ErrorCollector::NAME,
5267           strings::Substitute("Enum value \"$0\" is reserved.", value->name()));
5268     }
5269   }
5270 }
5271 
BuildEnumValue(const EnumValueDescriptorProto & proto,const EnumDescriptor * parent,EnumValueDescriptor * result)5272 void DescriptorBuilder::BuildEnumValue(const EnumValueDescriptorProto& proto,
5273                                        const EnumDescriptor* parent,
5274                                        EnumValueDescriptor* result) {
5275   result->name_ = tables_->AllocateString(proto.name());
5276   result->number_ = proto.number();
5277   result->type_ = parent;
5278 
5279   // Note:  full_name for enum values is a sibling to the parent's name, not a
5280   //   child of it.
5281   std::string* full_name = tables_->AllocateEmptyString();
5282   size_t scope_len = parent->full_name_->size() - parent->name_->size();
5283   full_name->reserve(scope_len + result->name_->size());
5284   full_name->append(parent->full_name_->data(), scope_len);
5285   full_name->append(*result->name_);
5286   result->full_name_ = full_name;
5287 
5288   ValidateSymbolName(proto.name(), *full_name, proto);
5289 
5290   // Copy options.
5291   result->options_ = nullptr;  // Set to default_instance later if necessary.
5292   if (proto.has_options()) {
5293     AllocateOptions(proto.options(), result,
5294                     EnumValueDescriptorProto::kOptionsFieldNumber,
5295                     "google.protobuf.EnumValueOptions");
5296   }
5297 
5298   // Again, enum values are weird because we makes them appear as siblings
5299   // of the enum type instead of children of it.  So, we use
5300   // parent->containing_type() as the value's parent.
5301   bool added_to_outer_scope =
5302       AddSymbol(result->full_name(), parent->containing_type(), result->name(),
5303                 proto, Symbol(result));
5304 
5305   // However, we also want to be able to search for values within a single
5306   // enum type, so we add it as a child of the enum type itself, too.
5307   // Note:  This could fail, but if it does, the error has already been
5308   //   reported by the above AddSymbol() call, so we ignore the return code.
5309   bool added_to_inner_scope =
5310       file_tables_->AddAliasUnderParent(parent, result->name(), Symbol(result));
5311 
5312   if (added_to_inner_scope && !added_to_outer_scope) {
5313     // This value did not conflict with any values defined in the same enum,
5314     // but it did conflict with some other symbol defined in the enum type's
5315     // scope.  Let's print an additional error to explain this.
5316     std::string outer_scope;
5317     if (parent->containing_type() == nullptr) {
5318       outer_scope = file_->package();
5319     } else {
5320       outer_scope = parent->containing_type()->full_name();
5321     }
5322 
5323     if (outer_scope.empty()) {
5324       outer_scope = "the global scope";
5325     } else {
5326       outer_scope = "\"" + outer_scope + "\"";
5327     }
5328 
5329     AddError(result->full_name(), proto, DescriptorPool::ErrorCollector::NAME,
5330              "Note that enum values use C++ scoping rules, meaning that "
5331              "enum values are siblings of their type, not children of it.  "
5332              "Therefore, \"" +
5333                  result->name() + "\" must be unique within " + outer_scope +
5334                  ", not just within \"" + parent->name() + "\".");
5335   }
5336 
5337   // An enum is allowed to define two numbers that refer to the same value.
5338   // FindValueByNumber() should return the first such value, so we simply
5339   // ignore AddEnumValueByNumber()'s return code.
5340   file_tables_->AddEnumValueByNumber(result);
5341 }
5342 
BuildService(const ServiceDescriptorProto & proto,const void *,ServiceDescriptor * result)5343 void DescriptorBuilder::BuildService(const ServiceDescriptorProto& proto,
5344                                      const void* /* dummy */,
5345                                      ServiceDescriptor* result) {
5346   std::string* full_name = AllocateNameString(file_->package(), proto.name());
5347   ValidateSymbolName(proto.name(), *full_name, proto);
5348 
5349   result->name_ = tables_->AllocateString(proto.name());
5350   result->full_name_ = full_name;
5351   result->file_ = file_;
5352 
5353   BUILD_ARRAY(proto, result, method, BuildMethod, result);
5354 
5355   // Copy options.
5356   result->options_ = nullptr;  // Set to default_instance later if necessary.
5357   if (proto.has_options()) {
5358     AllocateOptions(proto.options(), result,
5359                     ServiceDescriptorProto::kOptionsFieldNumber,
5360                     "google.protobuf.ServiceOptions");
5361   }
5362 
5363   AddSymbol(result->full_name(), nullptr, result->name(), proto,
5364             Symbol(result));
5365 }
5366 
BuildMethod(const MethodDescriptorProto & proto,const ServiceDescriptor * parent,MethodDescriptor * result)5367 void DescriptorBuilder::BuildMethod(const MethodDescriptorProto& proto,
5368                                     const ServiceDescriptor* parent,
5369                                     MethodDescriptor* result) {
5370   result->name_ = tables_->AllocateString(proto.name());
5371   result->service_ = parent;
5372 
5373   std::string* full_name =
5374       AllocateNameString(parent->full_name(), *result->name_);
5375   result->full_name_ = full_name;
5376 
5377   ValidateSymbolName(proto.name(), *full_name, proto);
5378 
5379   // These will be filled in when cross-linking.
5380   result->input_type_.Init();
5381   result->output_type_.Init();
5382 
5383   // Copy options.
5384   result->options_ = nullptr;  // Set to default_instance later if necessary.
5385   if (proto.has_options()) {
5386     AllocateOptions(proto.options(), result,
5387                     MethodDescriptorProto::kOptionsFieldNumber,
5388                     "google.protobuf.MethodOptions");
5389   }
5390 
5391   result->client_streaming_ = proto.client_streaming();
5392   result->server_streaming_ = proto.server_streaming();
5393 
5394   AddSymbol(result->full_name(), parent, result->name(), proto, Symbol(result));
5395 }
5396 
5397 #undef BUILD_ARRAY
5398 
5399 // -------------------------------------------------------------------
5400 
CrossLinkFile(FileDescriptor * file,const FileDescriptorProto & proto)5401 void DescriptorBuilder::CrossLinkFile(FileDescriptor* file,
5402                                       const FileDescriptorProto& proto) {
5403   if (file->options_ == nullptr) {
5404     file->options_ = &FileOptions::default_instance();
5405   }
5406 
5407   for (int i = 0; i < file->message_type_count(); i++) {
5408     CrossLinkMessage(&file->message_types_[i], proto.message_type(i));
5409   }
5410 
5411   for (int i = 0; i < file->extension_count(); i++) {
5412     CrossLinkField(&file->extensions_[i], proto.extension(i));
5413   }
5414 
5415   for (int i = 0; i < file->enum_type_count(); i++) {
5416     CrossLinkEnum(&file->enum_types_[i], proto.enum_type(i));
5417   }
5418 
5419   for (int i = 0; i < file->service_count(); i++) {
5420     CrossLinkService(&file->services_[i], proto.service(i));
5421   }
5422 }
5423 
CrossLinkMessage(Descriptor * message,const DescriptorProto & proto)5424 void DescriptorBuilder::CrossLinkMessage(Descriptor* message,
5425                                          const DescriptorProto& proto) {
5426   if (message->options_ == nullptr) {
5427     message->options_ = &MessageOptions::default_instance();
5428   }
5429 
5430   for (int i = 0; i < message->nested_type_count(); i++) {
5431     CrossLinkMessage(&message->nested_types_[i], proto.nested_type(i));
5432   }
5433 
5434   for (int i = 0; i < message->enum_type_count(); i++) {
5435     CrossLinkEnum(&message->enum_types_[i], proto.enum_type(i));
5436   }
5437 
5438   for (int i = 0; i < message->field_count(); i++) {
5439     CrossLinkField(&message->fields_[i], proto.field(i));
5440   }
5441 
5442   for (int i = 0; i < message->extension_count(); i++) {
5443     CrossLinkField(&message->extensions_[i], proto.extension(i));
5444   }
5445 
5446   for (int i = 0; i < message->extension_range_count(); i++) {
5447     CrossLinkExtensionRange(&message->extension_ranges_[i],
5448                             proto.extension_range(i));
5449   }
5450 
5451   // Set up field array for each oneof.
5452 
5453   // First count the number of fields per oneof.
5454   for (int i = 0; i < message->field_count(); i++) {
5455     const OneofDescriptor* oneof_decl = message->field(i)->containing_oneof();
5456     if (oneof_decl != nullptr) {
5457       // Make sure fields belonging to the same oneof are defined consecutively.
5458       // This enables optimizations in codegens and reflection libraries to
5459       // skip fields in the oneof group, as only one of the field can be set.
5460       // Note that field_count() returns how many fields in this oneof we have
5461       // seen so far. field_count() > 0 guarantees that i > 0, so field(i-1) is
5462       // safe.
5463       if (oneof_decl->field_count() > 0 &&
5464           message->field(i - 1)->containing_oneof() != oneof_decl) {
5465         AddError(message->full_name() + "." + message->field(i - 1)->name(),
5466                  proto.field(i - 1), DescriptorPool::ErrorCollector::TYPE,
5467                  strings::Substitute(
5468                      "Fields in the same oneof must be defined consecutively. "
5469                      "\"$0\" cannot be defined before the completion of the "
5470                      "\"$1\" oneof definition.",
5471                      message->field(i - 1)->name(), oneof_decl->name()));
5472       }
5473       // Must go through oneof_decls_ array to get a non-const version of the
5474       // OneofDescriptor.
5475       ++message->oneof_decls_[oneof_decl->index()].field_count_;
5476     }
5477   }
5478 
5479   // Then allocate the arrays.
5480   for (int i = 0; i < message->oneof_decl_count(); i++) {
5481     OneofDescriptor* oneof_decl = &message->oneof_decls_[i];
5482 
5483     if (oneof_decl->field_count() == 0) {
5484       AddError(message->full_name() + "." + oneof_decl->name(),
5485                proto.oneof_decl(i), DescriptorPool::ErrorCollector::NAME,
5486                "Oneof must have at least one field.");
5487     }
5488 
5489     oneof_decl->fields_ = tables_->AllocateArray<const FieldDescriptor*>(
5490         oneof_decl->field_count_);
5491     oneof_decl->field_count_ = 0;
5492 
5493     if (oneof_decl->options_ == nullptr) {
5494       oneof_decl->options_ = &OneofOptions::default_instance();
5495     }
5496   }
5497 
5498   // Then fill them in.
5499   for (int i = 0; i < message->field_count(); i++) {
5500     const OneofDescriptor* oneof_decl = message->field(i)->containing_oneof();
5501     if (oneof_decl != nullptr) {
5502       OneofDescriptor* mutable_oneof_decl =
5503           &message->oneof_decls_[oneof_decl->index()];
5504       message->fields_[i].index_in_oneof_ = mutable_oneof_decl->field_count_;
5505       mutable_oneof_decl->fields_[mutable_oneof_decl->field_count_++] =
5506           message->field(i);
5507     }
5508   }
5509 
5510   for (int i = 0; i < message->field_count(); i++) {
5511     const FieldDescriptor* field = message->field(i);
5512     if (field->proto3_optional_) {
5513       if (!field->containing_oneof() ||
5514           !field->containing_oneof()->is_synthetic()) {
5515         AddError(message->full_name(), proto.field(i),
5516                  DescriptorPool::ErrorCollector::OTHER,
5517                  "Fields with proto3_optional set must be "
5518                  "a member of a one-field oneof");
5519       }
5520     }
5521   }
5522 
5523   // Synthetic oneofs must be last.
5524   int first_synthetic = -1;
5525   for (int i = 0; i < message->oneof_decl_count(); i++) {
5526     const OneofDescriptor* oneof = message->oneof_decl(i);
5527     if (oneof->is_synthetic()) {
5528       if (first_synthetic == -1) {
5529         first_synthetic = i;
5530       }
5531     } else {
5532       if (first_synthetic != -1) {
5533         AddError(message->full_name(), proto.oneof_decl(i),
5534                  DescriptorPool::ErrorCollector::OTHER,
5535                  "Synthetic oneofs must be after all other oneofs");
5536       }
5537     }
5538   }
5539 
5540   if (first_synthetic == -1) {
5541     message->real_oneof_decl_count_ = message->oneof_decl_count_;
5542   } else {
5543     message->real_oneof_decl_count_ = first_synthetic;
5544   }
5545 }
5546 
CrossLinkExtensionRange(Descriptor::ExtensionRange * range,const DescriptorProto::ExtensionRange & proto)5547 void DescriptorBuilder::CrossLinkExtensionRange(
5548     Descriptor::ExtensionRange* range,
5549     const DescriptorProto::ExtensionRange& proto) {
5550   if (range->options_ == nullptr) {
5551     range->options_ = &ExtensionRangeOptions::default_instance();
5552   }
5553 }
5554 
CrossLinkField(FieldDescriptor * field,const FieldDescriptorProto & proto)5555 void DescriptorBuilder::CrossLinkField(FieldDescriptor* field,
5556                                        const FieldDescriptorProto& proto) {
5557   if (field->options_ == nullptr) {
5558     field->options_ = &FieldOptions::default_instance();
5559   }
5560 
5561   // Add the field to the lowercase-name and camelcase-name tables.
5562   file_tables_->AddFieldByStylizedNames(field);
5563 
5564   if (proto.has_extendee()) {
5565     Symbol extendee =
5566         LookupSymbol(proto.extendee(), field->full_name(),
5567                      DescriptorPool::PLACEHOLDER_EXTENDABLE_MESSAGE);
5568     if (extendee.IsNull()) {
5569       AddNotDefinedError(field->full_name(), proto,
5570                          DescriptorPool::ErrorCollector::EXTENDEE,
5571                          proto.extendee());
5572       return;
5573     } else if (extendee.type != Symbol::MESSAGE) {
5574       AddError(field->full_name(), proto,
5575                DescriptorPool::ErrorCollector::EXTENDEE,
5576                "\"" + proto.extendee() + "\" is not a message type.");
5577       return;
5578     }
5579     field->containing_type_ = extendee.descriptor;
5580 
5581     const Descriptor::ExtensionRange* extension_range =
5582         field->containing_type()->FindExtensionRangeContainingNumber(
5583             field->number());
5584 
5585     if (extension_range == nullptr) {
5586       // Set of valid extension numbers for MessageSet is different (< 2^32)
5587       // from other extendees (< 2^29). If unknown deps are allowed, we may not
5588       // have that information, and wrongly deem the extension as invalid.
5589       auto skip_check = get_allow_unknown(pool_) &&
5590                         proto.extendee() == "google.protobuf.bridge.MessageSet";
5591       if (!skip_check) {
5592         AddError(field->full_name(), proto,
5593                  DescriptorPool::ErrorCollector::NUMBER,
5594                  strings::Substitute("\"$0\" does not declare $1 as an "
5595                                   "extension number.",
5596                                   field->containing_type()->full_name(),
5597                                   field->number()));
5598       }
5599     }
5600   }
5601 
5602   if (field->containing_oneof() != nullptr) {
5603     if (field->label() != FieldDescriptor::LABEL_OPTIONAL) {
5604       // Note that this error will never happen when parsing .proto files.
5605       // It can only happen if you manually construct a FileDescriptorProto
5606       // that is incorrect.
5607       AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::NAME,
5608                "Fields of oneofs must themselves have label LABEL_OPTIONAL.");
5609     }
5610   }
5611 
5612   if (proto.has_type_name()) {
5613     // Assume we are expecting a message type unless the proto contains some
5614     // evidence that it expects an enum type.  This only makes a difference if
5615     // we end up creating a placeholder.
5616     bool expecting_enum = (proto.type() == FieldDescriptorProto::TYPE_ENUM) ||
5617                           proto.has_default_value();
5618 
5619     // In case of weak fields we force building the dependency. We need to know
5620     // if the type exist or not. If it doesn't exist we substitute Empty which
5621     // should only be done if the type can't be found in the generated pool.
5622     // TODO(gerbens) Ideally we should query the database directly to check
5623     // if weak fields exist or not so that we don't need to force building
5624     // weak dependencies. However the name lookup rules for symbols are
5625     // somewhat complicated, so I defer it too another CL.
5626     bool is_weak = !pool_->enforce_weak_ && proto.options().weak();
5627     bool is_lazy = pool_->lazily_build_dependencies_ && !is_weak;
5628 
5629     Symbol type =
5630         LookupSymbol(proto.type_name(), field->full_name(),
5631                      expecting_enum ? DescriptorPool::PLACEHOLDER_ENUM
5632                                     : DescriptorPool::PLACEHOLDER_MESSAGE,
5633                      LOOKUP_TYPES, !is_lazy);
5634 
5635     if (type.IsNull()) {
5636       if (is_lazy) {
5637         // Save the symbol names for later for lookup, and allocate the once
5638         // object needed for the accessors.
5639         std::string name = proto.type_name();
5640         field->type_once_ = tables_->AllocateOnceDynamic();
5641         field->type_name_ = tables_->AllocateString(name);
5642         if (proto.has_default_value()) {
5643           field->default_value_enum_name_ =
5644               tables_->AllocateString(proto.default_value());
5645         }
5646         // AddFieldByNumber and AddExtension are done later in this function,
5647         // and can/must be done if the field type was not found. The related
5648         // error checking is not necessary when in lazily_build_dependencies_
5649         // mode, and can't be done without building the type's descriptor,
5650         // which we don't want to do.
5651         file_tables_->AddFieldByNumber(field);
5652         if (field->is_extension()) {
5653           tables_->AddExtension(field);
5654         }
5655         return;
5656       } else {
5657         // If the type is a weak type, we change the type to a google.protobuf.Empty
5658         // field.
5659         if (is_weak) {
5660           type = FindSymbol(kNonLinkedWeakMessageReplacementName);
5661         }
5662         if (type.IsNull()) {
5663           AddNotDefinedError(field->full_name(), proto,
5664                              DescriptorPool::ErrorCollector::TYPE,
5665                              proto.type_name());
5666           return;
5667         }
5668       }
5669     }
5670 
5671     if (!proto.has_type()) {
5672       // Choose field type based on symbol.
5673       if (type.type == Symbol::MESSAGE) {
5674         field->type_ = FieldDescriptor::TYPE_MESSAGE;
5675       } else if (type.type == Symbol::ENUM) {
5676         field->type_ = FieldDescriptor::TYPE_ENUM;
5677       } else {
5678         AddError(field->full_name(), proto,
5679                  DescriptorPool::ErrorCollector::TYPE,
5680                  "\"" + proto.type_name() + "\" is not a type.");
5681         return;
5682       }
5683     }
5684 
5685     if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
5686       if (type.type != Symbol::MESSAGE) {
5687         AddError(field->full_name(), proto,
5688                  DescriptorPool::ErrorCollector::TYPE,
5689                  "\"" + proto.type_name() + "\" is not a message type.");
5690         return;
5691       }
5692       field->message_type_ = type.descriptor;
5693 
5694       if (field->has_default_value()) {
5695         AddError(field->full_name(), proto,
5696                  DescriptorPool::ErrorCollector::DEFAULT_VALUE,
5697                  "Messages can't have default values.");
5698       }
5699     } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
5700       if (type.type != Symbol::ENUM) {
5701         AddError(field->full_name(), proto,
5702                  DescriptorPool::ErrorCollector::TYPE,
5703                  "\"" + proto.type_name() + "\" is not an enum type.");
5704         return;
5705       }
5706       field->enum_type_ = type.enum_descriptor;
5707 
5708       if (field->enum_type()->is_placeholder_) {
5709         // We can't look up default values for placeholder types.  We'll have
5710         // to just drop them.
5711         field->has_default_value_ = false;
5712       }
5713 
5714       if (field->has_default_value()) {
5715         // Ensure that the default value is an identifier. Parser cannot always
5716         // verify this because it does not have complete type information.
5717         // N.B. that this check yields better error messages but is not
5718         // necessary for correctness (an enum symbol must be a valid identifier
5719         // anyway), only for better errors.
5720         if (!io::Tokenizer::IsIdentifier(proto.default_value())) {
5721           AddError(field->full_name(), proto,
5722                    DescriptorPool::ErrorCollector::DEFAULT_VALUE,
5723                    "Default value for an enum field must be an identifier.");
5724         } else {
5725           // We can't just use field->enum_type()->FindValueByName() here
5726           // because that locks the pool's mutex, which we have already locked
5727           // at this point.
5728           Symbol default_value = LookupSymbolNoPlaceholder(
5729               proto.default_value(), field->enum_type()->full_name());
5730 
5731           if (default_value.type == Symbol::ENUM_VALUE &&
5732               default_value.enum_value_descriptor->type() ==
5733                   field->enum_type()) {
5734             field->default_value_enum_ = default_value.enum_value_descriptor;
5735           } else {
5736             AddError(field->full_name(), proto,
5737                      DescriptorPool::ErrorCollector::DEFAULT_VALUE,
5738                      "Enum type \"" + field->enum_type()->full_name() +
5739                          "\" has no value named \"" + proto.default_value() +
5740                          "\".");
5741           }
5742         }
5743       } else if (field->enum_type()->value_count() > 0) {
5744         // All enums must have at least one value, or we would have reported
5745         // an error elsewhere.  We use the first defined value as the default
5746         // if a default is not explicitly defined.
5747         field->default_value_enum_ = field->enum_type()->value(0);
5748       }
5749     } else {
5750       AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
5751                "Field with primitive type has type_name.");
5752     }
5753   } else {
5754     if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE ||
5755         field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
5756       AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
5757                "Field with message or enum type missing type_name.");
5758     }
5759   }
5760 
5761   // Add the field to the fields-by-number table.
5762   // Note:  We have to do this *after* cross-linking because extensions do not
5763   // know their containing type until now. If we're in
5764   // lazily_build_dependencies_ mode, we're guaranteed there's no errors, so no
5765   // risk to calling containing_type() or other accessors that will build
5766   // dependencies.
5767   if (!file_tables_->AddFieldByNumber(field)) {
5768     const FieldDescriptor* conflicting_field = file_tables_->FindFieldByNumber(
5769         field->containing_type(), field->number());
5770     std::string containing_type_name =
5771         field->containing_type() == nullptr
5772             ? "unknown"
5773             : field->containing_type()->full_name();
5774     if (field->is_extension()) {
5775       AddError(field->full_name(), proto,
5776                DescriptorPool::ErrorCollector::NUMBER,
5777                strings::Substitute("Extension number $0 has already been used "
5778                                 "in \"$1\" by extension \"$2\".",
5779                                 field->number(), containing_type_name,
5780                                 conflicting_field->full_name()));
5781     } else {
5782       AddError(field->full_name(), proto,
5783                DescriptorPool::ErrorCollector::NUMBER,
5784                strings::Substitute("Field number $0 has already been used in "
5785                                 "\"$1\" by field \"$2\".",
5786                                 field->number(), containing_type_name,
5787                                 conflicting_field->name()));
5788     }
5789   } else {
5790     if (field->is_extension()) {
5791       if (!tables_->AddExtension(field)) {
5792         const FieldDescriptor* conflicting_field =
5793             tables_->FindExtension(field->containing_type(), field->number());
5794         std::string containing_type_name =
5795             field->containing_type() == nullptr
5796                 ? "unknown"
5797                 : field->containing_type()->full_name();
5798         std::string error_msg = strings::Substitute(
5799             "Extension number $0 has already been used in \"$1\" by extension "
5800             "\"$2\" defined in $3.",
5801             field->number(), containing_type_name,
5802             conflicting_field->full_name(), conflicting_field->file()->name());
5803         // Conflicting extension numbers should be an error. However, before
5804         // turning this into an error we need to fix all existing broken
5805         // protos first.
5806         // TODO(xiaofeng): Change this to an error.
5807         AddWarning(field->full_name(), proto,
5808                    DescriptorPool::ErrorCollector::NUMBER, error_msg);
5809       }
5810     }
5811   }
5812 }
5813 
CrossLinkEnum(EnumDescriptor * enum_type,const EnumDescriptorProto & proto)5814 void DescriptorBuilder::CrossLinkEnum(EnumDescriptor* enum_type,
5815                                       const EnumDescriptorProto& proto) {
5816   if (enum_type->options_ == nullptr) {
5817     enum_type->options_ = &EnumOptions::default_instance();
5818   }
5819 
5820   for (int i = 0; i < enum_type->value_count(); i++) {
5821     CrossLinkEnumValue(&enum_type->values_[i], proto.value(i));
5822   }
5823 }
5824 
CrossLinkEnumValue(EnumValueDescriptor * enum_value,const EnumValueDescriptorProto &)5825 void DescriptorBuilder::CrossLinkEnumValue(
5826     EnumValueDescriptor* enum_value,
5827     const EnumValueDescriptorProto& /* proto */) {
5828   if (enum_value->options_ == nullptr) {
5829     enum_value->options_ = &EnumValueOptions::default_instance();
5830   }
5831 }
5832 
CrossLinkService(ServiceDescriptor * service,const ServiceDescriptorProto & proto)5833 void DescriptorBuilder::CrossLinkService(ServiceDescriptor* service,
5834                                          const ServiceDescriptorProto& proto) {
5835   if (service->options_ == nullptr) {
5836     service->options_ = &ServiceOptions::default_instance();
5837   }
5838 
5839   for (int i = 0; i < service->method_count(); i++) {
5840     CrossLinkMethod(&service->methods_[i], proto.method(i));
5841   }
5842 }
5843 
CrossLinkMethod(MethodDescriptor * method,const MethodDescriptorProto & proto)5844 void DescriptorBuilder::CrossLinkMethod(MethodDescriptor* method,
5845                                         const MethodDescriptorProto& proto) {
5846   if (method->options_ == nullptr) {
5847     method->options_ = &MethodOptions::default_instance();
5848   }
5849 
5850   Symbol input_type =
5851       LookupSymbol(proto.input_type(), method->full_name(),
5852                    DescriptorPool::PLACEHOLDER_MESSAGE, LOOKUP_ALL,
5853                    !pool_->lazily_build_dependencies_);
5854   if (input_type.IsNull()) {
5855     if (!pool_->lazily_build_dependencies_) {
5856       AddNotDefinedError(method->full_name(), proto,
5857                          DescriptorPool::ErrorCollector::INPUT_TYPE,
5858                          proto.input_type());
5859     } else {
5860       method->input_type_.SetLazy(proto.input_type(), file_);
5861     }
5862   } else if (input_type.type != Symbol::MESSAGE) {
5863     AddError(method->full_name(), proto,
5864              DescriptorPool::ErrorCollector::INPUT_TYPE,
5865              "\"" + proto.input_type() + "\" is not a message type.");
5866   } else {
5867     method->input_type_.Set(input_type.descriptor);
5868   }
5869 
5870   Symbol output_type =
5871       LookupSymbol(proto.output_type(), method->full_name(),
5872                    DescriptorPool::PLACEHOLDER_MESSAGE, LOOKUP_ALL,
5873                    !pool_->lazily_build_dependencies_);
5874   if (output_type.IsNull()) {
5875     if (!pool_->lazily_build_dependencies_) {
5876       AddNotDefinedError(method->full_name(), proto,
5877                          DescriptorPool::ErrorCollector::OUTPUT_TYPE,
5878                          proto.output_type());
5879     } else {
5880       method->output_type_.SetLazy(proto.output_type(), file_);
5881     }
5882   } else if (output_type.type != Symbol::MESSAGE) {
5883     AddError(method->full_name(), proto,
5884              DescriptorPool::ErrorCollector::OUTPUT_TYPE,
5885              "\"" + proto.output_type() + "\" is not a message type.");
5886   } else {
5887     method->output_type_.Set(output_type.descriptor);
5888   }
5889 }
5890 
5891 // -------------------------------------------------------------------
5892 
5893 #define VALIDATE_OPTIONS_FROM_ARRAY(descriptor, array_name, type) \
5894   for (int i = 0; i < descriptor->array_name##_count(); ++i) {    \
5895     Validate##type##Options(descriptor->array_name##s_ + i,       \
5896                             proto.array_name(i));                 \
5897   }
5898 
5899 // Determine if the file uses optimize_for = LITE_RUNTIME, being careful to
5900 // avoid problems that exist at init time.
IsLite(const FileDescriptor * file)5901 static bool IsLite(const FileDescriptor* file) {
5902   // TODO(kenton):  I don't even remember how many of these conditions are
5903   //   actually possible.  I'm just being super-safe.
5904   return file != nullptr &&
5905          &file->options() != &FileOptions::default_instance() &&
5906          file->options().optimize_for() == FileOptions::LITE_RUNTIME;
5907 }
5908 
ValidateFileOptions(FileDescriptor * file,const FileDescriptorProto & proto)5909 void DescriptorBuilder::ValidateFileOptions(FileDescriptor* file,
5910                                             const FileDescriptorProto& proto) {
5911   VALIDATE_OPTIONS_FROM_ARRAY(file, message_type, Message);
5912   VALIDATE_OPTIONS_FROM_ARRAY(file, enum_type, Enum);
5913   VALIDATE_OPTIONS_FROM_ARRAY(file, service, Service);
5914   VALIDATE_OPTIONS_FROM_ARRAY(file, extension, Field);
5915 
5916   // Lite files can only be imported by other Lite files.
5917   if (!IsLite(file)) {
5918     for (int i = 0; i < file->dependency_count(); i++) {
5919       if (IsLite(file->dependency(i))) {
5920         AddError(
5921             file->dependency(i)->name(), proto,
5922             DescriptorPool::ErrorCollector::IMPORT,
5923             "Files that do not use optimize_for = LITE_RUNTIME cannot import "
5924             "files which do use this option.  This file is not lite, but it "
5925             "imports \"" +
5926                 file->dependency(i)->name() + "\" which is.");
5927         break;
5928       }
5929     }
5930   }
5931   if (file->syntax() == FileDescriptor::SYNTAX_PROTO3) {
5932     ValidateProto3(file, proto);
5933   }
5934 }
5935 
ValidateProto3(FileDescriptor * file,const FileDescriptorProto & proto)5936 void DescriptorBuilder::ValidateProto3(FileDescriptor* file,
5937                                        const FileDescriptorProto& proto) {
5938   for (int i = 0; i < file->extension_count(); ++i) {
5939     ValidateProto3Field(file->extensions_ + i, proto.extension(i));
5940   }
5941   for (int i = 0; i < file->message_type_count(); ++i) {
5942     ValidateProto3Message(file->message_types_ + i, proto.message_type(i));
5943   }
5944   for (int i = 0; i < file->enum_type_count(); ++i) {
5945     ValidateProto3Enum(file->enum_types_ + i, proto.enum_type(i));
5946   }
5947 }
5948 
ToLowercaseWithoutUnderscores(const std::string & name)5949 static std::string ToLowercaseWithoutUnderscores(const std::string& name) {
5950   std::string result;
5951   for (char character : name) {
5952     if (character != '_') {
5953       if (character >= 'A' && character <= 'Z') {
5954         result.push_back(character - 'A' + 'a');
5955       } else {
5956         result.push_back(character);
5957       }
5958     }
5959   }
5960   return result;
5961 }
5962 
ValidateProto3Message(Descriptor * message,const DescriptorProto & proto)5963 void DescriptorBuilder::ValidateProto3Message(Descriptor* message,
5964                                               const DescriptorProto& proto) {
5965   for (int i = 0; i < message->nested_type_count(); ++i) {
5966     ValidateProto3Message(message->nested_types_ + i, proto.nested_type(i));
5967   }
5968   for (int i = 0; i < message->enum_type_count(); ++i) {
5969     ValidateProto3Enum(message->enum_types_ + i, proto.enum_type(i));
5970   }
5971   for (int i = 0; i < message->field_count(); ++i) {
5972     ValidateProto3Field(message->fields_ + i, proto.field(i));
5973   }
5974   for (int i = 0; i < message->extension_count(); ++i) {
5975     ValidateProto3Field(message->extensions_ + i, proto.extension(i));
5976   }
5977   if (message->extension_range_count() > 0) {
5978     AddError(message->full_name(), proto.extension_range(0),
5979              DescriptorPool::ErrorCollector::NUMBER,
5980              "Extension ranges are not allowed in proto3.");
5981   }
5982   if (message->options().message_set_wire_format()) {
5983     // Using MessageSet doesn't make sense since we disallow extensions.
5984     AddError(message->full_name(), proto, DescriptorPool::ErrorCollector::NAME,
5985              "MessageSet is not supported in proto3.");
5986   }
5987 
5988   // In proto3, we reject field names if they conflict in camelCase.
5989   // Note that we currently enforce a stricter rule: Field names must be
5990   // unique after being converted to lowercase with underscores removed.
5991   std::map<std::string, const FieldDescriptor*> name_to_field;
5992   for (int i = 0; i < message->field_count(); ++i) {
5993     std::string lowercase_name =
5994         ToLowercaseWithoutUnderscores(message->field(i)->name());
5995     if (name_to_field.find(lowercase_name) != name_to_field.end()) {
5996       AddError(message->full_name(), proto.field(i),
5997                DescriptorPool::ErrorCollector::NAME,
5998                "The JSON camel-case name of field \"" +
5999                    message->field(i)->name() + "\" conflicts with field \"" +
6000                    name_to_field[lowercase_name]->name() + "\". This is not " +
6001                    "allowed in proto3.");
6002     } else {
6003       name_to_field[lowercase_name] = message->field(i);
6004     }
6005   }
6006 }
6007 
ValidateProto3Field(FieldDescriptor * field,const FieldDescriptorProto & proto)6008 void DescriptorBuilder::ValidateProto3Field(FieldDescriptor* field,
6009                                             const FieldDescriptorProto& proto) {
6010   if (field->is_extension() &&
6011       !AllowedExtendeeInProto3(field->containing_type()->full_name())) {
6012     AddError(field->full_name(), proto,
6013              DescriptorPool::ErrorCollector::EXTENDEE,
6014              "Extensions in proto3 are only allowed for defining options.");
6015   }
6016   if (field->is_required()) {
6017     AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
6018              "Required fields are not allowed in proto3.");
6019   }
6020   if (field->has_default_value()) {
6021     AddError(field->full_name(), proto,
6022              DescriptorPool::ErrorCollector::DEFAULT_VALUE,
6023              "Explicit default values are not allowed in proto3.");
6024   }
6025   if (field->cpp_type() == FieldDescriptor::CPPTYPE_ENUM &&
6026       field->enum_type() &&
6027       field->enum_type()->file()->syntax() != FileDescriptor::SYNTAX_PROTO3 &&
6028       field->enum_type()->file()->syntax() != FileDescriptor::SYNTAX_UNKNOWN) {
6029     // Proto3 messages can only use Proto3 enum types; otherwise we can't
6030     // guarantee that the default value is zero.
6031     AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
6032              "Enum type \"" + field->enum_type()->full_name() +
6033                  "\" is not a proto3 enum, but is used in \"" +
6034                  field->containing_type()->full_name() +
6035                  "\" which is a proto3 message type.");
6036   }
6037   if (field->type() == FieldDescriptor::TYPE_GROUP) {
6038     AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
6039              "Groups are not supported in proto3 syntax.");
6040   }
6041 }
6042 
ValidateProto3Enum(EnumDescriptor * enm,const EnumDescriptorProto & proto)6043 void DescriptorBuilder::ValidateProto3Enum(EnumDescriptor* enm,
6044                                            const EnumDescriptorProto& proto) {
6045   if (enm->value_count() > 0 && enm->value(0)->number() != 0) {
6046     AddError(enm->full_name(), proto.value(0),
6047              DescriptorPool::ErrorCollector::NUMBER,
6048              "The first enum value must be zero in proto3.");
6049   }
6050 }
6051 
ValidateMessageOptions(Descriptor * message,const DescriptorProto & proto)6052 void DescriptorBuilder::ValidateMessageOptions(Descriptor* message,
6053                                                const DescriptorProto& proto) {
6054   VALIDATE_OPTIONS_FROM_ARRAY(message, field, Field);
6055   VALIDATE_OPTIONS_FROM_ARRAY(message, nested_type, Message);
6056   VALIDATE_OPTIONS_FROM_ARRAY(message, enum_type, Enum);
6057   VALIDATE_OPTIONS_FROM_ARRAY(message, extension, Field);
6058 
6059   const int64 max_extension_range =
6060       static_cast<int64>(message->options().message_set_wire_format()
6061                              ? kint32max
6062                              : FieldDescriptor::kMaxNumber);
6063   for (int i = 0; i < message->extension_range_count(); ++i) {
6064     if (message->extension_range(i)->end > max_extension_range + 1) {
6065       AddError(message->full_name(), proto.extension_range(i),
6066                DescriptorPool::ErrorCollector::NUMBER,
6067                strings::Substitute("Extension numbers cannot be greater than $0.",
6068                                 max_extension_range));
6069     }
6070 
6071     ValidateExtensionRangeOptions(message->full_name(),
6072                                   message->extension_ranges_ + i,
6073                                   proto.extension_range(i));
6074   }
6075 }
6076 
6077 
ValidateFieldOptions(FieldDescriptor * field,const FieldDescriptorProto & proto)6078 void DescriptorBuilder::ValidateFieldOptions(
6079     FieldDescriptor* field, const FieldDescriptorProto& proto) {
6080   if (pool_->lazily_build_dependencies_ && (!field || !field->message_type())) {
6081     return;
6082   }
6083   // Only message type fields may be lazy.
6084   if (field->options().lazy()) {
6085     if (field->type() != FieldDescriptor::TYPE_MESSAGE) {
6086       AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
6087                "[lazy = true] can only be specified for submessage fields.");
6088     }
6089   }
6090 
6091   // Only repeated primitive fields may be packed.
6092   if (field->options().packed() && !field->is_packable()) {
6093     AddError(
6094         field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
6095         "[packed = true] can only be specified for repeated primitive fields.");
6096   }
6097 
6098   // Note:  Default instance may not yet be initialized here, so we have to
6099   //   avoid reading from it.
6100   if (field->containing_type_ != nullptr &&
6101       &field->containing_type()->options() !=
6102           &MessageOptions::default_instance() &&
6103       field->containing_type()->options().message_set_wire_format()) {
6104     if (field->is_extension()) {
6105       if (!field->is_optional() ||
6106           field->type() != FieldDescriptor::TYPE_MESSAGE) {
6107         AddError(field->full_name(), proto,
6108                  DescriptorPool::ErrorCollector::TYPE,
6109                  "Extensions of MessageSets must be optional messages.");
6110       }
6111     } else {
6112       AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::NAME,
6113                "MessageSets cannot have fields, only extensions.");
6114     }
6115   }
6116 
6117   // Lite extensions can only be of Lite types.
6118   if (IsLite(field->file()) && field->containing_type_ != nullptr &&
6119       !IsLite(field->containing_type()->file())) {
6120     AddError(field->full_name(), proto,
6121              DescriptorPool::ErrorCollector::EXTENDEE,
6122              "Extensions to non-lite types can only be declared in non-lite "
6123              "files.  Note that you cannot extend a non-lite type to contain "
6124              "a lite type, but the reverse is allowed.");
6125   }
6126 
6127   // Validate map types.
6128   if (field->is_map()) {
6129     if (!ValidateMapEntry(field, proto)) {
6130       AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
6131                "map_entry should not be set explicitly. Use map<KeyType, "
6132                "ValueType> instead.");
6133     }
6134   }
6135 
6136   ValidateJSType(field, proto);
6137 
6138   // json_name option is not allowed on extension fields. Note that the
6139   // json_name field in FieldDescriptorProto is always populated by protoc
6140   // when it sends descriptor data to plugins (calculated from field name if
6141   // the option is not explicitly set) so we can't rely on its presence to
6142   // determine whether the json_name option is set on the field. Here we
6143   // compare it against the default calculated json_name value and consider
6144   // the option set if they are different. This won't catch the case when
6145   // an user explicitly sets json_name to the default value, but should be
6146   // good enough to catch common misuses.
6147   if (field->is_extension() &&
6148       (field->has_json_name() &&
6149        field->json_name() != ToJsonName(field->name()))) {
6150     AddError(field->full_name(), proto,
6151              DescriptorPool::ErrorCollector::OPTION_NAME,
6152              "option json_name is not allowed on extension fields.");
6153   }
6154 
6155 }
6156 
ValidateEnumOptions(EnumDescriptor * enm,const EnumDescriptorProto & proto)6157 void DescriptorBuilder::ValidateEnumOptions(EnumDescriptor* enm,
6158                                             const EnumDescriptorProto& proto) {
6159   VALIDATE_OPTIONS_FROM_ARRAY(enm, value, EnumValue);
6160   if (!enm->options().has_allow_alias() || !enm->options().allow_alias()) {
6161     std::map<int, std::string> used_values;
6162     for (int i = 0; i < enm->value_count(); ++i) {
6163       const EnumValueDescriptor* enum_value = enm->value(i);
6164       if (used_values.find(enum_value->number()) != used_values.end()) {
6165         std::string error =
6166             "\"" + enum_value->full_name() +
6167             "\" uses the same enum value as \"" +
6168             used_values[enum_value->number()] +
6169             "\". If this is intended, set "
6170             "'option allow_alias = true;' to the enum definition.";
6171         if (!enm->options().allow_alias()) {
6172           // Generate error if duplicated enum values are explicitly disallowed.
6173           AddError(enm->full_name(), proto.value(i),
6174                    DescriptorPool::ErrorCollector::NUMBER, error);
6175         }
6176       } else {
6177         used_values[enum_value->number()] = enum_value->full_name();
6178       }
6179     }
6180   }
6181 }
6182 
ValidateEnumValueOptions(EnumValueDescriptor *,const EnumValueDescriptorProto &)6183 void DescriptorBuilder::ValidateEnumValueOptions(
6184     EnumValueDescriptor* /* enum_value */,
6185     const EnumValueDescriptorProto& /* proto */) {
6186   // Nothing to do so far.
6187 }
6188 
ValidateExtensionRangeOptions(const std::string & full_name,Descriptor::ExtensionRange * extension_range,const DescriptorProto_ExtensionRange & proto)6189 void DescriptorBuilder::ValidateExtensionRangeOptions(
6190     const std::string& full_name, Descriptor::ExtensionRange* extension_range,
6191     const DescriptorProto_ExtensionRange& proto) {
6192 }
6193 
ValidateServiceOptions(ServiceDescriptor * service,const ServiceDescriptorProto & proto)6194 void DescriptorBuilder::ValidateServiceOptions(
6195     ServiceDescriptor* service, const ServiceDescriptorProto& proto) {
6196   if (IsLite(service->file()) &&
6197       (service->file()->options().cc_generic_services() ||
6198        service->file()->options().java_generic_services())) {
6199     AddError(service->full_name(), proto, DescriptorPool::ErrorCollector::NAME,
6200              "Files with optimize_for = LITE_RUNTIME cannot define services "
6201              "unless you set both options cc_generic_services and "
6202              "java_generic_services to false.");
6203   }
6204 
6205   VALIDATE_OPTIONS_FROM_ARRAY(service, method, Method);
6206 }
6207 
ValidateMethodOptions(MethodDescriptor *,const MethodDescriptorProto &)6208 void DescriptorBuilder::ValidateMethodOptions(
6209     MethodDescriptor* /* method */, const MethodDescriptorProto& /* proto */) {
6210   // Nothing to do so far.
6211 }
6212 
ValidateMapEntry(FieldDescriptor * field,const FieldDescriptorProto & proto)6213 bool DescriptorBuilder::ValidateMapEntry(FieldDescriptor* field,
6214                                          const FieldDescriptorProto& proto) {
6215   const Descriptor* message = field->message_type();
6216   if (  // Must not contain extensions, extension range or nested message or
6217         // enums
6218       message->extension_count() != 0 ||
6219       field->label() != FieldDescriptor::LABEL_REPEATED ||
6220       message->extension_range_count() != 0 ||
6221       message->nested_type_count() != 0 || message->enum_type_count() != 0 ||
6222       // Must contain exactly two fields
6223       message->field_count() != 2 ||
6224       // Field name and message name must match
6225       message->name() != ToCamelCase(field->name(), false) + "Entry" ||
6226       // Entry message must be in the same containing type of the field.
6227       field->containing_type() != message->containing_type()) {
6228     return false;
6229   }
6230 
6231   const FieldDescriptor* key = message->map_key();
6232   const FieldDescriptor* value = message->map_value();
6233   if (key->label() != FieldDescriptor::LABEL_OPTIONAL || key->number() != 1 ||
6234       key->name() != "key") {
6235     return false;
6236   }
6237   if (value->label() != FieldDescriptor::LABEL_OPTIONAL ||
6238       value->number() != 2 || value->name() != "value") {
6239     return false;
6240   }
6241 
6242   // Check key types are legal.
6243   switch (key->type()) {
6244     case FieldDescriptor::TYPE_ENUM:
6245       AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
6246                "Key in map fields cannot be enum types.");
6247       break;
6248     case FieldDescriptor::TYPE_FLOAT:
6249     case FieldDescriptor::TYPE_DOUBLE:
6250     case FieldDescriptor::TYPE_MESSAGE:
6251     case FieldDescriptor::TYPE_GROUP:
6252     case FieldDescriptor::TYPE_BYTES:
6253       AddError(
6254           field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
6255           "Key in map fields cannot be float/double, bytes or message types.");
6256       break;
6257     case FieldDescriptor::TYPE_BOOL:
6258     case FieldDescriptor::TYPE_INT32:
6259     case FieldDescriptor::TYPE_INT64:
6260     case FieldDescriptor::TYPE_SINT32:
6261     case FieldDescriptor::TYPE_SINT64:
6262     case FieldDescriptor::TYPE_STRING:
6263     case FieldDescriptor::TYPE_UINT32:
6264     case FieldDescriptor::TYPE_UINT64:
6265     case FieldDescriptor::TYPE_FIXED32:
6266     case FieldDescriptor::TYPE_FIXED64:
6267     case FieldDescriptor::TYPE_SFIXED32:
6268     case FieldDescriptor::TYPE_SFIXED64:
6269       // Legal cases
6270       break;
6271       // Do not add a default, so that the compiler will complain when new types
6272       // are added.
6273   }
6274 
6275   if (value->type() == FieldDescriptor::TYPE_ENUM) {
6276     if (value->enum_type()->value(0)->number() != 0) {
6277       AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
6278                "Enum value in map must define 0 as the first value.");
6279     }
6280   }
6281 
6282   return true;
6283 }
6284 
DetectMapConflicts(const Descriptor * message,const DescriptorProto & proto)6285 void DescriptorBuilder::DetectMapConflicts(const Descriptor* message,
6286                                            const DescriptorProto& proto) {
6287   std::map<std::string, const Descriptor*> seen_types;
6288   for (int i = 0; i < message->nested_type_count(); ++i) {
6289     const Descriptor* nested = message->nested_type(i);
6290     std::pair<std::map<std::string, const Descriptor*>::iterator, bool> result =
6291         seen_types.insert(std::make_pair(nested->name(), nested));
6292     if (!result.second) {
6293       if (result.first->second->options().map_entry() ||
6294           nested->options().map_entry()) {
6295         AddError(message->full_name(), proto,
6296                  DescriptorPool::ErrorCollector::NAME,
6297                  "Expanded map entry type " + nested->name() +
6298                      " conflicts with an existing nested message type.");
6299       }
6300     }
6301     // Recursively test on the nested types.
6302     DetectMapConflicts(message->nested_type(i), proto.nested_type(i));
6303   }
6304   // Check for conflicted field names.
6305   for (int i = 0; i < message->field_count(); ++i) {
6306     const FieldDescriptor* field = message->field(i);
6307     std::map<std::string, const Descriptor*>::iterator iter =
6308         seen_types.find(field->name());
6309     if (iter != seen_types.end() && iter->second->options().map_entry()) {
6310       AddError(message->full_name(), proto,
6311                DescriptorPool::ErrorCollector::NAME,
6312                "Expanded map entry type " + iter->second->name() +
6313                    " conflicts with an existing field.");
6314     }
6315   }
6316   // Check for conflicted enum names.
6317   for (int i = 0; i < message->enum_type_count(); ++i) {
6318     const EnumDescriptor* enum_desc = message->enum_type(i);
6319     std::map<std::string, const Descriptor*>::iterator iter =
6320         seen_types.find(enum_desc->name());
6321     if (iter != seen_types.end() && iter->second->options().map_entry()) {
6322       AddError(message->full_name(), proto,
6323                DescriptorPool::ErrorCollector::NAME,
6324                "Expanded map entry type " + iter->second->name() +
6325                    " conflicts with an existing enum type.");
6326     }
6327   }
6328   // Check for conflicted oneof names.
6329   for (int i = 0; i < message->oneof_decl_count(); ++i) {
6330     const OneofDescriptor* oneof_desc = message->oneof_decl(i);
6331     std::map<std::string, const Descriptor*>::iterator iter =
6332         seen_types.find(oneof_desc->name());
6333     if (iter != seen_types.end() && iter->second->options().map_entry()) {
6334       AddError(message->full_name(), proto,
6335                DescriptorPool::ErrorCollector::NAME,
6336                "Expanded map entry type " + iter->second->name() +
6337                    " conflicts with an existing oneof type.");
6338     }
6339   }
6340 }
6341 
ValidateJSType(FieldDescriptor * field,const FieldDescriptorProto & proto)6342 void DescriptorBuilder::ValidateJSType(FieldDescriptor* field,
6343                                        const FieldDescriptorProto& proto) {
6344   FieldOptions::JSType jstype = field->options().jstype();
6345   // The default is always acceptable.
6346   if (jstype == FieldOptions::JS_NORMAL) {
6347     return;
6348   }
6349 
6350   switch (field->type()) {
6351     // Integral 64-bit types may be represented as JavaScript numbers or
6352     // strings.
6353     case FieldDescriptor::TYPE_UINT64:
6354     case FieldDescriptor::TYPE_INT64:
6355     case FieldDescriptor::TYPE_SINT64:
6356     case FieldDescriptor::TYPE_FIXED64:
6357     case FieldDescriptor::TYPE_SFIXED64:
6358       if (jstype == FieldOptions::JS_STRING ||
6359           jstype == FieldOptions::JS_NUMBER) {
6360         return;
6361       }
6362       AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
6363                "Illegal jstype for int64, uint64, sint64, fixed64 "
6364                "or sfixed64 field: " +
6365                    FieldOptions_JSType_descriptor()->value(jstype)->name());
6366       break;
6367 
6368     // No other types permit a jstype option.
6369     default:
6370       AddError(field->full_name(), proto, DescriptorPool::ErrorCollector::TYPE,
6371                "jstype is only allowed on int64, uint64, sint64, fixed64 "
6372                "or sfixed64 fields.");
6373       break;
6374   }
6375 }
6376 
6377 #undef VALIDATE_OPTIONS_FROM_ARRAY
6378 
6379 // -------------------------------------------------------------------
6380 
OptionInterpreter(DescriptorBuilder * builder)6381 DescriptorBuilder::OptionInterpreter::OptionInterpreter(
6382     DescriptorBuilder* builder)
6383     : builder_(builder) {
6384   GOOGLE_CHECK(builder_);
6385 }
6386 
~OptionInterpreter()6387 DescriptorBuilder::OptionInterpreter::~OptionInterpreter() {}
6388 
InterpretOptions(OptionsToInterpret * options_to_interpret)6389 bool DescriptorBuilder::OptionInterpreter::InterpretOptions(
6390     OptionsToInterpret* options_to_interpret) {
6391   // Note that these may be in different pools, so we can't use the same
6392   // descriptor and reflection objects on both.
6393   Message* options = options_to_interpret->options;
6394   const Message* original_options = options_to_interpret->original_options;
6395 
6396   bool failed = false;
6397   options_to_interpret_ = options_to_interpret;
6398 
6399   // Find the uninterpreted_option field in the mutable copy of the options
6400   // and clear them, since we're about to interpret them.
6401   const FieldDescriptor* uninterpreted_options_field =
6402       options->GetDescriptor()->FindFieldByName("uninterpreted_option");
6403   GOOGLE_CHECK(uninterpreted_options_field != nullptr)
6404       << "No field named \"uninterpreted_option\" in the Options proto.";
6405   options->GetReflection()->ClearField(options, uninterpreted_options_field);
6406 
6407   std::vector<int> src_path = options_to_interpret->element_path;
6408   src_path.push_back(uninterpreted_options_field->number());
6409 
6410   // Find the uninterpreted_option field in the original options.
6411   const FieldDescriptor* original_uninterpreted_options_field =
6412       original_options->GetDescriptor()->FindFieldByName(
6413           "uninterpreted_option");
6414   GOOGLE_CHECK(original_uninterpreted_options_field != nullptr)
6415       << "No field named \"uninterpreted_option\" in the Options proto.";
6416 
6417   const int num_uninterpreted_options =
6418       original_options->GetReflection()->FieldSize(
6419           *original_options, original_uninterpreted_options_field);
6420   for (int i = 0; i < num_uninterpreted_options; ++i) {
6421     src_path.push_back(i);
6422     uninterpreted_option_ = down_cast<const UninterpretedOption*>(
6423         &original_options->GetReflection()->GetRepeatedMessage(
6424             *original_options, original_uninterpreted_options_field, i));
6425     if (!InterpretSingleOption(options, src_path,
6426                                options_to_interpret->element_path)) {
6427       // Error already added by InterpretSingleOption().
6428       failed = true;
6429       break;
6430     }
6431     src_path.pop_back();
6432   }
6433   // Reset these, so we don't have any dangling pointers.
6434   uninterpreted_option_ = nullptr;
6435   options_to_interpret_ = nullptr;
6436 
6437   if (!failed) {
6438     // InterpretSingleOption() added the interpreted options in the
6439     // UnknownFieldSet, in case the option isn't yet known to us.  Now we
6440     // serialize the options message and deserialize it back.  That way, any
6441     // option fields that we do happen to know about will get moved from the
6442     // UnknownFieldSet into the real fields, and thus be available right away.
6443     // If they are not known, that's OK too. They will get reparsed into the
6444     // UnknownFieldSet and wait there until the message is parsed by something
6445     // that does know about the options.
6446 
6447     // Keep the unparsed options around in case the reparsing fails.
6448     std::unique_ptr<Message> unparsed_options(options->New());
6449     options->GetReflection()->Swap(unparsed_options.get(), options);
6450 
6451     std::string buf;
6452     if (!unparsed_options->AppendToString(&buf) ||
6453         !options->ParseFromString(buf)) {
6454       builder_->AddError(
6455           options_to_interpret->element_name, *original_options,
6456           DescriptorPool::ErrorCollector::OTHER,
6457           "Some options could not be correctly parsed using the proto "
6458           "descriptors compiled into this binary.\n"
6459           "Unparsed options: " +
6460               unparsed_options->ShortDebugString() +
6461               "\n"
6462               "Parsing attempt:  " +
6463               options->ShortDebugString());
6464       // Restore the unparsed options.
6465       options->GetReflection()->Swap(unparsed_options.get(), options);
6466     }
6467   }
6468 
6469   return !failed;
6470 }
6471 
InterpretSingleOption(Message * options,const std::vector<int> & src_path,const std::vector<int> & options_path)6472 bool DescriptorBuilder::OptionInterpreter::InterpretSingleOption(
6473     Message* options, const std::vector<int>& src_path,
6474     const std::vector<int>& options_path) {
6475   // First do some basic validation.
6476   if (uninterpreted_option_->name_size() == 0) {
6477     // This should never happen unless the parser has gone seriously awry or
6478     // someone has manually created the uninterpreted option badly.
6479     return AddNameError("Option must have a name.");
6480   }
6481   if (uninterpreted_option_->name(0).name_part() == "uninterpreted_option") {
6482     return AddNameError(
6483         "Option must not use reserved name "
6484         "\"uninterpreted_option\".");
6485   }
6486 
6487   const Descriptor* options_descriptor = nullptr;
6488   // Get the options message's descriptor from the builder's pool, so that we
6489   // get the version that knows about any extension options declared in the file
6490   // we're currently building. The descriptor should be there as long as the
6491   // file we're building imported descriptor.proto.
6492 
6493   // Note that we use DescriptorBuilder::FindSymbolNotEnforcingDeps(), not
6494   // DescriptorPool::FindMessageTypeByName() because we're already holding the
6495   // pool's mutex, and the latter method locks it again.  We don't use
6496   // FindSymbol() because files that use custom options only need to depend on
6497   // the file that defines the option, not descriptor.proto itself.
6498   Symbol symbol = builder_->FindSymbolNotEnforcingDeps(
6499       options->GetDescriptor()->full_name());
6500   if (!symbol.IsNull() && symbol.type == Symbol::MESSAGE) {
6501     options_descriptor = symbol.descriptor;
6502   } else {
6503     // The options message's descriptor was not in the builder's pool, so use
6504     // the standard version from the generated pool. We're not holding the
6505     // generated pool's mutex, so we can search it the straightforward way.
6506     options_descriptor = options->GetDescriptor();
6507   }
6508   GOOGLE_CHECK(options_descriptor);
6509 
6510   // We iterate over the name parts to drill into the submessages until we find
6511   // the leaf field for the option. As we drill down we remember the current
6512   // submessage's descriptor in |descriptor| and the next field in that
6513   // submessage in |field|. We also track the fields we're drilling down
6514   // through in |intermediate_fields|. As we go, we reconstruct the full option
6515   // name in |debug_msg_name|, for use in error messages.
6516   const Descriptor* descriptor = options_descriptor;
6517   const FieldDescriptor* field = nullptr;
6518   std::vector<const FieldDescriptor*> intermediate_fields;
6519   std::string debug_msg_name = "";
6520 
6521   std::vector<int> dest_path = options_path;
6522 
6523   for (int i = 0; i < uninterpreted_option_->name_size(); ++i) {
6524     builder_->undefine_resolved_name_.clear();
6525     const std::string& name_part = uninterpreted_option_->name(i).name_part();
6526     if (debug_msg_name.size() > 0) {
6527       debug_msg_name += ".";
6528     }
6529     if (uninterpreted_option_->name(i).is_extension()) {
6530       debug_msg_name += "(" + name_part + ")";
6531       // Search for the extension's descriptor as an extension in the builder's
6532       // pool. Note that we use DescriptorBuilder::LookupSymbol(), not
6533       // DescriptorPool::FindExtensionByName(), for two reasons: 1) It allows
6534       // relative lookups, and 2) because we're already holding the pool's
6535       // mutex, and the latter method locks it again.
6536       symbol =
6537           builder_->LookupSymbol(name_part, options_to_interpret_->name_scope);
6538       if (!symbol.IsNull() && symbol.type == Symbol::FIELD) {
6539         field = symbol.field_descriptor;
6540       }
6541       // If we don't find the field then the field's descriptor was not in the
6542       // builder's pool, but there's no point in looking in the generated
6543       // pool. We require that you import the file that defines any extensions
6544       // you use, so they must be present in the builder's pool.
6545     } else {
6546       debug_msg_name += name_part;
6547       // Search for the field's descriptor as a regular field.
6548       field = descriptor->FindFieldByName(name_part);
6549     }
6550 
6551     if (field == nullptr) {
6552       if (get_allow_unknown(builder_->pool_)) {
6553         // We can't find the option, but AllowUnknownDependencies() is enabled,
6554         // so we will just leave it as uninterpreted.
6555         AddWithoutInterpreting(*uninterpreted_option_, options);
6556         return true;
6557       } else if (!(builder_->undefine_resolved_name_).empty()) {
6558         // Option is resolved to a name which is not defined.
6559         return AddNameError(
6560             "Option \"" + debug_msg_name + "\" is resolved to \"(" +
6561             builder_->undefine_resolved_name_ +
6562             ")\", which is not defined. The innermost scope is searched first "
6563             "in name resolution. Consider using a leading '.'(i.e., \"(." +
6564             debug_msg_name.substr(1) +
6565             "\") to start from the outermost scope.");
6566       } else {
6567         return AddNameError(
6568             "Option \"" + debug_msg_name +
6569             "\" unknown. Ensure that your proto" +
6570             " definition file imports the proto which defines the option.");
6571       }
6572     } else if (field->containing_type() != descriptor) {
6573       if (get_is_placeholder(field->containing_type())) {
6574         // The field is an extension of a placeholder type, so we can't
6575         // reliably verify whether it is a valid extension to use here (e.g.
6576         // we don't know if it is an extension of the correct *Options message,
6577         // or if it has a valid field number, etc.).  Just leave it as
6578         // uninterpreted instead.
6579         AddWithoutInterpreting(*uninterpreted_option_, options);
6580         return true;
6581       } else {
6582         // This can only happen if, due to some insane misconfiguration of the
6583         // pools, we find the options message in one pool but the field in
6584         // another. This would probably imply a hefty bug somewhere.
6585         return AddNameError("Option field \"" + debug_msg_name +
6586                             "\" is not a field or extension of message \"" +
6587                             descriptor->name() + "\".");
6588       }
6589     } else {
6590       // accumulate field numbers to form path to interpreted option
6591       dest_path.push_back(field->number());
6592 
6593       if (i < uninterpreted_option_->name_size() - 1) {
6594         if (field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) {
6595           return AddNameError("Option \"" + debug_msg_name +
6596                               "\" is an atomic type, not a message.");
6597         } else if (field->is_repeated()) {
6598           return AddNameError("Option field \"" + debug_msg_name +
6599                               "\" is a repeated message. Repeated message "
6600                               "options must be initialized using an "
6601                               "aggregate value.");
6602         } else {
6603           // Drill down into the submessage.
6604           intermediate_fields.push_back(field);
6605           descriptor = field->message_type();
6606         }
6607       }
6608     }
6609   }
6610 
6611   // We've found the leaf field. Now we use UnknownFieldSets to set its value
6612   // on the options message. We do so because the message may not yet know
6613   // about its extension fields, so we may not be able to set the fields
6614   // directly. But the UnknownFieldSets will serialize to the same wire-format
6615   // message, so reading that message back in once the extension fields are
6616   // known will populate them correctly.
6617 
6618   // First see if the option is already set.
6619   if (!field->is_repeated() &&
6620       !ExamineIfOptionIsSet(
6621           intermediate_fields.begin(), intermediate_fields.end(), field,
6622           debug_msg_name,
6623           options->GetReflection()->GetUnknownFields(*options))) {
6624     return false;  // ExamineIfOptionIsSet() already added the error.
6625   }
6626 
6627   // First set the value on the UnknownFieldSet corresponding to the
6628   // innermost message.
6629   std::unique_ptr<UnknownFieldSet> unknown_fields(new UnknownFieldSet());
6630   if (!SetOptionValue(field, unknown_fields.get())) {
6631     return false;  // SetOptionValue() already added the error.
6632   }
6633 
6634   // Now wrap the UnknownFieldSet with UnknownFieldSets corresponding to all
6635   // the intermediate messages.
6636   for (std::vector<const FieldDescriptor*>::reverse_iterator iter =
6637            intermediate_fields.rbegin();
6638        iter != intermediate_fields.rend(); ++iter) {
6639     std::unique_ptr<UnknownFieldSet> parent_unknown_fields(
6640         new UnknownFieldSet());
6641     switch ((*iter)->type()) {
6642       case FieldDescriptor::TYPE_MESSAGE: {
6643         io::StringOutputStream outstr(
6644             parent_unknown_fields->AddLengthDelimited((*iter)->number()));
6645         io::CodedOutputStream out(&outstr);
6646         internal::WireFormat::SerializeUnknownFields(*unknown_fields, &out);
6647         GOOGLE_CHECK(!out.HadError())
6648             << "Unexpected failure while serializing option submessage "
6649             << debug_msg_name << "\".";
6650         break;
6651       }
6652 
6653       case FieldDescriptor::TYPE_GROUP: {
6654         parent_unknown_fields->AddGroup((*iter)->number())
6655             ->MergeFrom(*unknown_fields);
6656         break;
6657       }
6658 
6659       default:
6660         GOOGLE_LOG(FATAL) << "Invalid wire type for CPPTYPE_MESSAGE: "
6661                    << (*iter)->type();
6662         return false;
6663     }
6664     unknown_fields.reset(parent_unknown_fields.release());
6665   }
6666 
6667   // Now merge the UnknownFieldSet corresponding to the top-level message into
6668   // the options message.
6669   options->GetReflection()->MutableUnknownFields(options)->MergeFrom(
6670       *unknown_fields);
6671 
6672   // record the element path of the interpreted option
6673   if (field->is_repeated()) {
6674     int index = repeated_option_counts_[dest_path]++;
6675     dest_path.push_back(index);
6676   }
6677   interpreted_paths_[src_path] = dest_path;
6678 
6679   return true;
6680 }
6681 
UpdateSourceCodeInfo(SourceCodeInfo * info)6682 void DescriptorBuilder::OptionInterpreter::UpdateSourceCodeInfo(
6683     SourceCodeInfo* info) {
6684   if (interpreted_paths_.empty()) {
6685     // nothing to do!
6686     return;
6687   }
6688 
6689   // We find locations that match keys in interpreted_paths_ and
6690   // 1) replace the path with the corresponding value in interpreted_paths_
6691   // 2) remove any subsequent sub-locations (sub-location is one whose path
6692   //    has the parent path as a prefix)
6693   //
6694   // To avoid quadratic behavior of removing interior rows as we go,
6695   // we keep a copy. But we don't actually copy anything until we've
6696   // found the first match (so if the source code info has no locations
6697   // that need to be changed, there is zero copy overhead).
6698 
6699   RepeatedPtrField<SourceCodeInfo_Location>* locs = info->mutable_location();
6700   RepeatedPtrField<SourceCodeInfo_Location> new_locs;
6701   bool copying = false;
6702 
6703   std::vector<int> pathv;
6704   bool matched = false;
6705 
6706   for (RepeatedPtrField<SourceCodeInfo_Location>::iterator loc = locs->begin();
6707        loc != locs->end(); loc++) {
6708     if (matched) {
6709       // see if this location is in the range to remove
6710       bool loc_matches = true;
6711       if (loc->path_size() < static_cast<int64>(pathv.size())) {
6712         loc_matches = false;
6713       } else {
6714         for (size_t j = 0; j < pathv.size(); j++) {
6715           if (loc->path(j) != pathv[j]) {
6716             loc_matches = false;
6717             break;
6718           }
6719         }
6720       }
6721 
6722       if (loc_matches) {
6723         // don't copy this row since it is a sub-location that we're removing
6724         continue;
6725       }
6726 
6727       matched = false;
6728     }
6729 
6730     pathv.clear();
6731     for (int j = 0; j < loc->path_size(); j++) {
6732       pathv.push_back(loc->path(j));
6733     }
6734 
6735     std::map<std::vector<int>, std::vector<int>>::iterator entry =
6736         interpreted_paths_.find(pathv);
6737 
6738     if (entry == interpreted_paths_.end()) {
6739       // not a match
6740       if (copying) {
6741         *new_locs.Add() = *loc;
6742       }
6743       continue;
6744     }
6745 
6746     matched = true;
6747 
6748     if (!copying) {
6749       // initialize the copy we are building
6750       copying = true;
6751       new_locs.Reserve(locs->size());
6752       for (RepeatedPtrField<SourceCodeInfo_Location>::iterator it =
6753                locs->begin();
6754            it != loc; it++) {
6755         *new_locs.Add() = *it;
6756       }
6757     }
6758 
6759     // add replacement and update its path
6760     SourceCodeInfo_Location* replacement = new_locs.Add();
6761     *replacement = *loc;
6762     replacement->clear_path();
6763     for (std::vector<int>::iterator rit = entry->second.begin();
6764          rit != entry->second.end(); rit++) {
6765       replacement->add_path(*rit);
6766     }
6767   }
6768 
6769   // if we made a changed copy, put it in place
6770   if (copying) {
6771     *locs = new_locs;
6772   }
6773 }
6774 
AddWithoutInterpreting(const UninterpretedOption & uninterpreted_option,Message * options)6775 void DescriptorBuilder::OptionInterpreter::AddWithoutInterpreting(
6776     const UninterpretedOption& uninterpreted_option, Message* options) {
6777   const FieldDescriptor* field =
6778       options->GetDescriptor()->FindFieldByName("uninterpreted_option");
6779   GOOGLE_CHECK(field != nullptr);
6780 
6781   options->GetReflection()
6782       ->AddMessage(options, field)
6783       ->CopyFrom(uninterpreted_option);
6784 }
6785 
ExamineIfOptionIsSet(std::vector<const FieldDescriptor * >::const_iterator intermediate_fields_iter,std::vector<const FieldDescriptor * >::const_iterator intermediate_fields_end,const FieldDescriptor * innermost_field,const std::string & debug_msg_name,const UnknownFieldSet & unknown_fields)6786 bool DescriptorBuilder::OptionInterpreter::ExamineIfOptionIsSet(
6787     std::vector<const FieldDescriptor*>::const_iterator
6788         intermediate_fields_iter,
6789     std::vector<const FieldDescriptor*>::const_iterator intermediate_fields_end,
6790     const FieldDescriptor* innermost_field, const std::string& debug_msg_name,
6791     const UnknownFieldSet& unknown_fields) {
6792   // We do linear searches of the UnknownFieldSet and its sub-groups.  This
6793   // should be fine since it's unlikely that any one options structure will
6794   // contain more than a handful of options.
6795 
6796   if (intermediate_fields_iter == intermediate_fields_end) {
6797     // We're at the innermost submessage.
6798     for (int i = 0; i < unknown_fields.field_count(); i++) {
6799       if (unknown_fields.field(i).number() == innermost_field->number()) {
6800         return AddNameError("Option \"" + debug_msg_name +
6801                             "\" was already set.");
6802       }
6803     }
6804     return true;
6805   }
6806 
6807   for (int i = 0; i < unknown_fields.field_count(); i++) {
6808     if (unknown_fields.field(i).number() ==
6809         (*intermediate_fields_iter)->number()) {
6810       const UnknownField* unknown_field = &unknown_fields.field(i);
6811       FieldDescriptor::Type type = (*intermediate_fields_iter)->type();
6812       // Recurse into the next submessage.
6813       switch (type) {
6814         case FieldDescriptor::TYPE_MESSAGE:
6815           if (unknown_field->type() == UnknownField::TYPE_LENGTH_DELIMITED) {
6816             UnknownFieldSet intermediate_unknown_fields;
6817             if (intermediate_unknown_fields.ParseFromString(
6818                     unknown_field->length_delimited()) &&
6819                 !ExamineIfOptionIsSet(intermediate_fields_iter + 1,
6820                                       intermediate_fields_end, innermost_field,
6821                                       debug_msg_name,
6822                                       intermediate_unknown_fields)) {
6823               return false;  // Error already added.
6824             }
6825           }
6826           break;
6827 
6828         case FieldDescriptor::TYPE_GROUP:
6829           if (unknown_field->type() == UnknownField::TYPE_GROUP) {
6830             if (!ExamineIfOptionIsSet(intermediate_fields_iter + 1,
6831                                       intermediate_fields_end, innermost_field,
6832                                       debug_msg_name, unknown_field->group())) {
6833               return false;  // Error already added.
6834             }
6835           }
6836           break;
6837 
6838         default:
6839           GOOGLE_LOG(FATAL) << "Invalid wire type for CPPTYPE_MESSAGE: " << type;
6840           return false;
6841       }
6842     }
6843   }
6844   return true;
6845 }
6846 
SetOptionValue(const FieldDescriptor * option_field,UnknownFieldSet * unknown_fields)6847 bool DescriptorBuilder::OptionInterpreter::SetOptionValue(
6848     const FieldDescriptor* option_field, UnknownFieldSet* unknown_fields) {
6849   // We switch on the CppType to validate.
6850   switch (option_field->cpp_type()) {
6851     case FieldDescriptor::CPPTYPE_INT32:
6852       if (uninterpreted_option_->has_positive_int_value()) {
6853         if (uninterpreted_option_->positive_int_value() >
6854             static_cast<uint64>(kint32max)) {
6855           return AddValueError("Value out of range for int32 option \"" +
6856                                option_field->full_name() + "\".");
6857         } else {
6858           SetInt32(option_field->number(),
6859                    uninterpreted_option_->positive_int_value(),
6860                    option_field->type(), unknown_fields);
6861         }
6862       } else if (uninterpreted_option_->has_negative_int_value()) {
6863         if (uninterpreted_option_->negative_int_value() <
6864             static_cast<int64>(kint32min)) {
6865           return AddValueError("Value out of range for int32 option \"" +
6866                                option_field->full_name() + "\".");
6867         } else {
6868           SetInt32(option_field->number(),
6869                    uninterpreted_option_->negative_int_value(),
6870                    option_field->type(), unknown_fields);
6871         }
6872       } else {
6873         return AddValueError("Value must be integer for int32 option \"" +
6874                              option_field->full_name() + "\".");
6875       }
6876       break;
6877 
6878     case FieldDescriptor::CPPTYPE_INT64:
6879       if (uninterpreted_option_->has_positive_int_value()) {
6880         if (uninterpreted_option_->positive_int_value() >
6881             static_cast<uint64>(kint64max)) {
6882           return AddValueError("Value out of range for int64 option \"" +
6883                                option_field->full_name() + "\".");
6884         } else {
6885           SetInt64(option_field->number(),
6886                    uninterpreted_option_->positive_int_value(),
6887                    option_field->type(), unknown_fields);
6888         }
6889       } else if (uninterpreted_option_->has_negative_int_value()) {
6890         SetInt64(option_field->number(),
6891                  uninterpreted_option_->negative_int_value(),
6892                  option_field->type(), unknown_fields);
6893       } else {
6894         return AddValueError("Value must be integer for int64 option \"" +
6895                              option_field->full_name() + "\".");
6896       }
6897       break;
6898 
6899     case FieldDescriptor::CPPTYPE_UINT32:
6900       if (uninterpreted_option_->has_positive_int_value()) {
6901         if (uninterpreted_option_->positive_int_value() > kuint32max) {
6902           return AddValueError("Value out of range for uint32 option \"" +
6903                                option_field->name() + "\".");
6904         } else {
6905           SetUInt32(option_field->number(),
6906                     uninterpreted_option_->positive_int_value(),
6907                     option_field->type(), unknown_fields);
6908         }
6909       } else {
6910         return AddValueError(
6911             "Value must be non-negative integer for uint32 "
6912             "option \"" +
6913             option_field->full_name() + "\".");
6914       }
6915       break;
6916 
6917     case FieldDescriptor::CPPTYPE_UINT64:
6918       if (uninterpreted_option_->has_positive_int_value()) {
6919         SetUInt64(option_field->number(),
6920                   uninterpreted_option_->positive_int_value(),
6921                   option_field->type(), unknown_fields);
6922       } else {
6923         return AddValueError(
6924             "Value must be non-negative integer for uint64 "
6925             "option \"" +
6926             option_field->full_name() + "\".");
6927       }
6928       break;
6929 
6930     case FieldDescriptor::CPPTYPE_FLOAT: {
6931       float value;
6932       if (uninterpreted_option_->has_double_value()) {
6933         value = uninterpreted_option_->double_value();
6934       } else if (uninterpreted_option_->has_positive_int_value()) {
6935         value = uninterpreted_option_->positive_int_value();
6936       } else if (uninterpreted_option_->has_negative_int_value()) {
6937         value = uninterpreted_option_->negative_int_value();
6938       } else {
6939         return AddValueError("Value must be number for float option \"" +
6940                              option_field->full_name() + "\".");
6941       }
6942       unknown_fields->AddFixed32(option_field->number(),
6943                                  internal::WireFormatLite::EncodeFloat(value));
6944       break;
6945     }
6946 
6947     case FieldDescriptor::CPPTYPE_DOUBLE: {
6948       double value;
6949       if (uninterpreted_option_->has_double_value()) {
6950         value = uninterpreted_option_->double_value();
6951       } else if (uninterpreted_option_->has_positive_int_value()) {
6952         value = uninterpreted_option_->positive_int_value();
6953       } else if (uninterpreted_option_->has_negative_int_value()) {
6954         value = uninterpreted_option_->negative_int_value();
6955       } else {
6956         return AddValueError("Value must be number for double option \"" +
6957                              option_field->full_name() + "\".");
6958       }
6959       unknown_fields->AddFixed64(option_field->number(),
6960                                  internal::WireFormatLite::EncodeDouble(value));
6961       break;
6962     }
6963 
6964     case FieldDescriptor::CPPTYPE_BOOL:
6965       uint64 value;
6966       if (!uninterpreted_option_->has_identifier_value()) {
6967         return AddValueError(
6968             "Value must be identifier for boolean option "
6969             "\"" +
6970             option_field->full_name() + "\".");
6971       }
6972       if (uninterpreted_option_->identifier_value() == "true") {
6973         value = 1;
6974       } else if (uninterpreted_option_->identifier_value() == "false") {
6975         value = 0;
6976       } else {
6977         return AddValueError(
6978             "Value must be \"true\" or \"false\" for boolean "
6979             "option \"" +
6980             option_field->full_name() + "\".");
6981       }
6982       unknown_fields->AddVarint(option_field->number(), value);
6983       break;
6984 
6985     case FieldDescriptor::CPPTYPE_ENUM: {
6986       if (!uninterpreted_option_->has_identifier_value()) {
6987         return AddValueError(
6988             "Value must be identifier for enum-valued option "
6989             "\"" +
6990             option_field->full_name() + "\".");
6991       }
6992       const EnumDescriptor* enum_type = option_field->enum_type();
6993       const std::string& value_name = uninterpreted_option_->identifier_value();
6994       const EnumValueDescriptor* enum_value = nullptr;
6995 
6996       if (enum_type->file()->pool() != DescriptorPool::generated_pool()) {
6997         // Note that the enum value's fully-qualified name is a sibling of the
6998         // enum's name, not a child of it.
6999         std::string fully_qualified_name = enum_type->full_name();
7000         fully_qualified_name.resize(fully_qualified_name.size() -
7001                                     enum_type->name().size());
7002         fully_qualified_name += value_name;
7003 
7004         // Search for the enum value's descriptor in the builder's pool. Note
7005         // that we use DescriptorBuilder::FindSymbolNotEnforcingDeps(), not
7006         // DescriptorPool::FindEnumValueByName() because we're already holding
7007         // the pool's mutex, and the latter method locks it again.
7008         Symbol symbol =
7009             builder_->FindSymbolNotEnforcingDeps(fully_qualified_name);
7010         if (!symbol.IsNull() && symbol.type == Symbol::ENUM_VALUE) {
7011           if (symbol.enum_value_descriptor->type() != enum_type) {
7012             return AddValueError(
7013                 "Enum type \"" + enum_type->full_name() +
7014                 "\" has no value named \"" + value_name + "\" for option \"" +
7015                 option_field->full_name() +
7016                 "\". This appears to be a value from a sibling type.");
7017           } else {
7018             enum_value = symbol.enum_value_descriptor;
7019           }
7020         }
7021       } else {
7022         // The enum type is in the generated pool, so we can search for the
7023         // value there.
7024         enum_value = enum_type->FindValueByName(value_name);
7025       }
7026 
7027       if (enum_value == nullptr) {
7028         return AddValueError("Enum type \"" +
7029                              option_field->enum_type()->full_name() +
7030                              "\" has no value named \"" + value_name +
7031                              "\" for "
7032                              "option \"" +
7033                              option_field->full_name() + "\".");
7034       } else {
7035         // Sign-extension is not a problem, since we cast directly from int32 to
7036         // uint64, without first going through uint32.
7037         unknown_fields->AddVarint(
7038             option_field->number(),
7039             static_cast<uint64>(static_cast<int64>(enum_value->number())));
7040       }
7041       break;
7042     }
7043 
7044     case FieldDescriptor::CPPTYPE_STRING:
7045       if (!uninterpreted_option_->has_string_value()) {
7046         return AddValueError(
7047             "Value must be quoted string for string option "
7048             "\"" +
7049             option_field->full_name() + "\".");
7050       }
7051       // The string has already been unquoted and unescaped by the parser.
7052       unknown_fields->AddLengthDelimited(option_field->number(),
7053                                          uninterpreted_option_->string_value());
7054       break;
7055 
7056     case FieldDescriptor::CPPTYPE_MESSAGE:
7057       if (!SetAggregateOption(option_field, unknown_fields)) {
7058         return false;
7059       }
7060       break;
7061   }
7062 
7063   return true;
7064 }
7065 
7066 class DescriptorBuilder::OptionInterpreter::AggregateOptionFinder
7067     : public TextFormat::Finder {
7068  public:
7069   DescriptorBuilder* builder_;
7070 
FindAnyType(const Message & message,const std::string & prefix,const std::string & name) const7071   const Descriptor* FindAnyType(const Message& message,
7072                                 const std::string& prefix,
7073                                 const std::string& name) const override {
7074     if (prefix != internal::kTypeGoogleApisComPrefix &&
7075         prefix != internal::kTypeGoogleProdComPrefix) {
7076       return nullptr;
7077     }
7078     assert_mutex_held(builder_->pool_);
7079     Symbol result = builder_->FindSymbol(name);
7080     return result.type == Symbol::MESSAGE ? result.descriptor : nullptr;
7081   }
7082 
FindExtension(Message * message,const std::string & name) const7083   const FieldDescriptor* FindExtension(Message* message,
7084                                        const std::string& name) const override {
7085     assert_mutex_held(builder_->pool_);
7086     const Descriptor* descriptor = message->GetDescriptor();
7087     Symbol result =
7088         builder_->LookupSymbolNoPlaceholder(name, descriptor->full_name());
7089     if (result.type == Symbol::FIELD &&
7090         result.field_descriptor->is_extension()) {
7091       return result.field_descriptor;
7092     } else if (result.type == Symbol::MESSAGE &&
7093                descriptor->options().message_set_wire_format()) {
7094       const Descriptor* foreign_type = result.descriptor;
7095       // The text format allows MessageSet items to be specified using
7096       // the type name, rather than the extension identifier. If the symbol
7097       // lookup returned a Message, and the enclosing Message has
7098       // message_set_wire_format = true, then return the message set
7099       // extension, if one exists.
7100       for (int i = 0; i < foreign_type->extension_count(); i++) {
7101         const FieldDescriptor* extension = foreign_type->extension(i);
7102         if (extension->containing_type() == descriptor &&
7103             extension->type() == FieldDescriptor::TYPE_MESSAGE &&
7104             extension->is_optional() &&
7105             extension->message_type() == foreign_type) {
7106           // Found it.
7107           return extension;
7108         }
7109       }
7110     }
7111     return nullptr;
7112   }
7113 };
7114 
7115 // A custom error collector to record any text-format parsing errors
7116 namespace {
7117 class AggregateErrorCollector : public io::ErrorCollector {
7118  public:
7119   std::string error_;
7120 
AddError(int,int,const std::string & message)7121   void AddError(int /* line */, int /* column */,
7122                 const std::string& message) override {
7123     if (!error_.empty()) {
7124       error_ += "; ";
7125     }
7126     error_ += message;
7127   }
7128 
AddWarning(int,int,const std::string &)7129   void AddWarning(int /* line */, int /* column */,
7130                   const std::string& /* message */) override {
7131     // Ignore warnings
7132   }
7133 };
7134 }  // namespace
7135 
7136 // We construct a dynamic message of the type corresponding to
7137 // option_field, parse the supplied text-format string into this
7138 // message, and serialize the resulting message to produce the value.
SetAggregateOption(const FieldDescriptor * option_field,UnknownFieldSet * unknown_fields)7139 bool DescriptorBuilder::OptionInterpreter::SetAggregateOption(
7140     const FieldDescriptor* option_field, UnknownFieldSet* unknown_fields) {
7141   if (!uninterpreted_option_->has_aggregate_value()) {
7142     return AddValueError("Option \"" + option_field->full_name() +
7143                          "\" is a message. To set the entire message, use "
7144                          "syntax like \"" +
7145                          option_field->name() +
7146                          " = { <proto text format> }\". "
7147                          "To set fields within it, use "
7148                          "syntax like \"" +
7149                          option_field->name() + ".foo = value\".");
7150   }
7151 
7152   const Descriptor* type = option_field->message_type();
7153   std::unique_ptr<Message> dynamic(dynamic_factory_.GetPrototype(type)->New());
7154   GOOGLE_CHECK(dynamic.get() != nullptr)
7155       << "Could not create an instance of " << option_field->DebugString();
7156 
7157   AggregateErrorCollector collector;
7158   AggregateOptionFinder finder;
7159   finder.builder_ = builder_;
7160   TextFormat::Parser parser;
7161   parser.RecordErrorsTo(&collector);
7162   parser.SetFinder(&finder);
7163   if (!parser.ParseFromString(uninterpreted_option_->aggregate_value(),
7164                               dynamic.get())) {
7165     AddValueError("Error while parsing option value for \"" +
7166                   option_field->name() + "\": " + collector.error_);
7167     return false;
7168   } else {
7169     std::string serial;
7170     dynamic->SerializeToString(&serial);  // Never fails
7171     if (option_field->type() == FieldDescriptor::TYPE_MESSAGE) {
7172       unknown_fields->AddLengthDelimited(option_field->number(), serial);
7173     } else {
7174       GOOGLE_CHECK_EQ(option_field->type(), FieldDescriptor::TYPE_GROUP);
7175       UnknownFieldSet* group = unknown_fields->AddGroup(option_field->number());
7176       group->ParseFromString(serial);
7177     }
7178     return true;
7179   }
7180 }
7181 
SetInt32(int number,int32 value,FieldDescriptor::Type type,UnknownFieldSet * unknown_fields)7182 void DescriptorBuilder::OptionInterpreter::SetInt32(
7183     int number, int32 value, FieldDescriptor::Type type,
7184     UnknownFieldSet* unknown_fields) {
7185   switch (type) {
7186     case FieldDescriptor::TYPE_INT32:
7187       unknown_fields->AddVarint(number,
7188                                 static_cast<uint64>(static_cast<int64>(value)));
7189       break;
7190 
7191     case FieldDescriptor::TYPE_SFIXED32:
7192       unknown_fields->AddFixed32(number, static_cast<uint32>(value));
7193       break;
7194 
7195     case FieldDescriptor::TYPE_SINT32:
7196       unknown_fields->AddVarint(
7197           number, internal::WireFormatLite::ZigZagEncode32(value));
7198       break;
7199 
7200     default:
7201       GOOGLE_LOG(FATAL) << "Invalid wire type for CPPTYPE_INT32: " << type;
7202       break;
7203   }
7204 }
7205 
SetInt64(int number,int64 value,FieldDescriptor::Type type,UnknownFieldSet * unknown_fields)7206 void DescriptorBuilder::OptionInterpreter::SetInt64(
7207     int number, int64 value, FieldDescriptor::Type type,
7208     UnknownFieldSet* unknown_fields) {
7209   switch (type) {
7210     case FieldDescriptor::TYPE_INT64:
7211       unknown_fields->AddVarint(number, static_cast<uint64>(value));
7212       break;
7213 
7214     case FieldDescriptor::TYPE_SFIXED64:
7215       unknown_fields->AddFixed64(number, static_cast<uint64>(value));
7216       break;
7217 
7218     case FieldDescriptor::TYPE_SINT64:
7219       unknown_fields->AddVarint(
7220           number, internal::WireFormatLite::ZigZagEncode64(value));
7221       break;
7222 
7223     default:
7224       GOOGLE_LOG(FATAL) << "Invalid wire type for CPPTYPE_INT64: " << type;
7225       break;
7226   }
7227 }
7228 
SetUInt32(int number,uint32 value,FieldDescriptor::Type type,UnknownFieldSet * unknown_fields)7229 void DescriptorBuilder::OptionInterpreter::SetUInt32(
7230     int number, uint32 value, FieldDescriptor::Type type,
7231     UnknownFieldSet* unknown_fields) {
7232   switch (type) {
7233     case FieldDescriptor::TYPE_UINT32:
7234       unknown_fields->AddVarint(number, static_cast<uint64>(value));
7235       break;
7236 
7237     case FieldDescriptor::TYPE_FIXED32:
7238       unknown_fields->AddFixed32(number, static_cast<uint32>(value));
7239       break;
7240 
7241     default:
7242       GOOGLE_LOG(FATAL) << "Invalid wire type for CPPTYPE_UINT32: " << type;
7243       break;
7244   }
7245 }
7246 
SetUInt64(int number,uint64 value,FieldDescriptor::Type type,UnknownFieldSet * unknown_fields)7247 void DescriptorBuilder::OptionInterpreter::SetUInt64(
7248     int number, uint64 value, FieldDescriptor::Type type,
7249     UnknownFieldSet* unknown_fields) {
7250   switch (type) {
7251     case FieldDescriptor::TYPE_UINT64:
7252       unknown_fields->AddVarint(number, value);
7253       break;
7254 
7255     case FieldDescriptor::TYPE_FIXED64:
7256       unknown_fields->AddFixed64(number, value);
7257       break;
7258 
7259     default:
7260       GOOGLE_LOG(FATAL) << "Invalid wire type for CPPTYPE_UINT64: " << type;
7261       break;
7262   }
7263 }
7264 
LogUnusedDependency(const FileDescriptorProto & proto,const FileDescriptor * result)7265 void DescriptorBuilder::LogUnusedDependency(const FileDescriptorProto& proto,
7266                                             const FileDescriptor* result) {
7267 
7268   if (!unused_dependency_.empty()) {
7269     auto itr = pool_->unused_import_track_files_.find(proto.name());
7270     bool is_error =
7271         itr != pool_->unused_import_track_files_.end() && itr->second;
7272     for (std::set<const FileDescriptor*>::const_iterator it =
7273              unused_dependency_.begin();
7274          it != unused_dependency_.end(); ++it) {
7275       std::string error_message = "Import " + (*it)->name() + " is unused.";
7276       if (is_error) {
7277         AddError((*it)->name(), proto, DescriptorPool::ErrorCollector::IMPORT,
7278                  error_message);
7279       } else {
7280         AddWarning((*it)->name(), proto, DescriptorPool::ErrorCollector::IMPORT,
7281                    error_message);
7282       }
7283     }
7284   }
7285 }
7286 
CrossLinkOnDemandHelper(StringPiece name,bool expecting_enum) const7287 Symbol DescriptorPool::CrossLinkOnDemandHelper(StringPiece name,
7288                                                bool expecting_enum) const {
7289   auto lookup_name = std::string(name);
7290   if (!lookup_name.empty() && lookup_name[0] == '.') {
7291     lookup_name = lookup_name.substr(1);
7292   }
7293   Symbol result = tables_->FindByNameHelper(this, lookup_name);
7294   return result;
7295 }
7296 
7297 // Handle the lazy import building for a message field whose type wasn't built
7298 // at cross link time. If that was the case, we saved the name of the type to
7299 // be looked up when the accessor for the type was called. Set type_,
7300 // enum_type_, message_type_, and default_value_enum_ appropriately.
InternalTypeOnceInit() const7301 void FieldDescriptor::InternalTypeOnceInit() const {
7302   GOOGLE_CHECK(file()->finished_building_ == true);
7303   if (type_name_) {
7304     Symbol result = file()->pool()->CrossLinkOnDemandHelper(
7305         *type_name_, type_ == FieldDescriptor::TYPE_ENUM);
7306     if (result.type == Symbol::MESSAGE) {
7307       type_ = FieldDescriptor::TYPE_MESSAGE;
7308       message_type_ = result.descriptor;
7309     } else if (result.type == Symbol::ENUM) {
7310       type_ = FieldDescriptor::TYPE_ENUM;
7311       enum_type_ = result.enum_descriptor;
7312     }
7313   }
7314   if (enum_type_ && !default_value_enum_) {
7315     if (default_value_enum_name_) {
7316       // Have to build the full name now instead of at CrossLink time,
7317       // because enum_type_ may not be known at the time.
7318       std::string name = enum_type_->full_name();
7319       // Enum values reside in the same scope as the enum type.
7320       std::string::size_type last_dot = name.find_last_of('.');
7321       if (last_dot != std::string::npos) {
7322         name = name.substr(0, last_dot) + "." + *default_value_enum_name_;
7323       } else {
7324         name = *default_value_enum_name_;
7325       }
7326       Symbol result = file()->pool()->CrossLinkOnDemandHelper(name, true);
7327       if (result.type == Symbol::ENUM_VALUE) {
7328         default_value_enum_ = result.enum_value_descriptor;
7329       }
7330     }
7331     if (!default_value_enum_) {
7332       // We use the first defined value as the default
7333       // if a default is not explicitly defined.
7334       GOOGLE_CHECK(enum_type_->value_count());
7335       default_value_enum_ = enum_type_->value(0);
7336     }
7337   }
7338 }
7339 
TypeOnceInit(const FieldDescriptor * to_init)7340 void FieldDescriptor::TypeOnceInit(const FieldDescriptor* to_init) {
7341   to_init->InternalTypeOnceInit();
7342 }
7343 
7344 // message_type(), enum_type(), default_value_enum(), and type()
7345 // all share the same internal::call_once init path to do lazy
7346 // import building and cross linking of a field of a message.
message_type() const7347 const Descriptor* FieldDescriptor::message_type() const {
7348   if (type_once_) {
7349     internal::call_once(*type_once_, FieldDescriptor::TypeOnceInit, this);
7350   }
7351   return message_type_;
7352 }
7353 
enum_type() const7354 const EnumDescriptor* FieldDescriptor::enum_type() const {
7355   if (type_once_) {
7356     internal::call_once(*type_once_, FieldDescriptor::TypeOnceInit, this);
7357   }
7358   return enum_type_;
7359 }
7360 
default_value_enum() const7361 const EnumValueDescriptor* FieldDescriptor::default_value_enum() const {
7362   if (type_once_) {
7363     internal::call_once(*type_once_, FieldDescriptor::TypeOnceInit, this);
7364   }
7365   return default_value_enum_;
7366 }
7367 
PrintableNameForExtension() const7368 const std::string& FieldDescriptor::PrintableNameForExtension() const {
7369   const bool is_message_set_extension =
7370       is_extension() &&
7371       containing_type()->options().message_set_wire_format() &&
7372       type() == FieldDescriptor::TYPE_MESSAGE && is_optional() &&
7373       extension_scope() == message_type();
7374   return is_message_set_extension ? message_type()->full_name() : full_name();
7375 }
7376 
InternalDependenciesOnceInit() const7377 void FileDescriptor::InternalDependenciesOnceInit() const {
7378   GOOGLE_CHECK(finished_building_ == true);
7379   for (int i = 0; i < dependency_count(); i++) {
7380     if (dependencies_names_[i]) {
7381       dependencies_[i] = pool_->FindFileByName(*dependencies_names_[i]);
7382     }
7383   }
7384 }
7385 
DependenciesOnceInit(const FileDescriptor * to_init)7386 void FileDescriptor::DependenciesOnceInit(const FileDescriptor* to_init) {
7387   to_init->InternalDependenciesOnceInit();
7388 }
7389 
dependency(int index) const7390 const FileDescriptor* FileDescriptor::dependency(int index) const {
7391   if (dependencies_once_) {
7392     // Do once init for all indices, as it's unlikely only a single index would
7393     // be called, and saves on internal::call_once allocations.
7394     internal::call_once(*dependencies_once_,
7395                         FileDescriptor::DependenciesOnceInit, this);
7396   }
7397   return dependencies_[index];
7398 }
7399 
input_type() const7400 const Descriptor* MethodDescriptor::input_type() const {
7401   return input_type_.Get();
7402 }
7403 
output_type() const7404 const Descriptor* MethodDescriptor::output_type() const {
7405   return output_type_.Get();
7406 }
7407 
7408 
7409 namespace internal {
Set(const Descriptor * descriptor)7410 void LazyDescriptor::Set(const Descriptor* descriptor) {
7411   GOOGLE_CHECK(!name_);
7412   GOOGLE_CHECK(!once_);
7413   GOOGLE_CHECK(!file_);
7414   descriptor_ = descriptor;
7415 }
7416 
SetLazy(StringPiece name,const FileDescriptor * file)7417 void LazyDescriptor::SetLazy(StringPiece name,
7418                              const FileDescriptor* file) {
7419   // verify Init() has been called and Set hasn't been called yet.
7420   GOOGLE_CHECK(!descriptor_);
7421   GOOGLE_CHECK(!file_);
7422   GOOGLE_CHECK(!name_);
7423   GOOGLE_CHECK(!once_);
7424   GOOGLE_CHECK(file && file->pool_);
7425   GOOGLE_CHECK(file->pool_->lazily_build_dependencies_);
7426   GOOGLE_CHECK(!file->finished_building_);
7427   file_ = file;
7428   name_ = file->pool_->tables_->AllocateString(name);
7429   once_ = file->pool_->tables_->AllocateOnceDynamic();
7430 }
7431 
Once()7432 void LazyDescriptor::Once() {
7433   if (once_) {
7434     internal::call_once(*once_, LazyDescriptor::OnceStatic, this);
7435   }
7436 }
7437 
OnceStatic(LazyDescriptor * lazy)7438 void LazyDescriptor::OnceStatic(LazyDescriptor* lazy) { lazy->OnceInternal(); }
7439 
OnceInternal()7440 void LazyDescriptor::OnceInternal() {
7441   GOOGLE_CHECK(file_->finished_building_);
7442   if (!descriptor_ && name_) {
7443     Symbol result = file_->pool_->CrossLinkOnDemandHelper(*name_, false);
7444     if (!result.IsNull() && result.type == Symbol::MESSAGE) {
7445       descriptor_ = result.descriptor;
7446     }
7447   }
7448 }
7449 }  // namespace internal
7450 
7451 }  // namespace protobuf
7452 }  // namespace google
7453 
7454 #include <google/protobuf/port_undef.inc>
7455