Coverage Report

Created: 2023-11-12 09:30

/proc/self/cwd/external/com_google_protobuf/src/google/protobuf/message.cc
Line
Count
Source (jump to first uncovered line)
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/message.h"
36
37
#include <iostream>
38
#include <stack>
39
40
#include "absl/base/casts.h"
41
#include "absl/container/flat_hash_map.h"
42
#include "absl/container/flat_hash_set.h"
43
#include "absl/log/absl_check.h"
44
#include "absl/log/absl_log.h"
45
#include "absl/strings/str_join.h"
46
#include "absl/strings/string_view.h"
47
#include "absl/synchronization/mutex.h"
48
#include "google/protobuf/descriptor.h"
49
#include "google/protobuf/descriptor.pb.h"
50
#include "google/protobuf/generated_message_reflection.h"
51
#include "google/protobuf/generated_message_tctable_impl.h"
52
#include "google/protobuf/generated_message_util.h"
53
#include "google/protobuf/io/coded_stream.h"
54
#include "google/protobuf/io/zero_copy_stream_impl.h"
55
#include "google/protobuf/map_field.h"
56
#include "google/protobuf/map_field_inl.h"
57
#include "google/protobuf/parse_context.h"
58
#include "google/protobuf/reflection_internal.h"
59
#include "google/protobuf/reflection_ops.h"
60
#include "google/protobuf/unknown_field_set.h"
61
#include "google/protobuf/wire_format.h"
62
#include "google/protobuf/wire_format_lite.h"
63
64
65
// Must be included last.
66
#include "google/protobuf/port_def.inc"
67
68
namespace google {
69
namespace protobuf {
70
namespace internal {
71
72
// TODO(gerbens) make this factorized better. This should not have to hop
73
// to reflection. Currently uses GeneratedMessageReflection and thus is
74
// defined in generated_message_reflection.cc
75
void RegisterFileLevelMetadata(const DescriptorTable* descriptor_table);
76
77
}  // namespace internal
78
79
using internal::DownCast;
80
using internal::ReflectionOps;
81
using internal::WireFormat;
82
using internal::WireFormatLite;
83
84
30.2k
void Message::MergeFrom(const Message& from) {
85
30.2k
  auto* class_to = GetClassData();
86
30.2k
  auto* class_from = from.GetClassData();
87
30.2k
  auto* merge_to_from = class_to ? class_to->merge_to_from : nullptr;
88
30.2k
  if (class_to == nullptr || class_to != class_from) {
89
0
    merge_to_from = [](Message& to, const Message& from) {
90
0
      ReflectionOps::Merge(from, &to);
91
0
    };
92
0
  }
93
30.2k
  merge_to_from(*this, from);
94
30.2k
}
95
96
20.1k
void Message::CheckTypeAndMergeFrom(const MessageLite& other) {
97
20.1k
  MergeFrom(*DownCast<const Message*>(&other));
98
20.1k
}
99
100
82.2k
void Message::CopyFrom(const Message& from) {
101
82.2k
  if (&from == this) return;
102
103
82.2k
  auto* class_to = GetClassData();
104
82.2k
  auto* class_from = from.GetClassData();
105
82.2k
  auto* copy_to_from = class_to ? class_to->copy_to_from : nullptr;
106
107
82.2k
  if (class_to == nullptr || class_to != class_from) {
108
0
    const Descriptor* descriptor = GetDescriptor();
109
0
    ABSL_CHECK_EQ(from.GetDescriptor(), descriptor)
110
0
        << ": Tried to copy from a message with a different type. "
111
0
           "to: "
112
0
        << descriptor->full_name()
113
0
        << ", "
114
0
           "from: "
115
0
        << from.GetDescriptor()->full_name();
116
0
    copy_to_from = [](Message& to, const Message& from) {
117
0
      ReflectionOps::Copy(from, &to);
118
0
    };
119
0
  }
120
82.2k
  copy_to_from(*this, from);
121
82.2k
}
122
123
82.2k
void Message::CopyWithSourceCheck(Message& to, const Message& from) {
124
  // Fail if "from" is a descendant of "to" as such copy is not allowed.
125
164k
  ABSL_DCHECK(!internal::IsDescendant(to, from))
126
164k
      << "Source of CopyFrom cannot be a descendant of the target.";
127
128
82.2k
  to.Clear();
129
82.2k
  to.GetClassData()->merge_to_from(to, from);
130
82.2k
}
131
132
508k
std::string Message::GetTypeName() const {
133
508k
  return GetDescriptor()->full_name();
134
508k
}
135
136
146k
void Message::Clear() { ReflectionOps::Clear(this); }
137
138
1.79M
bool Message::IsInitialized() const {
139
1.79M
  return ReflectionOps::IsInitialized(*this);
140
1.79M
}
141
142
0
void Message::FindInitializationErrors(std::vector<std::string>* errors) const {
143
0
  return ReflectionOps::FindInitializationErrors(*this, "", errors);
144
0
}
145
146
0
std::string Message::InitializationErrorString() const {
147
0
  std::vector<std::string> errors;
148
0
  FindInitializationErrors(&errors);
149
0
  return absl::StrJoin(errors, ", ");
150
0
}
151
152
0
void Message::CheckInitialized() const {
153
0
  ABSL_CHECK(IsInitialized())
154
0
      << "Message of type \"" << GetDescriptor()->full_name()
155
0
      << "\" is missing required fields: " << InitializationErrorString();
156
0
}
157
158
0
void Message::DiscardUnknownFields() {
159
0
  return ReflectionOps::DiscardUnknownFields(this);
160
0
}
161
162
const char* Message::_InternalParse(const char* ptr,
163
1.79M
                                    internal::ParseContext* ctx) {
164
1.79M
#if defined(PROTOBUF_USE_TABLE_PARSER_ON_REFLECTION)
165
1.79M
  auto meta = GetMetadata();
166
1.79M
  ptr = internal::TcParser::ParseLoop(this, ptr, ctx,
167
1.79M
                                      meta.reflection->GetTcParseTable());
168
169
1.79M
  return ptr;
170
#else
171
  return WireFormat::_InternalParse(this, ptr, ctx);
172
#endif
173
1.79M
}
174
175
uint8_t* Message::_InternalSerialize(uint8_t* target,
176
773k
                                     io::EpsCopyOutputStream* stream) const {
177
773k
  return WireFormat::_InternalSerialize(*this, target, stream);
178
773k
}
179
180
773k
size_t Message::ByteSizeLong() const {
181
773k
  size_t size = WireFormat::ByteSize(*this);
182
773k
  SetCachedSize(internal::ToCachedSize(size));
183
773k
  return size;
184
773k
}
185
186
0
void Message::SetCachedSize(int /* size */) const {
187
0
  ABSL_LOG(FATAL) << "Message class \"" << GetDescriptor()->full_name()
188
0
                  << "\" implements neither SetCachedSize() nor ByteSize().  "
189
0
                     "Must implement one or the other.";
190
0
}
191
192
size_t Message::ComputeUnknownFieldsSize(
193
2.25k
    size_t total_size, internal::CachedSize* cached_size) const {
194
2.25k
  total_size += WireFormat::ComputeUnknownFieldsSize(
195
2.25k
      _internal_metadata_.unknown_fields<UnknownFieldSet>(
196
2.25k
          UnknownFieldSet::default_instance));
197
2.25k
  cached_size->Set(internal::ToCachedSize(total_size));
198
2.25k
  return total_size;
199
2.25k
}
200
201
size_t Message::MaybeComputeUnknownFieldsSize(
202
5.10M
    size_t total_size, internal::CachedSize* cached_size) const {
203
5.10M
  if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) {
204
2.25k
    return ComputeUnknownFieldsSize(total_size, cached_size);
205
2.25k
  }
206
5.10M
  cached_size->Set(internal::ToCachedSize(total_size));
207
5.10M
  return total_size;
208
5.10M
}
209
210
0
size_t Message::SpaceUsedLong() const {
211
0
  return GetReflection()->SpaceUsedLong(*this);
212
0
}
213
214
0
uint64_t Message::GetInvariantPerBuild(uint64_t salt) {
215
0
  return salt;
216
0
}
217
218
namespace internal {
219
void* CreateSplitMessageGeneric(Arena* arena, const void* default_split,
220
                                size_t size, const void* message,
221
0
                                const void* default_message) {
222
0
  ABSL_DCHECK_NE(message, default_message);
223
0
  void* split =
224
0
      (arena == nullptr) ? ::operator new(size) : arena->AllocateAligned(size);
225
0
  memcpy(split, default_split, size);
226
0
  return split;
227
0
}
228
}  // namespace internal
229
230
// =============================================================================
231
// MessageFactory
232
233
162k
MessageFactory::~MessageFactory() {}
234
235
namespace {
236
237
class GeneratedMessageFactory final : public MessageFactory {
238
 public:
239
  static GeneratedMessageFactory* singleton();
240
241
  void RegisterFile(const google::protobuf::internal::DescriptorTable* table);
242
  void RegisterType(const Descriptor* descriptor, const Message* prototype);
243
244
  // implements MessageFactory ---------------------------------------
245
  const Message* GetPrototype(const Descriptor* type) override;
246
247
 private:
248
  const Message* FindInTypeMap(const Descriptor* type)
249
      ABSL_SHARED_LOCKS_REQUIRED(mutex_)
250
993k
  {
251
993k
    auto it = type_map_.find(type);
252
993k
    if (it == type_map_.end()) return nullptr;
253
991k
    return it->second;
254
993k
  }
255
256
  const google::protobuf::internal::DescriptorTable* FindInFileMap(
257
588
      absl::string_view name) {
258
588
    auto it = files_.find(name);
259
588
    if (it == files_.end()) return nullptr;
260
588
    return *it;
261
588
  }
262
263
  struct DescriptorByNameHash {
264
    using is_transparent = void;
265
81.2k
    size_t operator()(const google::protobuf::internal::DescriptorTable* t) const {
266
81.2k
      return absl::HashOf(absl::string_view{t->filename});
267
81.2k
    }
268
269
588
    size_t operator()(absl::string_view name) const {
270
588
      return absl::HashOf(name);
271
588
    }
272
  };
273
  struct DescriptorByNameEq {
274
    using is_transparent = void;
275
    bool operator()(const google::protobuf::internal::DescriptorTable* lhs,
276
29.5k
                    const google::protobuf::internal::DescriptorTable* rhs) const {
277
29.5k
      return lhs == rhs || (*this)(lhs->filename, rhs->filename);
278
29.5k
    }
279
    bool operator()(absl::string_view lhs,
280
0
                    const google::protobuf::internal::DescriptorTable* rhs) const {
281
0
      return (*this)(lhs, rhs->filename);
282
0
    }
283
    bool operator()(const google::protobuf::internal::DescriptorTable* lhs,
284
618
                    absl::string_view rhs) const {
285
618
      return (*this)(lhs->filename, rhs);
286
618
    }
287
4.14k
    bool operator()(absl::string_view lhs, absl::string_view rhs) const {
288
4.14k
      return lhs == rhs;
289
4.14k
    }
290
  };
291
292
  // Only written at static init time, so does not require locking.
293
  absl::flat_hash_set<const google::protobuf::internal::DescriptorTable*,
294
                      DescriptorByNameHash, DescriptorByNameEq>
295
      files_;
296
297
  absl::Mutex mutex_;
298
  absl::flat_hash_map<const Descriptor*, const Message*> type_map_
299
      ABSL_GUARDED_BY(mutex_);
300
};
301
302
8.74M
GeneratedMessageFactory* GeneratedMessageFactory::singleton() {
303
8.74M
  static auto instance =
304
8.74M
      internal::OnShutdownDelete(new GeneratedMessageFactory);
305
8.74M
  return instance;
306
8.74M
}
307
308
void GeneratedMessageFactory::RegisterFile(
309
26.0k
    const google::protobuf::internal::DescriptorTable* table) {
310
26.0k
  if (!files_.insert(table).second) {
311
0
    ABSL_LOG(FATAL) << "File is already registered: " << table->filename;
312
0
  }
313
26.0k
}
314
315
void GeneratedMessageFactory::RegisterType(const Descriptor* descriptor,
316
4.57k
                                           const Message* prototype) {
317
4.57k
  ABSL_DCHECK_EQ(descriptor->file()->pool(), DescriptorPool::generated_pool())
318
0
      << "Tried to register a non-generated type with the generated "
319
0
         "type registry.";
320
321
  // This should only be called as a result of calling a file registration
322
  // function during GetPrototype(), in which case we already have locked
323
  // the mutex.
324
4.57k
  mutex_.AssertHeld();
325
4.57k
  if (!type_map_.try_emplace(descriptor, prototype).second) {
326
0
    ABSL_DLOG(FATAL) << "Type is already registered: "
327
0
                     << descriptor->full_name();
328
0
  }
329
4.57k
}
330
331
332
991k
const Message* GeneratedMessageFactory::GetPrototype(const Descriptor* type) {
333
991k
  {
334
991k
    absl::ReaderMutexLock lock(&mutex_);
335
991k
    const Message* result = FindInTypeMap(type);
336
991k
    if (result != nullptr) return result;
337
991k
  }
338
339
  // If the type is not in the generated pool, then we can't possibly handle
340
  // it.
341
588
  if (type->file()->pool() != DescriptorPool::generated_pool()) return nullptr;
342
343
  // Apparently the file hasn't been registered yet.  Let's do that now.
344
588
  const internal::DescriptorTable* registration_data =
345
588
      FindInFileMap(type->file()->name());
346
588
  if (registration_data == nullptr) {
347
0
    ABSL_DLOG(FATAL) << "File appears to be in generated pool but wasn't "
348
0
                        "registered: "
349
0
                     << type->file()->name();
350
0
    return nullptr;
351
0
  }
352
353
588
  absl::WriterMutexLock lock(&mutex_);
354
355
  // Check if another thread preempted us.
356
588
  const Message* result = FindInTypeMap(type);
357
588
  if (result == nullptr) {
358
    // Nope.  OK, register everything.
359
588
    internal::RegisterFileLevelMetadata(registration_data);
360
    // Should be here now.
361
588
    result = FindInTypeMap(type);
362
588
  }
363
364
588
  if (result == nullptr) {
365
0
    ABSL_DLOG(FATAL) << "Type appears to be in generated pool but wasn't "
366
0
                     << "registered: " << type->full_name();
367
0
  }
368
369
588
  return result;
370
588
}
371
372
}  // namespace
373
374
8.71M
MessageFactory* MessageFactory::generated_factory() {
375
8.71M
  return GeneratedMessageFactory::singleton();
376
8.71M
}
377
378
void MessageFactory::InternalRegisterGeneratedFile(
379
26.0k
    const google::protobuf::internal::DescriptorTable* table) {
380
26.0k
  GeneratedMessageFactory::singleton()->RegisterFile(table);
381
26.0k
}
382
383
void MessageFactory::InternalRegisterGeneratedMessage(
384
4.57k
    const Descriptor* descriptor, const Message* prototype) {
385
4.57k
  GeneratedMessageFactory::singleton()->RegisterType(descriptor, prototype);
386
4.57k
}
387
388
389
namespace {
390
template <typename T>
391
0
T* GetSingleton() {
392
0
  static T singleton;
393
0
  return &singleton;
394
0
}
Unexecuted instantiation: message.cc:google::protobuf::internal::RepeatedFieldPrimitiveAccessor<int>* google::protobuf::(anonymous namespace)::GetSingleton<google::protobuf::internal::RepeatedFieldPrimitiveAccessor<int> >()
Unexecuted instantiation: message.cc:google::protobuf::internal::RepeatedFieldPrimitiveAccessor<unsigned int>* google::protobuf::(anonymous namespace)::GetSingleton<google::protobuf::internal::RepeatedFieldPrimitiveAccessor<unsigned int> >()
Unexecuted instantiation: message.cc:google::protobuf::internal::RepeatedFieldPrimitiveAccessor<long>* google::protobuf::(anonymous namespace)::GetSingleton<google::protobuf::internal::RepeatedFieldPrimitiveAccessor<long> >()
Unexecuted instantiation: message.cc:google::protobuf::internal::RepeatedFieldPrimitiveAccessor<unsigned long>* google::protobuf::(anonymous namespace)::GetSingleton<google::protobuf::internal::RepeatedFieldPrimitiveAccessor<unsigned long> >()
Unexecuted instantiation: message.cc:google::protobuf::internal::RepeatedFieldPrimitiveAccessor<float>* google::protobuf::(anonymous namespace)::GetSingleton<google::protobuf::internal::RepeatedFieldPrimitiveAccessor<float> >()
Unexecuted instantiation: message.cc:google::protobuf::internal::RepeatedFieldPrimitiveAccessor<double>* google::protobuf::(anonymous namespace)::GetSingleton<google::protobuf::internal::RepeatedFieldPrimitiveAccessor<double> >()
Unexecuted instantiation: message.cc:google::protobuf::internal::RepeatedFieldPrimitiveAccessor<bool>* google::protobuf::(anonymous namespace)::GetSingleton<google::protobuf::internal::RepeatedFieldPrimitiveAccessor<bool> >()
Unexecuted instantiation: message.cc:google::protobuf::internal::RepeatedPtrFieldStringAccessor* google::protobuf::(anonymous namespace)::GetSingleton<google::protobuf::internal::RepeatedPtrFieldStringAccessor>()
Unexecuted instantiation: message.cc:google::protobuf::internal::MapFieldAccessor* google::protobuf::(anonymous namespace)::GetSingleton<google::protobuf::internal::MapFieldAccessor>()
Unexecuted instantiation: message.cc:google::protobuf::internal::RepeatedPtrFieldMessageAccessor* google::protobuf::(anonymous namespace)::GetSingleton<google::protobuf::internal::RepeatedPtrFieldMessageAccessor>()
395
}  // namespace
396
397
const internal::RepeatedFieldAccessor* Reflection::RepeatedFieldAccessor(
398
0
    const FieldDescriptor* field) const {
399
0
  ABSL_CHECK(field->is_repeated());
400
0
  switch (field->cpp_type()) {
401
0
#define HANDLE_PRIMITIVE_TYPE(TYPE, type) \
402
0
  case FieldDescriptor::CPPTYPE_##TYPE:   \
403
0
    return GetSingleton<internal::RepeatedFieldPrimitiveAccessor<type> >();
404
0
    HANDLE_PRIMITIVE_TYPE(INT32, int32_t)
405
0
    HANDLE_PRIMITIVE_TYPE(UINT32, uint32_t)
406
0
    HANDLE_PRIMITIVE_TYPE(INT64, int64_t)
407
0
    HANDLE_PRIMITIVE_TYPE(UINT64, uint64_t)
408
0
    HANDLE_PRIMITIVE_TYPE(FLOAT, float)
409
0
    HANDLE_PRIMITIVE_TYPE(DOUBLE, double)
410
0
    HANDLE_PRIMITIVE_TYPE(BOOL, bool)
411
0
    HANDLE_PRIMITIVE_TYPE(ENUM, int32_t)
412
0
#undef HANDLE_PRIMITIVE_TYPE
413
0
    case FieldDescriptor::CPPTYPE_STRING:
414
0
      switch (field->options().ctype()) {
415
0
        default:
416
0
        case FieldOptions::STRING:
417
0
          return GetSingleton<internal::RepeatedPtrFieldStringAccessor>();
418
0
      }
419
0
      break;
420
0
    case FieldDescriptor::CPPTYPE_MESSAGE:
421
0
      if (field->is_map()) {
422
0
        return GetSingleton<internal::MapFieldAccessor>();
423
0
      } else {
424
0
        return GetSingleton<internal::RepeatedPtrFieldMessageAccessor>();
425
0
      }
426
0
  }
427
0
  ABSL_LOG(FATAL) << "Should not reach here.";
428
0
  return nullptr;
429
0
}
430
431
namespace internal {
432
template <>
433
#if defined(_MSC_VER) && (_MSC_VER >= 1800)
434
// Note: force noinline to workaround MSVC compiler bug with /Zc:inline, issue
435
// #240
436
PROTOBUF_NOINLINE
437
#endif
438
    Message*
439
    GenericTypeHandler<Message>::NewFromPrototype(const Message* prototype,
440
0
                                                  Arena* arena) {
441
0
  return prototype->New(arena);
442
0
}
443
template <>
444
#if defined(_MSC_VER) && (_MSC_VER >= 1800)
445
// Note: force noinline to workaround MSVC compiler bug with /Zc:inline, issue
446
// #240
447
PROTOBUF_NOINLINE
448
#endif
449
    Arena*
450
0
    GenericTypeHandler<Message>::GetOwningArena(Message* value) {
451
0
  return value->GetOwningArena();
452
0
}
453
454
template void InternalMetadata::DoClear<UnknownFieldSet>();
455
template void InternalMetadata::DoMergeFrom<UnknownFieldSet>(
456
    const UnknownFieldSet& other);
457
template void InternalMetadata::DoSwap<UnknownFieldSet>(UnknownFieldSet* other);
458
template Arena* InternalMetadata::DeleteOutOfLineHelper<UnknownFieldSet>();
459
template UnknownFieldSet*
460
InternalMetadata::mutable_unknown_fields_slow<UnknownFieldSet>();
461
462
}  // namespace internal
463
464
}  // namespace protobuf
465
}  // namespace google
466
467
#include "google/protobuf/port_undef.inc"