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