Coverage Report

Created: 2023-06-07 07:09

/src/LPM/external.protobuf/include/google/protobuf/parse_context.h
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
#ifndef GOOGLE_PROTOBUF_PARSE_CONTEXT_H__
32
#define GOOGLE_PROTOBUF_PARSE_CONTEXT_H__
33
34
#include <cstdint>
35
#include <cstring>
36
#include <string>
37
#include <type_traits>
38
39
#include "absl/log/absl_check.h"
40
#include "absl/log/absl_log.h"
41
#include "absl/strings/cord.h"
42
#include "absl/strings/internal/resize_uninitialized.h"
43
#include "absl/strings/string_view.h"
44
#include "google/protobuf/arena.h"
45
#include "google/protobuf/arenastring.h"
46
#include "google/protobuf/endian.h"
47
#include "google/protobuf/implicit_weak_message.h"
48
#include "google/protobuf/inlined_string_field.h"
49
#include "google/protobuf/io/coded_stream.h"
50
#include "google/protobuf/io/zero_copy_stream.h"
51
#include "google/protobuf/metadata_lite.h"
52
#include "google/protobuf/port.h"
53
#include "google/protobuf/repeated_field.h"
54
#include "google/protobuf/wire_format_lite.h"
55
56
57
// Must be included last.
58
#include "google/protobuf/port_def.inc"
59
60
61
namespace google {
62
namespace protobuf {
63
64
class UnknownFieldSet;
65
class DescriptorPool;
66
class MessageFactory;
67
68
namespace internal {
69
70
// Template code below needs to know about the existence of these functions.
71
PROTOBUF_EXPORT void WriteVarint(uint32_t num, uint64_t val, std::string* s);
72
PROTOBUF_EXPORT void WriteLengthDelimited(uint32_t num, absl::string_view val,
73
                                          std::string* s);
74
// Inline because it is just forwarding to s->WriteVarint
75
inline void WriteVarint(uint32_t num, uint64_t val, UnknownFieldSet* s);
76
inline void WriteLengthDelimited(uint32_t num, absl::string_view val,
77
                                 UnknownFieldSet* s);
78
79
80
// The basic abstraction the parser is designed for is a slight modification
81
// of the ZeroCopyInputStream (ZCIS) abstraction. A ZCIS presents a serialized
82
// stream as a series of buffers that concatenate to the full stream.
83
// Pictorially a ZCIS presents a stream in chunks like so
84
// [---------------------------------------------------------------]
85
// [---------------------] chunk 1
86
//                      [----------------------------] chunk 2
87
//                                          chunk 3 [--------------]
88
//
89
// Where the '-' represent the bytes which are vertically lined up with the
90
// bytes of the stream. The proto parser requires its input to be presented
91
// similarly with the extra
92
// property that each chunk has kSlopBytes past its end that overlaps with the
93
// first kSlopBytes of the next chunk, or if there is no next chunk at least its
94
// still valid to read those bytes. Again, pictorially, we now have
95
//
96
// [---------------------------------------------------------------]
97
// [-------------------....] chunk 1
98
//                    [------------------------....] chunk 2
99
//                                    chunk 3 [------------------..**]
100
//                                                      chunk 4 [--****]
101
// Here '-' mean the bytes of the stream or chunk and '.' means bytes past the
102
// chunk that match up with the start of the next chunk. Above each chunk has
103
// 4 '.' after the chunk. In the case these 'overflow' bytes represents bytes
104
// past the stream, indicated by '*' above, their values are unspecified. It is
105
// still legal to read them (ie. should not segfault). Reading past the
106
// end should be detected by the user and indicated as an error.
107
//
108
// The reason for this, admittedly, unconventional invariant is to ruthlessly
109
// optimize the protobuf parser. Having an overlap helps in two important ways.
110
// Firstly it alleviates having to performing bounds checks if a piece of code
111
// is guaranteed to not read more than kSlopBytes. Secondly, and more
112
// importantly, the protobuf wireformat is such that reading a key/value pair is
113
// always less than 16 bytes. This removes the need to change to next buffer in
114
// the middle of reading primitive values. Hence there is no need to store and
115
// load the current position.
116
117
class PROTOBUF_EXPORT EpsCopyInputStream {
118
 public:
119
  enum { kMaxCordBytesToCopy = 512 };
120
  explicit EpsCopyInputStream(bool enable_aliasing)
121
0
      : aliasing_(enable_aliasing ? kOnPatch : kNoAliasing) {}
122
123
0
  void BackUp(const char* ptr) {
124
0
    ABSL_DCHECK(ptr <= buffer_end_ + kSlopBytes);
125
0
    int count;
126
0
    if (next_chunk_ == patch_buffer_) {
127
0
      count = static_cast<int>(buffer_end_ + kSlopBytes - ptr);
128
0
    } else {
129
0
      count = size_ + static_cast<int>(buffer_end_ - ptr);
130
0
    }
131
0
    if (count > 0) StreamBackUp(count);
132
0
  }
133
134
  // If return value is negative it's an error
135
0
  PROTOBUF_NODISCARD int PushLimit(const char* ptr, int limit) {
136
0
    ABSL_DCHECK(limit >= 0 && limit <= INT_MAX - kSlopBytes);
137
0
    // This add is safe due to the invariant above, because
138
0
    // ptr - buffer_end_ <= kSlopBytes.
139
0
    limit += static_cast<int>(ptr - buffer_end_);
140
0
    limit_end_ = buffer_end_ + (std::min)(0, limit);
141
0
    auto old_limit = limit_;
142
0
    limit_ = limit;
143
0
    return old_limit - limit;
144
0
  }
145
146
0
  PROTOBUF_NODISCARD bool PopLimit(int delta) {
147
0
    if (PROTOBUF_PREDICT_FALSE(!EndedAtLimit())) return false;
148
0
    limit_ = limit_ + delta;
149
0
    // TODO(gerbens) We could remove this line and hoist the code to
150
0
    // DoneFallback. Study the perf/bin-size effects.
151
0
    limit_end_ = buffer_end_ + (std::min)(0, limit_);
152
0
    return true;
153
0
  }
154
155
0
  PROTOBUF_NODISCARD const char* Skip(const char* ptr, int size) {
156
0
    if (size <= buffer_end_ + kSlopBytes - ptr) {
157
0
      return ptr + size;
158
0
    }
159
0
    return SkipFallback(ptr, size);
160
0
  }
161
  PROTOBUF_NODISCARD const char* ReadString(const char* ptr, int size,
162
0
                                            std::string* s) {
163
0
    if (size <= buffer_end_ + kSlopBytes - ptr) {
164
0
      // Fundamentally we just want to do assign to the string.
165
0
      // However micro-benchmarks regress on string reading cases. So we copy
166
0
      // the same logic from the old CodedInputStream ReadString. Note: as of
167
0
      // Apr 2021, this is still a significant win over `assign()`.
168
0
      absl::strings_internal::STLStringResizeUninitialized(s, size);
169
0
      char* z = &(*s)[0];
170
0
      memcpy(z, ptr, size);
171
0
      return ptr + size;
172
0
    }
173
0
    return ReadStringFallback(ptr, size, s);
174
0
  }
175
  PROTOBUF_NODISCARD const char* AppendString(const char* ptr, int size,
176
0
                                              std::string* s) {
177
0
    if (size <= buffer_end_ + kSlopBytes - ptr) {
178
0
      s->append(ptr, size);
179
0
      return ptr + size;
180
0
    }
181
0
    return AppendStringFallback(ptr, size, s);
182
0
  }
183
  // Implemented in arenastring.cc
184
  PROTOBUF_NODISCARD const char* ReadArenaString(const char* ptr,
185
                                                 ArenaStringPtr* s,
186
                                                 Arena* arena);
187
188
  PROTOBUF_NODISCARD const char* ReadCord(const char* ptr, int size,
189
0
                                          ::absl::Cord* cord) {
190
0
    if (size <= std::min<int>(static_cast<int>(buffer_end_ + kSlopBytes - ptr),
191
0
                              kMaxCordBytesToCopy)) {
192
0
      *cord = absl::string_view(ptr, size);
193
0
      return ptr + size;
194
0
    }
195
0
    return ReadCordFallback(ptr, size, cord);
196
0
  }
197
198
199
  template <typename Tag, typename T>
200
  PROTOBUF_NODISCARD const char* ReadRepeatedFixed(const char* ptr,
201
                                                   Tag expected_tag,
202
                                                   RepeatedField<T>* out);
203
204
  template <typename T>
205
  PROTOBUF_NODISCARD const char* ReadPackedFixed(const char* ptr, int size,
206
                                                 RepeatedField<T>* out);
207
  template <typename Add>
208
  PROTOBUF_NODISCARD const char* ReadPackedVarint(const char* ptr, Add add);
209
210
0
  uint32_t LastTag() const { return last_tag_minus_1_ + 1; }
211
0
  bool ConsumeEndGroup(uint32_t start_tag) {
212
0
    bool res = last_tag_minus_1_ == start_tag;
213
0
    last_tag_minus_1_ = 0;
214
0
    return res;
215
0
  }
216
0
  bool EndedAtLimit() const { return last_tag_minus_1_ == 0; }
217
0
  bool EndedAtEndOfStream() const { return last_tag_minus_1_ == 1; }
218
0
  void SetLastTag(uint32_t tag) { last_tag_minus_1_ = tag - 1; }
219
0
  void SetEndOfStream() { last_tag_minus_1_ = 1; }
220
0
  bool IsExceedingLimit(const char* ptr) {
221
0
    return ptr > limit_end_ &&
222
0
           (next_chunk_ == nullptr || ptr - buffer_end_ > limit_);
223
0
  }
224
0
  bool AliasingEnabled() const { return aliasing_ != kNoAliasing; }
225
0
  int BytesUntilLimit(const char* ptr) const {
226
0
    return limit_ + static_cast<int>(buffer_end_ - ptr);
227
0
  }
228
  // Maximum number of sequential bytes that can be read starting from `ptr`.
229
0
  int MaximumReadSize(const char* ptr) const {
230
0
    return static_cast<int>(limit_end_ - ptr) + kSlopBytes;
231
0
  }
232
  // Returns true if more data is available, if false is returned one has to
233
  // call Done for further checks.
234
0
  bool DataAvailable(const char* ptr) { return ptr < limit_end_; }
235
236
 protected:
237
  // Returns true is limit (either an explicit limit or end of stream) is
238
  // reached. It aligns *ptr across buffer seams.
239
  // If limit is exceeded it returns true and ptr is set to null.
240
0
  bool DoneWithCheck(const char** ptr, int d) {
241
0
    ABSL_DCHECK(*ptr);
242
0
    if (PROTOBUF_PREDICT_TRUE(*ptr < limit_end_)) return false;
243
0
    int overrun = static_cast<int>(*ptr - buffer_end_);
244
0
    ABSL_DCHECK_LE(overrun, kSlopBytes);  // Guaranteed by parse loop.
245
0
    if (overrun ==
246
0
        limit_) {  //  No need to flip buffers if we ended on a limit.
247
      // If we actually overrun the buffer and next_chunk_ is null. It means
248
      // the stream ended and we passed the stream end.
249
0
      if (overrun > 0 && next_chunk_ == nullptr) *ptr = nullptr;
250
0
      return true;
251
0
    }
252
0
    auto res = DoneFallback(overrun, d);
253
0
    *ptr = res.first;
254
0
    return res.second;
255
0
  }
256
257
0
  const char* InitFrom(absl::string_view flat) {
258
0
    overall_limit_ = 0;
259
0
    if (flat.size() > kSlopBytes) {
260
0
      limit_ = kSlopBytes;
261
0
      limit_end_ = buffer_end_ = flat.data() + flat.size() - kSlopBytes;
262
0
      next_chunk_ = patch_buffer_;
263
0
      if (aliasing_ == kOnPatch) aliasing_ = kNoDelta;
264
0
      return flat.data();
265
0
    } else {
266
0
      if (!flat.empty()) {
267
0
        std::memcpy(patch_buffer_, flat.data(), flat.size());
268
0
      }
269
0
      limit_ = 0;
270
0
      limit_end_ = buffer_end_ = patch_buffer_ + flat.size();
271
0
      next_chunk_ = nullptr;
272
0
      if (aliasing_ == kOnPatch) {
273
0
        aliasing_ = reinterpret_cast<std::uintptr_t>(flat.data()) -
274
0
                    reinterpret_cast<std::uintptr_t>(patch_buffer_);
275
0
      }
276
0
      return patch_buffer_;
277
0
    }
278
0
  }
279
280
  const char* InitFrom(io::ZeroCopyInputStream* zcis);
281
282
0
  const char* InitFrom(io::ZeroCopyInputStream* zcis, int limit) {
283
0
    if (limit == -1) return InitFrom(zcis);
284
0
    overall_limit_ = limit;
285
0
    auto res = InitFrom(zcis);
286
0
    limit_ = limit - static_cast<int>(buffer_end_ - res);
287
0
    limit_end_ = buffer_end_ + (std::min)(0, limit_);
288
0
    return res;
289
0
  }
290
291
 private:
292
  enum { kSlopBytes = 16, kPatchBufferSize = 32 };
293
  static_assert(kPatchBufferSize >= kSlopBytes * 2,
294
                "Patch buffer needs to be at least large enough to hold all "
295
                "the slop bytes from the previous buffer, plus the first "
296
                "kSlopBytes from the next buffer.");
297
298
  const char* limit_end_;  // buffer_end_ + min(limit_, 0)
299
  const char* buffer_end_;
300
  const char* next_chunk_;
301
  int size_;
302
  int limit_;  // relative to buffer_end_;
303
  io::ZeroCopyInputStream* zcis_ = nullptr;
304
  char patch_buffer_[kPatchBufferSize] = {};
305
  enum { kNoAliasing = 0, kOnPatch = 1, kNoDelta = 2 };
306
  std::uintptr_t aliasing_ = kNoAliasing;
307
  // This variable is used to communicate how the parse ended, in order to
308
  // completely verify the parsed data. A wire-format parse can end because of
309
  // one of the following conditions:
310
  // 1) A parse can end on a pushed limit.
311
  // 2) A parse can end on End Of Stream (EOS).
312
  // 3) A parse can end on 0 tag (only valid for toplevel message).
313
  // 4) A parse can end on an end-group tag.
314
  // This variable should always be set to 0, which indicates case 1. If the
315
  // parse terminated due to EOS (case 2), it's set to 1. In case the parse
316
  // ended due to a terminating tag (case 3 and 4) it's set to (tag - 1).
317
  // This var doesn't really belong in EpsCopyInputStream and should be part of
318
  // the ParseContext, but case 2 is most easily and optimally implemented in
319
  // DoneFallback.
320
  uint32_t last_tag_minus_1_ = 0;
321
  int overall_limit_ = INT_MAX;  // Overall limit independent of pushed limits.
322
  // Pretty random large number that seems like a safe allocation on most
323
  // systems. TODO(gerbens) do we need to set this as build flag?
324
  enum { kSafeStringSize = 50000000 };
325
326
  // Advances to next buffer chunk returns a pointer to the same logical place
327
  // in the stream as set by overrun. Overrun indicates the position in the slop
328
  // region the parse was left (0 <= overrun <= kSlopBytes). Returns true if at
329
  // limit, at which point the returned pointer maybe null if there was an
330
  // error. The invariant of this function is that it's guaranteed that
331
  // kSlopBytes bytes can be accessed from the returned ptr. This function might
332
  // advance more buffers than one in the underlying ZeroCopyInputStream.
333
  std::pair<const char*, bool> DoneFallback(int overrun, int depth);
334
  // Advances to the next buffer, at most one call to Next() on the underlying
335
  // ZeroCopyInputStream is made. This function DOES NOT match the returned
336
  // pointer to where in the slop region the parse ends, hence no overrun
337
  // parameter. This is useful for string operations where you always copy
338
  // to the end of the buffer (including the slop region).
339
  const char* Next();
340
  // overrun is the location in the slop region the stream currently is
341
  // (0 <= overrun <= kSlopBytes). To prevent flipping to the next buffer of
342
  // the ZeroCopyInputStream in the case the parse will end in the last
343
  // kSlopBytes of the current buffer. depth is the current depth of nested
344
  // groups (or negative if the use case does not need careful tracking).
345
  inline const char* NextBuffer(int overrun, int depth);
346
  const char* SkipFallback(const char* ptr, int size);
347
  const char* AppendStringFallback(const char* ptr, int size, std::string* str);
348
  const char* ReadStringFallback(const char* ptr, int size, std::string* str);
349
  const char* ReadCordFallback(const char* ptr, int size, absl::Cord* cord);
350
  static bool ParseEndsInSlopRegion(const char* begin, int overrun, int depth);
351
0
  bool StreamNext(const void** data) {
352
0
    bool res = zcis_->Next(data, &size_);
353
0
    if (res) overall_limit_ -= size_;
354
0
    return res;
355
0
  }
356
0
  void StreamBackUp(int count) {
357
0
    zcis_->BackUp(count);
358
0
    overall_limit_ += count;
359
0
  }
360
361
  template <typename A>
362
  const char* AppendSize(const char* ptr, int size, const A& append) {
363
    int chunk_size = static_cast<int>(buffer_end_ + kSlopBytes - ptr);
364
    do {
365
      ABSL_DCHECK(size > chunk_size);
366
      if (next_chunk_ == nullptr) return nullptr;
367
      append(ptr, chunk_size);
368
      ptr += chunk_size;
369
      size -= chunk_size;
370
      // TODO(gerbens) Next calls NextBuffer which generates buffers with
371
      // overlap and thus incurs cost of copying the slop regions. This is not
372
      // necessary for reading strings. We should just call Next buffers.
373
      if (limit_ <= kSlopBytes) return nullptr;
374
      ptr = Next();
375
      if (ptr == nullptr) return nullptr;  // passed the limit
376
      ptr += kSlopBytes;
377
      chunk_size = static_cast<int>(buffer_end_ + kSlopBytes - ptr);
378
    } while (size > chunk_size);
379
    append(ptr, size);
380
    return ptr + size;
381
  }
382
383
  // AppendUntilEnd appends data until a limit (either a PushLimit or end of
384
  // stream. Normal payloads are from length delimited fields which have an
385
  // explicit size. Reading until limit only comes when the string takes
386
  // the place of a protobuf, ie RawMessage/StringRawMessage, lazy fields and
387
  // implicit weak messages. We keep these methods private and friend them.
388
  template <typename A>
389
0
  const char* AppendUntilEnd(const char* ptr, const A& append) {
390
0
    if (ptr - buffer_end_ > limit_) return nullptr;
391
0
    while (limit_ > kSlopBytes) {
392
0
      size_t chunk_size = buffer_end_ + kSlopBytes - ptr;
393
0
      append(ptr, chunk_size);
394
0
      ptr = Next();
395
0
      if (ptr == nullptr) return limit_end_;
396
0
      ptr += kSlopBytes;
397
0
    }
398
0
    auto end = buffer_end_ + limit_;
399
0
    ABSL_DCHECK(end >= ptr);
400
0
    append(ptr, end - ptr);
401
0
    return end;
402
0
  }
403
404
  PROTOBUF_NODISCARD const char* AppendString(const char* ptr,
405
0
                                              std::string* str) {
406
0
    return AppendUntilEnd(
407
0
        ptr, [str](const char* p, ptrdiff_t s) { str->append(p, s); });
408
0
  }
409
  friend class ImplicitWeakMessage;
410
411
  // Needs access to kSlopBytes.
412
  friend PROTOBUF_EXPORT std::pair<const char*, int32_t> ReadSizeFallback(
413
      const char* p, uint32_t res);
414
};
415
416
using LazyEagerVerifyFnType = const char* (*)(const char* ptr,
417
                                              ParseContext* ctx);
418
using LazyEagerVerifyFnRef = std::remove_pointer<LazyEagerVerifyFnType>::type&;
419
420
// ParseContext holds all data that is global to the entire parse. Most
421
// importantly it contains the input stream, but also recursion depth and also
422
// stores the end group tag, in case a parser ended on a endgroup, to verify
423
// matching start/end group tags.
424
class PROTOBUF_EXPORT ParseContext : public EpsCopyInputStream {
425
 public:
426
  struct Data {
427
    const DescriptorPool* pool = nullptr;
428
    MessageFactory* factory = nullptr;
429
  };
430
431
  template <typename... T>
432
  ParseContext(int depth, bool aliasing, const char** start, T&&... args)
433
      : EpsCopyInputStream(aliasing), depth_(depth) {
434
    *start = InitFrom(std::forward<T>(args)...);
435
  }
436
437
0
  void TrackCorrectEnding() { group_depth_ = 0; }
438
439
  // Done should only be called when the parsing pointer is pointing to the
440
  // beginning of field data - that is, at a tag.  Or if it is NULL.
441
0
  bool Done(const char** ptr) { return DoneWithCheck(ptr, group_depth_); }
442
443
0
  int depth() const { return depth_; }
444
445
0
  Data& data() { return data_; }
446
0
  const Data& data() const { return data_; }
447
448
  const char* ParseMessage(MessageLite* msg, const char* ptr);
449
450
  // Spawns a child parsing context that inherits key properties. New context
451
  // inherits the following:
452
  // --depth_, data_, check_required_fields_, lazy_parse_mode_
453
  // The spawned context always disables aliasing (different input).
454
  template <typename... T>
455
  ParseContext Spawn(const char** start, T&&... args) {
456
    ParseContext spawned(depth_, false, start, std::forward<T>(args)...);
457
    // Transfer key context states.
458
    spawned.data_ = data_;
459
    return spawned;
460
  }
461
462
  // This overload supports those few cases where ParseMessage is called
463
  // on a class that is not actually a proto message.
464
  // TODO(jorg): Eliminate this use case.
465
  template <typename T,
466
            typename std::enable_if<!std::is_base_of<MessageLite, T>::value,
467
                                    bool>::type = true>
468
  PROTOBUF_NODISCARD const char* ParseMessage(T* msg, const char* ptr);
469
470
  template <typename TcParser, typename Table>
471
  PROTOBUF_NODISCARD PROTOBUF_ALWAYS_INLINE const char* ParseMessage(
472
      MessageLite* msg, const char* ptr, const Table* table) {
473
    int old;
474
    ptr = ReadSizeAndPushLimitAndDepthInlined(ptr, &old);
475
    auto old_depth = depth_;
476
    ptr = ptr ? TcParser::ParseLoop(msg, ptr, this, table) : nullptr;
477
    if (ptr != nullptr) ABSL_DCHECK_EQ(old_depth, depth_);
478
    depth_++;
479
    if (!PopLimit(old)) return nullptr;
480
    return ptr;
481
  }
482
483
  template <typename T>
484
  PROTOBUF_NODISCARD PROTOBUF_NDEBUG_INLINE const char* ParseGroup(
485
      T* msg, const char* ptr, uint32_t tag) {
486
    if (--depth_ < 0) return nullptr;
487
    group_depth_++;
488
    auto old_depth = depth_;
489
    auto old_group_depth = group_depth_;
490
    ptr = msg->_InternalParse(ptr, this);
491
    if (ptr != nullptr) {
492
      ABSL_DCHECK_EQ(old_depth, depth_);
493
      ABSL_DCHECK_EQ(old_group_depth, group_depth_);
494
    }
495
    group_depth_--;
496
    depth_++;
497
    if (PROTOBUF_PREDICT_FALSE(!ConsumeEndGroup(tag))) return nullptr;
498
    return ptr;
499
  }
500
501
  template <typename TcParser, typename Table>
502
  PROTOBUF_NODISCARD PROTOBUF_ALWAYS_INLINE const char* ParseGroup(
503
      MessageLite* msg, const char* ptr, uint32_t tag, const Table* table) {
504
    if (--depth_ < 0) return nullptr;
505
    group_depth_++;
506
    auto old_depth = depth_;
507
    auto old_group_depth = group_depth_;
508
    ptr = TcParser::ParseLoop(msg, ptr, this, table);
509
    if (ptr != nullptr) {
510
      ABSL_DCHECK_EQ(old_depth, depth_);
511
      ABSL_DCHECK_EQ(old_group_depth, group_depth_);
512
    }
513
    group_depth_--;
514
    depth_++;
515
    if (PROTOBUF_PREDICT_FALSE(!ConsumeEndGroup(tag))) return nullptr;
516
    return ptr;
517
  }
518
519
 private:
520
  // Out-of-line routine to save space in ParseContext::ParseMessage<T>
521
  //   int old;
522
  //   ptr = ReadSizeAndPushLimitAndDepth(ptr, &old)
523
  // is equivalent to:
524
  //   int size = ReadSize(&ptr);
525
  //   if (!ptr) return nullptr;
526
  //   int old = PushLimit(ptr, size);
527
  //   if (--depth_ < 0) return nullptr;
528
  PROTOBUF_NODISCARD const char* ReadSizeAndPushLimitAndDepth(const char* ptr,
529
                                                              int* old_limit);
530
531
  // As above, but fully inlined for the cases where we care about performance
532
  // more than size. eg TcParser.
533
  PROTOBUF_NODISCARD PROTOBUF_ALWAYS_INLINE const char*
534
  ReadSizeAndPushLimitAndDepthInlined(const char* ptr, int* old_limit);
535
536
  // The context keeps an internal stack to keep track of the recursive
537
  // part of the parse state.
538
  // Current depth of the active parser, depth counts down.
539
  // This is used to limit recursion depth (to prevent overflow on malicious
540
  // data), but is also used to index in stack_ to store the current state.
541
  int depth_;
542
  // Unfortunately necessary for the fringe case of ending on 0 or end-group tag
543
  // in the last kSlopBytes of a ZeroCopyInputStream chunk.
544
  int group_depth_ = INT_MIN;
545
  Data data_;
546
};
547
548
template <uint32_t tag>
549
0
bool ExpectTag(const char* ptr) {
550
0
  if (tag < 128) {
551
0
    return *ptr == static_cast<char>(tag);
552
0
  } else {
553
0
    static_assert(tag < 128 * 128, "We only expect tags for 1 or 2 bytes");
554
0
    char buf[2] = {static_cast<char>(tag | 0x80), static_cast<char>(tag >> 7)};
555
0
    return std::memcmp(ptr, buf, 2) == 0;
556
0
  }
557
0
}
558
559
template <int>
560
struct EndianHelper;
561
562
template <>
563
struct EndianHelper<1> {
564
0
  static uint8_t Load(const void* p) { return *static_cast<const uint8_t*>(p); }
565
};
566
567
template <>
568
struct EndianHelper<2> {
569
0
  static uint16_t Load(const void* p) {
570
0
    uint16_t tmp;
571
0
    std::memcpy(&tmp, p, 2);
572
0
    return little_endian::ToHost(tmp);
573
0
  }
574
};
575
576
template <>
577
struct EndianHelper<4> {
578
0
  static uint32_t Load(const void* p) {
579
0
    uint32_t tmp;
580
0
    std::memcpy(&tmp, p, 4);
581
0
    return little_endian::ToHost(tmp);
582
0
  }
583
};
584
585
template <>
586
struct EndianHelper<8> {
587
0
  static uint64_t Load(const void* p) {
588
0
    uint64_t tmp;
589
0
    std::memcpy(&tmp, p, 8);
590
0
    return little_endian::ToHost(tmp);
591
0
  }
592
};
593
594
template <typename T>
595
0
T UnalignedLoad(const char* p) {
596
0
  auto tmp = EndianHelper<sizeof(T)>::Load(p);
597
0
  T res;
598
0
  memcpy(&res, &tmp, sizeof(T));
599
0
  return res;
600
0
}
Unexecuted instantiation: unsigned short google::protobuf::internal::UnalignedLoad<unsigned short>(char const*)
Unexecuted instantiation: float google::protobuf::internal::UnalignedLoad<float>(char const*)
Unexecuted instantiation: double google::protobuf::internal::UnalignedLoad<double>(char const*)
Unexecuted instantiation: unsigned long google::protobuf::internal::UnalignedLoad<unsigned long>(char const*)
Unexecuted instantiation: unsigned int google::protobuf::internal::UnalignedLoad<unsigned int>(char const*)
Unexecuted instantiation: long google::protobuf::internal::UnalignedLoad<long>(char const*)
Unexecuted instantiation: int google::protobuf::internal::UnalignedLoad<int>(char const*)
601
602
PROTOBUF_EXPORT
603
std::pair<const char*, uint32_t> VarintParseSlow32(const char* p, uint32_t res);
604
PROTOBUF_EXPORT
605
std::pair<const char*, uint64_t> VarintParseSlow64(const char* p, uint32_t res);
606
607
0
inline const char* VarintParseSlow(const char* p, uint32_t res, uint32_t* out) {
608
0
  auto tmp = VarintParseSlow32(p, res);
609
0
  *out = tmp.second;
610
0
  return tmp.first;
611
0
}
612
613
0
inline const char* VarintParseSlow(const char* p, uint32_t res, uint64_t* out) {
614
0
  auto tmp = VarintParseSlow64(p, res);
615
0
  *out = tmp.second;
616
0
  return tmp.first;
617
0
}
618
619
#ifdef __aarch64__
620
PROTOBUF_EXPORT
621
const char* VarintParseSlowArm64(const char* p, uint64_t* out, uint64_t first8);
622
PROTOBUF_EXPORT
623
const char* VarintParseSlowArm32(const char* p, uint32_t* out, uint64_t first8);
624
625
inline const char* VarintParseSlowArm(const char* p, uint32_t* out,
626
                                      uint64_t first8) {
627
  return VarintParseSlowArm32(p, out, first8);
628
}
629
630
inline const char* VarintParseSlowArm(const char* p, uint64_t* out,
631
                                      uint64_t first8) {
632
  return VarintParseSlowArm64(p, out, first8);
633
}
634
635
// Falsely indicate that the specific value is modified at this location.  This
636
// prevents code which depends on this value from being scheduled earlier.
637
template <typename V1Type>
638
PROTOBUF_ALWAYS_INLINE inline V1Type ValueBarrier(V1Type value1) {
639
  asm("" : "+r"(value1));
640
  return value1;
641
}
642
643
template <typename V1Type, typename V2Type>
644
PROTOBUF_ALWAYS_INLINE inline V1Type ValueBarrier(V1Type value1,
645
                                                  V2Type value2) {
646
  asm("" : "+r"(value1) : "r"(value2));
647
  return value1;
648
}
649
650
// Performs a 7 bit UBFX (Unsigned Bit Extract) starting at the indicated bit.
651
static PROTOBUF_ALWAYS_INLINE inline uint64_t Ubfx7(uint64_t data,
652
                                                    uint64_t start) {
653
  return ValueBarrier((data >> start) & 0x7f);
654
}
655
656
#endif  // __aarch64__
657
658
template <typename T>
659
0
PROTOBUF_NODISCARD const char* VarintParse(const char* p, T* out) {
660
#if defined(__aarch64__) && defined(PROTOBUF_LITTLE_ENDIAN)
661
  // This optimization is not supported in big endian mode
662
  uint64_t first8;
663
  std::memcpy(&first8, p, sizeof(first8));
664
  if (PROTOBUF_PREDICT_TRUE((first8 & 0x80) == 0)) {
665
    *out = static_cast<uint8_t>(first8);
666
    return p + 1;
667
  }
668
  if (PROTOBUF_PREDICT_TRUE((first8 & 0x8000) == 0)) {
669
    uint64_t chunk1;
670
    uint64_t chunk2;
671
    // Extracting the two chunks this way gives a speedup for this path.
672
    chunk1 = Ubfx7(first8, 0);
673
    chunk2 = Ubfx7(first8, 8);
674
    *out = chunk1 | (chunk2 << 7);
675
    return p + 2;
676
  }
677
  return VarintParseSlowArm(p, out, first8);
678
#else   // __aarch64__
679
0
  auto ptr = reinterpret_cast<const uint8_t*>(p);
680
0
  uint32_t res = ptr[0];
681
0
  if ((res & 0x80) == 0) {
682
0
    *out = res;
683
0
    return p + 1;
684
0
  }
685
0
  return VarintParseSlow(p, res, out);
686
0
#endif  // __aarch64__
687
0
}
Unexecuted instantiation: char const* google::protobuf::internal::VarintParse<unsigned long>(char const*, unsigned long*)
Unexecuted instantiation: char const* google::protobuf::internal::VarintParse<unsigned int>(char const*, unsigned int*)
688
689
// Used for tags, could read up to 5 bytes which must be available.
690
// Caller must ensure its safe to call.
691
692
PROTOBUF_EXPORT
693
std::pair<const char*, uint32_t> ReadTagFallback(const char* p, uint32_t res);
694
695
// Same as ParseVarint but only accept 5 bytes at most.
696
inline const char* ReadTag(const char* p, uint32_t* out,
697
0
                           uint32_t /*max_tag*/ = 0) {
698
0
  uint32_t res = static_cast<uint8_t>(p[0]);
699
0
  if (res < 128) {
700
0
    *out = res;
701
0
    return p + 1;
702
0
  }
703
0
  uint32_t second = static_cast<uint8_t>(p[1]);
704
0
  res += (second - 1) << 7;
705
0
  if (second < 128) {
706
0
    *out = res;
707
0
    return p + 2;
708
0
  }
709
0
  auto tmp = ReadTagFallback(p, res);
710
0
  *out = tmp.second;
711
0
  return tmp.first;
712
0
}
713
714
// As above, but optimized to consume very few registers while still being fast,
715
// ReadTagInlined is useful for callers that don't mind the extra code but would
716
// like to avoid an extern function call causing spills into the stack.
717
//
718
// Two support routines for ReadTagInlined come first...
719
template <class T>
720
PROTOBUF_NODISCARD PROTOBUF_ALWAYS_INLINE constexpr T RotateLeft(
721
0
    T x, int s) noexcept {
722
0
  return static_cast<T>(x << (s & (std::numeric_limits<T>::digits - 1))) |
723
0
         static_cast<T>(x >> ((-s) & (std::numeric_limits<T>::digits - 1)));
724
0
}
725
726
PROTOBUF_NODISCARD inline PROTOBUF_ALWAYS_INLINE uint64_t
727
0
RotRight7AndReplaceLowByte(uint64_t res, const char& byte) {
728
0
  // TODO(b/239808098): remove the inline assembly
729
0
#if defined(__x86_64__) && defined(__GNUC__)
730
0
  // This will only use one register for `res`.
731
0
  // `byte` comes as a reference to allow the compiler to generate code like:
732
0
  //
733
0
  //   rorq    $7, %rcx
734
0
  //   movb    1(%rax), %cl
735
0
  //
736
0
  // which avoids loading the incoming bytes into a separate register first.
737
0
  asm("ror $7,%0\n\t"
738
0
      "movb %1,%b0"
739
0
      : "+r"(res)
740
0
      : "m"(byte));
741
0
#else
742
0
  res = RotateLeft(res, -7);
743
0
  res = res & ~0xFF;
744
0
  res |= 0xFF & byte;
745
0
#endif
746
0
  return res;
747
0
};
748
749
inline PROTOBUF_ALWAYS_INLINE
750
0
const char* ReadTagInlined(const char* ptr, uint32_t* out) {
751
0
  uint64_t res = 0xFF & ptr[0];
752
0
  if (PROTOBUF_PREDICT_FALSE(res >= 128)) {
753
0
    res = RotRight7AndReplaceLowByte(res, ptr[1]);
754
0
    if (PROTOBUF_PREDICT_FALSE(res & 0x80)) {
755
0
      res = RotRight7AndReplaceLowByte(res, ptr[2]);
756
0
      if (PROTOBUF_PREDICT_FALSE(res & 0x80)) {
757
0
        res = RotRight7AndReplaceLowByte(res, ptr[3]);
758
0
        if (PROTOBUF_PREDICT_FALSE(res & 0x80)) {
759
0
          // Note: this wouldn't work if res were 32-bit,
760
0
          // because then replacing the low byte would overwrite
761
0
          // the bottom 4 bits of the result.
762
0
          res = RotRight7AndReplaceLowByte(res, ptr[4]);
763
0
          if (PROTOBUF_PREDICT_FALSE(res & 0x80)) {
764
0
            // The proto format does not permit longer than 5-byte encodings for
765
0
            // tags.
766
0
            *out = 0;
767
0
            return nullptr;
768
0
          }
769
0
          *out = static_cast<uint32_t>(RotateLeft(res, 28));
770
0
#if defined(__GNUC__)
771
0
          // Note: this asm statement prevents the compiler from
772
0
          // trying to share the "return ptr + constant" among all
773
0
          // branches.
774
0
          asm("" : "+r"(ptr));
775
0
#endif
776
0
          return ptr + 5;
777
0
        }
778
0
        *out = static_cast<uint32_t>(RotateLeft(res, 21));
779
0
        return ptr + 4;
780
0
      }
781
0
      *out = static_cast<uint32_t>(RotateLeft(res, 14));
782
0
      return ptr + 3;
783
0
    }
784
0
    *out = static_cast<uint32_t>(RotateLeft(res, 7));
785
0
    return ptr + 2;
786
0
  }
787
0
  *out = static_cast<uint32_t>(res);
788
0
  return ptr + 1;
789
0
}
790
791
// Decode 2 consecutive bytes of a varint and returns the value, shifted left
792
// by 1. It simultaneous updates *ptr to *ptr + 1 or *ptr + 2 depending if the
793
// first byte's continuation bit is set.
794
// If bit 15 of return value is set (equivalent to the continuation bits of both
795
// bytes being set) the varint continues, otherwise the parse is done. On x86
796
// movsx eax, dil
797
// and edi, eax
798
// add eax, edi
799
// adc [rsi], 1
800
0
inline uint32_t DecodeTwoBytes(const char** ptr) {
801
0
  uint32_t value = UnalignedLoad<uint16_t>(*ptr);
802
0
  // Sign extend the low byte continuation bit
803
0
  uint32_t x = static_cast<int8_t>(value);
804
0
  value &= x;  // Mask out the high byte iff no continuation
805
0
  // This add is an amazing operation, it cancels the low byte continuation bit
806
0
  // from y transferring it to the carry. Simultaneously it also shifts the 7
807
0
  // LSB left by one tightly against high byte varint bits. Hence value now
808
0
  // contains the unpacked value shifted left by 1.
809
0
  value += x;
810
0
  // Use the carry to update the ptr appropriately.
811
0
  *ptr += value < x ? 2 : 1;
812
0
  return value;
813
0
}
814
815
// More efficient varint parsing for big varints
816
0
inline const char* ParseBigVarint(const char* p, uint64_t* out) {
817
0
  auto pnew = p;
818
0
  auto tmp = DecodeTwoBytes(&pnew);
819
0
  uint64_t res = tmp >> 1;
820
0
  if (PROTOBUF_PREDICT_TRUE(static_cast<std::int16_t>(tmp) >= 0)) {
821
0
    *out = res;
822
0
    return pnew;
823
0
  }
824
0
  for (std::uint32_t i = 1; i < 5; i++) {
825
0
    pnew = p + 2 * i;
826
0
    tmp = DecodeTwoBytes(&pnew);
827
0
    res += (static_cast<std::uint64_t>(tmp) - 2) << (14 * i - 1);
828
0
    if (PROTOBUF_PREDICT_TRUE(static_cast<std::int16_t>(tmp) >= 0)) {
829
0
      *out = res;
830
0
      return pnew;
831
0
    }
832
0
  }
833
0
  return nullptr;
834
0
}
835
836
PROTOBUF_EXPORT
837
std::pair<const char*, int32_t> ReadSizeFallback(const char* p, uint32_t first);
838
// Used for tags, could read up to 5 bytes which must be available. Additionally
839
// it makes sure the unsigned value fits a int32_t, otherwise returns nullptr.
840
// Caller must ensure its safe to call.
841
0
inline uint32_t ReadSize(const char** pp) {
842
0
  auto p = *pp;
843
0
  uint32_t res = static_cast<uint8_t>(p[0]);
844
0
  if (res < 128) {
845
0
    *pp = p + 1;
846
0
    return res;
847
0
  }
848
0
  auto x = ReadSizeFallback(p, res);
849
0
  *pp = x.first;
850
0
  return x.second;
851
0
}
852
853
// Some convenience functions to simplify the generated parse loop code.
854
// Returning the value and updating the buffer pointer allows for nicer
855
// function composition. We rely on the compiler to inline this.
856
// Also in debug compiles having local scoped variables tend to generated
857
// stack frames that scale as O(num fields).
858
0
inline uint64_t ReadVarint64(const char** p) {
859
0
  uint64_t tmp;
860
0
  *p = VarintParse(*p, &tmp);
861
0
  return tmp;
862
0
}
863
864
0
inline uint32_t ReadVarint32(const char** p) {
865
0
  uint32_t tmp;
866
0
  *p = VarintParse(*p, &tmp);
867
0
  return tmp;
868
0
}
869
870
0
inline int64_t ReadVarintZigZag64(const char** p) {
871
0
  uint64_t tmp;
872
0
  *p = VarintParse(*p, &tmp);
873
0
  return WireFormatLite::ZigZagDecode64(tmp);
874
0
}
875
876
0
inline int32_t ReadVarintZigZag32(const char** p) {
877
0
  uint64_t tmp;
878
0
  *p = VarintParse(*p, &tmp);
879
0
  return WireFormatLite::ZigZagDecode32(static_cast<uint32_t>(tmp));
880
0
}
881
882
template <typename T, typename std::enable_if<
883
                          !std::is_base_of<MessageLite, T>::value, bool>::type>
884
PROTOBUF_NODISCARD const char* ParseContext::ParseMessage(T* msg,
885
                                                          const char* ptr) {
886
  int old;
887
  ptr = ReadSizeAndPushLimitAndDepth(ptr, &old);
888
  if (ptr == nullptr) return ptr;
889
  auto old_depth = depth_;
890
  ptr = msg->_InternalParse(ptr, this);
891
  if (ptr != nullptr) ABSL_DCHECK_EQ(old_depth, depth_);
892
  depth_++;
893
  if (!PopLimit(old)) return nullptr;
894
  return ptr;
895
}
896
897
inline const char* ParseContext::ReadSizeAndPushLimitAndDepthInlined(
898
0
    const char* ptr, int* old_limit) {
899
0
  int size = ReadSize(&ptr);
900
0
  if (PROTOBUF_PREDICT_FALSE(!ptr)) {
901
0
    // Make sure this isn't uninitialized even on error return
902
0
    *old_limit = 0;
903
0
    return nullptr;
904
0
  }
905
0
  *old_limit = PushLimit(ptr, size);
906
0
  if (--depth_ < 0) return nullptr;
907
0
  return ptr;
908
0
}
909
910
template <typename Tag, typename T>
911
const char* EpsCopyInputStream::ReadRepeatedFixed(const char* ptr,
912
                                                  Tag expected_tag,
913
                                                  RepeatedField<T>* out) {
914
  do {
915
    out->Add(UnalignedLoad<T>(ptr));
916
    ptr += sizeof(T);
917
    if (PROTOBUF_PREDICT_FALSE(ptr >= limit_end_)) return ptr;
918
  } while (UnalignedLoad<Tag>(ptr) == expected_tag && (ptr += sizeof(Tag)));
919
  return ptr;
920
}
921
922
// Add any of the following lines to debug which parse function is failing.
923
924
#define GOOGLE_PROTOBUF_ASSERT_RETURN(predicate, ret) \
925
  if (!(predicate)) {                                  \
926
    /*  ::raise(SIGINT);  */                           \
927
    /*  ABSL_LOG(ERROR) << "Parse failure";  */        \
928
    return ret;                                        \
929
  }
930
931
#define GOOGLE_PROTOBUF_PARSER_ASSERT(predicate) \
932
  GOOGLE_PROTOBUF_ASSERT_RETURN(predicate, nullptr)
933
934
template <typename T>
935
const char* EpsCopyInputStream::ReadPackedFixed(const char* ptr, int size,
936
                                                RepeatedField<T>* out) {
937
  GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
938
  int nbytes = static_cast<int>(buffer_end_ + kSlopBytes - ptr);
939
  while (size > nbytes) {
940
    int num = nbytes / sizeof(T);
941
    int old_entries = out->size();
942
    out->Reserve(old_entries + num);
943
    int block_size = num * sizeof(T);
944
    auto dst = out->AddNAlreadyReserved(num);
945
#ifdef PROTOBUF_LITTLE_ENDIAN
946
    std::memcpy(dst, ptr, block_size);
947
#else
948
    for (int i = 0; i < num; i++)
949
      dst[i] = UnalignedLoad<T>(ptr + i * sizeof(T));
950
#endif
951
    size -= block_size;
952
    if (limit_ <= kSlopBytes) return nullptr;
953
    ptr = Next();
954
    if (ptr == nullptr) return nullptr;
955
    ptr += kSlopBytes - (nbytes - block_size);
956
    nbytes = static_cast<int>(buffer_end_ + kSlopBytes - ptr);
957
  }
958
  int num = size / sizeof(T);
959
  int block_size = num * sizeof(T);
960
  if (num == 0) return size == block_size ? ptr : nullptr;
961
  int old_entries = out->size();
962
  out->Reserve(old_entries + num);
963
  auto dst = out->AddNAlreadyReserved(num);
964
#ifdef PROTOBUF_LITTLE_ENDIAN
965
  ABSL_CHECK(dst != nullptr) << out << "," << num;
966
  std::memcpy(dst, ptr, block_size);
967
#else
968
  for (int i = 0; i < num; i++) dst[i] = UnalignedLoad<T>(ptr + i * sizeof(T));
969
#endif
970
  ptr += block_size;
971
  if (size != block_size) return nullptr;
972
  return ptr;
973
}
974
975
template <typename Add>
976
const char* ReadPackedVarintArray(const char* ptr, const char* end, Add add) {
977
  while (ptr < end) {
978
    uint64_t varint;
979
    ptr = VarintParse(ptr, &varint);
980
    if (ptr == nullptr) return nullptr;
981
    add(varint);
982
  }
983
  return ptr;
984
}
985
986
template <typename Add>
987
const char* EpsCopyInputStream::ReadPackedVarint(const char* ptr, Add add) {
988
  int size = ReadSize(&ptr);
989
  GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
990
  int chunk_size = static_cast<int>(buffer_end_ - ptr);
991
  while (size > chunk_size) {
992
    ptr = ReadPackedVarintArray(ptr, buffer_end_, add);
993
    if (ptr == nullptr) return nullptr;
994
    int overrun = static_cast<int>(ptr - buffer_end_);
995
    ABSL_DCHECK(overrun >= 0 && overrun <= kSlopBytes);
996
    if (size - chunk_size <= kSlopBytes) {
997
      // The current buffer contains all the information needed, we don't need
998
      // to flip buffers. However we must parse from a buffer with enough space
999
      // so we are not prone to a buffer overflow.
1000
      char buf[kSlopBytes + 10] = {};
1001
      std::memcpy(buf, buffer_end_, kSlopBytes);
1002
      ABSL_CHECK_LE(size - chunk_size, kSlopBytes);
1003
      auto end = buf + (size - chunk_size);
1004
      auto res = ReadPackedVarintArray(buf + overrun, end, add);
1005
      if (res == nullptr || res != end) return nullptr;
1006
      return buffer_end_ + (res - buf);
1007
    }
1008
    size -= overrun + chunk_size;
1009
    ABSL_DCHECK_GT(size, 0);
1010
    // We must flip buffers
1011
    if (limit_ <= kSlopBytes) return nullptr;
1012
    ptr = Next();
1013
    if (ptr == nullptr) return nullptr;
1014
    ptr += overrun;
1015
    chunk_size = static_cast<int>(buffer_end_ - ptr);
1016
  }
1017
  auto end = ptr + size;
1018
  ptr = ReadPackedVarintArray(ptr, end, add);
1019
  return end == ptr ? ptr : nullptr;
1020
}
1021
1022
// Helper for verification of utf8
1023
PROTOBUF_EXPORT
1024
bool VerifyUTF8(absl::string_view s, const char* field_name);
1025
1026
0
inline bool VerifyUTF8(const std::string* s, const char* field_name) {
1027
0
  return VerifyUTF8(*s, field_name);
1028
0
}
1029
1030
// All the string parsers with or without UTF checking and for all CTypes.
1031
PROTOBUF_NODISCARD PROTOBUF_EXPORT const char* InlineGreedyStringParser(
1032
    std::string* s, const char* ptr, ParseContext* ctx);
1033
1034
1035
template <typename T>
1036
PROTOBUF_NODISCARD const char* FieldParser(uint64_t tag, T& field_parser,
1037
                                           const char* ptr, ParseContext* ctx) {
1038
  uint32_t number = tag >> 3;
1039
  GOOGLE_PROTOBUF_PARSER_ASSERT(number != 0);
1040
  using WireType = internal::WireFormatLite::WireType;
1041
  switch (tag & 7) {
1042
    case WireType::WIRETYPE_VARINT: {
1043
      uint64_t value;
1044
      ptr = VarintParse(ptr, &value);
1045
      GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
1046
      field_parser.AddVarint(number, value);
1047
      break;
1048
    }
1049
    case WireType::WIRETYPE_FIXED64: {
1050
      uint64_t value = UnalignedLoad<uint64_t>(ptr);
1051
      ptr += 8;
1052
      field_parser.AddFixed64(number, value);
1053
      break;
1054
    }
1055
    case WireType::WIRETYPE_LENGTH_DELIMITED: {
1056
      ptr = field_parser.ParseLengthDelimited(number, ptr, ctx);
1057
      GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
1058
      break;
1059
    }
1060
    case WireType::WIRETYPE_START_GROUP: {
1061
      ptr = field_parser.ParseGroup(number, ptr, ctx);
1062
      GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
1063
      break;
1064
    }
1065
    case WireType::WIRETYPE_END_GROUP: {
1066
      ABSL_LOG(FATAL) << "Can't happen";
1067
      break;
1068
    }
1069
    case WireType::WIRETYPE_FIXED32: {
1070
      uint32_t value = UnalignedLoad<uint32_t>(ptr);
1071
      ptr += 4;
1072
      field_parser.AddFixed32(number, value);
1073
      break;
1074
    }
1075
    default:
1076
      return nullptr;
1077
  }
1078
  return ptr;
1079
}
1080
1081
template <typename T>
1082
PROTOBUF_NODISCARD const char* WireFormatParser(T& field_parser,
1083
                                                const char* ptr,
1084
                                                ParseContext* ctx) {
1085
  while (!ctx->Done(&ptr)) {
1086
    uint32_t tag;
1087
    ptr = ReadTag(ptr, &tag);
1088
    GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
1089
    if (tag == 0 || (tag & 7) == 4) {
1090
      ctx->SetLastTag(tag);
1091
      return ptr;
1092
    }
1093
    ptr = FieldParser(tag, field_parser, ptr, ctx);
1094
    GOOGLE_PROTOBUF_PARSER_ASSERT(ptr != nullptr);
1095
  }
1096
  return ptr;
1097
}
1098
1099
// The packed parsers parse repeated numeric primitives directly into  the
1100
// corresponding field
1101
1102
// These are packed varints
1103
PROTOBUF_NODISCARD PROTOBUF_EXPORT const char* PackedInt32Parser(
1104
    void* object, const char* ptr, ParseContext* ctx);
1105
PROTOBUF_NODISCARD PROTOBUF_EXPORT const char* PackedUInt32Parser(
1106
    void* object, const char* ptr, ParseContext* ctx);
1107
PROTOBUF_NODISCARD PROTOBUF_EXPORT const char* PackedInt64Parser(
1108
    void* object, const char* ptr, ParseContext* ctx);
1109
PROTOBUF_NODISCARD PROTOBUF_EXPORT const char* PackedUInt64Parser(
1110
    void* object, const char* ptr, ParseContext* ctx);
1111
PROTOBUF_NODISCARD PROTOBUF_EXPORT const char* PackedSInt32Parser(
1112
    void* object, const char* ptr, ParseContext* ctx);
1113
PROTOBUF_NODISCARD PROTOBUF_EXPORT const char* PackedSInt64Parser(
1114
    void* object, const char* ptr, ParseContext* ctx);
1115
PROTOBUF_NODISCARD PROTOBUF_EXPORT const char* PackedEnumParser(
1116
    void* object, const char* ptr, ParseContext* ctx);
1117
1118
template <typename T>
1119
PROTOBUF_NODISCARD const char* PackedEnumParser(void* object, const char* ptr,
1120
                                                ParseContext* ctx,
1121
                                                bool (*is_valid)(int),
1122
                                                InternalMetadata* metadata,
1123
                                                int field_num) {
1124
  return ctx->ReadPackedVarint(
1125
      ptr, [object, is_valid, metadata, field_num](uint64_t val) {
1126
        if (is_valid(val)) {
1127
          static_cast<RepeatedField<int>*>(object)->Add(val);
1128
        } else {
1129
          WriteVarint(field_num, val, metadata->mutable_unknown_fields<T>());
1130
        }
1131
      });
1132
}
1133
1134
template <typename T>
1135
PROTOBUF_NODISCARD const char* PackedEnumParserArg(
1136
    void* object, const char* ptr, ParseContext* ctx,
1137
    bool (*is_valid)(const void*, int), const void* data,
1138
    InternalMetadata* metadata, int field_num) {
1139
  return ctx->ReadPackedVarint(
1140
      ptr, [object, is_valid, data, metadata, field_num](uint64_t val) {
1141
        if (is_valid(data, val)) {
1142
          static_cast<RepeatedField<int>*>(object)->Add(val);
1143
        } else {
1144
          WriteVarint(field_num, val, metadata->mutable_unknown_fields<T>());
1145
        }
1146
      });
1147
}
1148
1149
PROTOBUF_NODISCARD PROTOBUF_EXPORT const char* PackedBoolParser(
1150
    void* object, const char* ptr, ParseContext* ctx);
1151
PROTOBUF_NODISCARD PROTOBUF_EXPORT const char* PackedFixed32Parser(
1152
    void* object, const char* ptr, ParseContext* ctx);
1153
PROTOBUF_NODISCARD PROTOBUF_EXPORT const char* PackedSFixed32Parser(
1154
    void* object, const char* ptr, ParseContext* ctx);
1155
PROTOBUF_NODISCARD PROTOBUF_EXPORT const char* PackedFixed64Parser(
1156
    void* object, const char* ptr, ParseContext* ctx);
1157
PROTOBUF_NODISCARD PROTOBUF_EXPORT const char* PackedSFixed64Parser(
1158
    void* object, const char* ptr, ParseContext* ctx);
1159
PROTOBUF_NODISCARD PROTOBUF_EXPORT const char* PackedFloatParser(
1160
    void* object, const char* ptr, ParseContext* ctx);
1161
PROTOBUF_NODISCARD PROTOBUF_EXPORT const char* PackedDoubleParser(
1162
    void* object, const char* ptr, ParseContext* ctx);
1163
1164
// This is the only recursive parser.
1165
PROTOBUF_NODISCARD PROTOBUF_EXPORT const char* UnknownGroupLiteParse(
1166
    std::string* unknown, const char* ptr, ParseContext* ctx);
1167
// This is a helper to for the UnknownGroupLiteParse but is actually also
1168
// useful in the generated code. It uses overload on std::string* vs
1169
// UnknownFieldSet* to make the generated code isomorphic between full and lite.
1170
PROTOBUF_NODISCARD PROTOBUF_EXPORT const char* UnknownFieldParse(
1171
    uint32_t tag, std::string* unknown, const char* ptr, ParseContext* ctx);
1172
1173
}  // namespace internal
1174
}  // namespace protobuf
1175
}  // namespace google
1176
1177
#include "google/protobuf/port_undef.inc"
1178
1179
#endif  // GOOGLE_PROTOBUF_PARSE_CONTEXT_H__