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