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