Coverage Report

Created: 2025-07-04 06:48

/src/sentencepiece/third_party/protobuf-lite/coded_stream.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
// This implementation is heavily optimized to make reads and writes
36
// of small values (especially varints) as fast as possible.  In
37
// particular, we optimize for the common case that a read or a write
38
// will not cross the end of the buffer, since we can avoid a lot
39
// of branching in this case.
40
41
#include <google/protobuf/io/coded_stream.h>
42
43
#include <limits.h>
44
45
#include <algorithm>
46
#include <cstring>
47
#include <utility>
48
49
#include <google/protobuf/stubs/logging.h>
50
#include <google/protobuf/stubs/common.h>
51
#include <google/protobuf/arena.h>
52
#include <google/protobuf/io/zero_copy_stream.h>
53
#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
54
#include <google/protobuf/stubs/stl_util.h>
55
56
57
#include <google/protobuf/port_def.inc>
58
59
namespace google {
60
namespace protobuf {
61
namespace io {
62
63
namespace {
64
65
static const int kMaxVarintBytes = 10;
66
static const int kMaxVarint32Bytes = 5;
67
68
69
inline bool NextNonEmpty(ZeroCopyInputStream* input, const void** data,
70
0
                         int* size) {
71
0
  bool success;
72
0
  do {
73
0
    success = input->Next(data, size);
74
0
  } while (success && *size == 0);
75
0
  return success;
76
0
}
77
78
}  // namespace
79
80
// CodedInputStream ==================================================
81
82
0
CodedInputStream::~CodedInputStream() {
83
0
  if (input_ != NULL) {
84
0
    BackUpInputToCurrentPosition();
85
0
  }
86
0
}
87
88
// Static.
89
int CodedInputStream::default_recursion_limit_ = 100;
90
91
92
0
void CodedInputStream::BackUpInputToCurrentPosition() {
93
0
  int backup_bytes = BufferSize() + buffer_size_after_limit_ + overflow_bytes_;
94
0
  if (backup_bytes > 0) {
95
0
    input_->BackUp(backup_bytes);
96
97
    // total_bytes_read_ doesn't include overflow_bytes_.
98
0
    total_bytes_read_ -= BufferSize() + buffer_size_after_limit_;
99
0
    buffer_end_ = buffer_;
100
0
    buffer_size_after_limit_ = 0;
101
0
    overflow_bytes_ = 0;
102
0
  }
103
0
}
104
105
0
inline void CodedInputStream::RecomputeBufferLimits() {
106
0
  buffer_end_ += buffer_size_after_limit_;
107
0
  int closest_limit = std::min(current_limit_, total_bytes_limit_);
108
0
  if (closest_limit < total_bytes_read_) {
109
    // The limit position is in the current buffer.  We must adjust
110
    // the buffer size accordingly.
111
0
    buffer_size_after_limit_ = total_bytes_read_ - closest_limit;
112
0
    buffer_end_ -= buffer_size_after_limit_;
113
0
  } else {
114
0
    buffer_size_after_limit_ = 0;
115
0
  }
116
0
}
117
118
0
CodedInputStream::Limit CodedInputStream::PushLimit(int byte_limit) {
119
  // Current position relative to the beginning of the stream.
120
0
  int current_position = CurrentPosition();
121
122
0
  Limit old_limit = current_limit_;
123
124
  // security: byte_limit is possibly evil, so check for negative values
125
  // and overflow. Also check that the new requested limit is before the
126
  // previous limit; otherwise we continue to enforce the previous limit.
127
0
  if (PROTOBUF_PREDICT_TRUE(byte_limit >= 0 &&
128
0
                            byte_limit <= INT_MAX - current_position &&
129
0
                            byte_limit < current_limit_ - current_position)) {
130
0
    current_limit_ = current_position + byte_limit;
131
0
    RecomputeBufferLimits();
132
0
  }
133
134
0
  return old_limit;
135
0
}
136
137
0
void CodedInputStream::PopLimit(Limit limit) {
138
  // The limit passed in is actually the *old* limit, which we returned from
139
  // PushLimit().
140
0
  current_limit_ = limit;
141
0
  RecomputeBufferLimits();
142
143
  // We may no longer be at a legitimate message end.  ReadTag() needs to be
144
  // called again to find out.
145
0
  legitimate_message_end_ = false;
146
0
}
147
148
std::pair<CodedInputStream::Limit, int>
149
0
CodedInputStream::IncrementRecursionDepthAndPushLimit(int byte_limit) {
150
0
  return std::make_pair(PushLimit(byte_limit), --recursion_budget_);
151
0
}
152
153
0
CodedInputStream::Limit CodedInputStream::ReadLengthAndPushLimit() {
154
0
  uint32 length;
155
0
  return PushLimit(ReadVarint32(&length) ? length : 0);
156
0
}
157
158
0
bool CodedInputStream::DecrementRecursionDepthAndPopLimit(Limit limit) {
159
0
  bool result = ConsumedEntireMessage();
160
0
  PopLimit(limit);
161
0
  GOOGLE_DCHECK_LT(recursion_budget_, recursion_limit_);
162
0
  ++recursion_budget_;
163
0
  return result;
164
0
}
165
166
0
bool CodedInputStream::CheckEntireMessageConsumedAndPopLimit(Limit limit) {
167
0
  bool result = ConsumedEntireMessage();
168
0
  PopLimit(limit);
169
0
  return result;
170
0
}
171
172
0
int CodedInputStream::BytesUntilLimit() const {
173
0
  if (current_limit_ == INT_MAX) return -1;
174
0
  int current_position = CurrentPosition();
175
176
0
  return current_limit_ - current_position;
177
0
}
178
179
0
void CodedInputStream::SetTotalBytesLimit(int total_bytes_limit) {
180
  // Make sure the limit isn't already past, since this could confuse other
181
  // code.
182
0
  int current_position = CurrentPosition();
183
0
  total_bytes_limit_ = std::max(current_position, total_bytes_limit);
184
0
  RecomputeBufferLimits();
185
0
}
186
187
0
int CodedInputStream::BytesUntilTotalBytesLimit() const {
188
0
  if (total_bytes_limit_ == INT_MAX) return -1;
189
0
  return total_bytes_limit_ - CurrentPosition();
190
0
}
191
192
0
void CodedInputStream::PrintTotalBytesLimitError() {
193
0
  GOOGLE_LOG(ERROR)
194
0
      << "A protocol message was rejected because it was too "
195
0
         "big (more than "
196
0
      << total_bytes_limit_
197
0
      << " bytes).  To increase the limit (or to disable these "
198
0
         "warnings), see CodedInputStream::SetTotalBytesLimit() "
199
0
         "in third_party/protobuf/src/google/protobuf/io/coded_stream.h.";
200
0
}
201
202
0
bool CodedInputStream::SkipFallback(int count, int original_buffer_size) {
203
0
  if (buffer_size_after_limit_ > 0) {
204
    // We hit a limit inside this buffer.  Advance to the limit and fail.
205
0
    Advance(original_buffer_size);
206
0
    return false;
207
0
  }
208
209
0
  count -= original_buffer_size;
210
0
  buffer_ = NULL;
211
0
  buffer_end_ = buffer_;
212
213
  // Make sure this skip doesn't try to skip past the current limit.
214
0
  int closest_limit = std::min(current_limit_, total_bytes_limit_);
215
0
  int bytes_until_limit = closest_limit - total_bytes_read_;
216
0
  if (bytes_until_limit < count) {
217
    // We hit the limit.  Skip up to it then fail.
218
0
    if (bytes_until_limit > 0) {
219
0
      total_bytes_read_ = closest_limit;
220
0
      input_->Skip(bytes_until_limit);
221
0
    }
222
0
    return false;
223
0
  }
224
225
0
  if (!input_->Skip(count)) {
226
0
    total_bytes_read_ = input_->ByteCount();
227
0
    return false;
228
0
  }
229
0
  total_bytes_read_ += count;
230
0
  return true;
231
0
}
232
233
0
bool CodedInputStream::GetDirectBufferPointer(const void** data, int* size) {
234
0
  if (BufferSize() == 0 && !Refresh()) return false;
235
236
0
  *data = buffer_;
237
0
  *size = BufferSize();
238
0
  return true;
239
0
}
240
241
0
bool CodedInputStream::ReadRaw(void* buffer, int size) {
242
0
  int current_buffer_size;
243
0
  while ((current_buffer_size = BufferSize()) < size) {
244
    // Reading past end of buffer.  Copy what we have, then refresh.
245
0
    memcpy(buffer, buffer_, current_buffer_size);
246
0
    buffer = reinterpret_cast<uint8*>(buffer) + current_buffer_size;
247
0
    size -= current_buffer_size;
248
0
    Advance(current_buffer_size);
249
0
    if (!Refresh()) return false;
250
0
  }
251
252
0
  memcpy(buffer, buffer_, size);
253
0
  Advance(size);
254
255
0
  return true;
256
0
}
257
258
0
bool CodedInputStream::ReadString(std::string* buffer, int size) {
259
0
  if (size < 0) return false;  // security: size is often user-supplied
260
261
0
  if (BufferSize() >= size) {
262
0
    STLStringResizeUninitialized(buffer, size);
263
0
    std::pair<char*, bool> z = as_string_data(buffer);
264
0
    if (z.second) {
265
      // Oddly enough, memcpy() requires its first two args to be non-NULL even
266
      // if we copy 0 bytes.  So, we have ensured that z.first is non-NULL here.
267
0
      GOOGLE_DCHECK(z.first != NULL);
268
0
      memcpy(z.first, buffer_, size);
269
0
      Advance(size);
270
0
    }
271
0
    return true;
272
0
  }
273
274
0
  return ReadStringFallback(buffer, size);
275
0
}
276
277
0
bool CodedInputStream::ReadStringFallback(std::string* buffer, int size) {
278
0
  if (!buffer->empty()) {
279
0
    buffer->clear();
280
0
  }
281
282
0
  int closest_limit = std::min(current_limit_, total_bytes_limit_);
283
0
  if (closest_limit != INT_MAX) {
284
0
    int bytes_to_limit = closest_limit - CurrentPosition();
285
0
    if (bytes_to_limit > 0 && size > 0 && size <= bytes_to_limit) {
286
0
      buffer->reserve(size);
287
0
    }
288
0
  }
289
290
0
  int current_buffer_size;
291
0
  while ((current_buffer_size = BufferSize()) < size) {
292
    // Some STL implementations "helpfully" crash on buffer->append(NULL, 0).
293
0
    if (current_buffer_size != 0) {
294
      // Note:  string1.append(string2) is O(string2.size()) (as opposed to
295
      //   O(string1.size() + string2.size()), which would be bad).
296
0
      buffer->append(reinterpret_cast<const char*>(buffer_),
297
0
                     current_buffer_size);
298
0
    }
299
0
    size -= current_buffer_size;
300
0
    Advance(current_buffer_size);
301
0
    if (!Refresh()) return false;
302
0
  }
303
304
0
  buffer->append(reinterpret_cast<const char*>(buffer_), size);
305
0
  Advance(size);
306
307
0
  return true;
308
0
}
309
310
311
0
bool CodedInputStream::ReadLittleEndian32Fallback(uint32* value) {
312
0
  uint8 bytes[sizeof(*value)];
313
314
0
  const uint8* ptr;
315
0
  if (BufferSize() >= sizeof(*value)) {
316
    // Fast path:  Enough bytes in the buffer to read directly.
317
0
    ptr = buffer_;
318
0
    Advance(sizeof(*value));
319
0
  } else {
320
    // Slow path:  Had to read past the end of the buffer.
321
0
    if (!ReadRaw(bytes, sizeof(*value))) return false;
322
0
    ptr = bytes;
323
0
  }
324
0
  ReadLittleEndian32FromArray(ptr, value);
325
0
  return true;
326
0
}
327
328
0
bool CodedInputStream::ReadLittleEndian64Fallback(uint64* value) {
329
0
  uint8 bytes[sizeof(*value)];
330
331
0
  const uint8* ptr;
332
0
  if (BufferSize() >= sizeof(*value)) {
333
    // Fast path:  Enough bytes in the buffer to read directly.
334
0
    ptr = buffer_;
335
0
    Advance(sizeof(*value));
336
0
  } else {
337
    // Slow path:  Had to read past the end of the buffer.
338
0
    if (!ReadRaw(bytes, sizeof(*value))) return false;
339
0
    ptr = bytes;
340
0
  }
341
0
  ReadLittleEndian64FromArray(ptr, value);
342
0
  return true;
343
0
}
344
345
namespace {
346
347
// Decodes varint64 with known size, N, and returns next pointer. Knowing N at
348
// compile time, compiler can generate optimal code. For example, instead of
349
// subtracting 0x80 at each iteration, it subtracts properly shifted mask once.
350
template <size_t N>
351
0
const uint8* DecodeVarint64KnownSize(const uint8* buffer, uint64* value) {
352
0
  GOOGLE_DCHECK_GT(N, 0);
353
0
  uint64 result = static_cast<uint64>(buffer[N - 1]) << (7 * (N - 1));
354
0
  for (int i = 0, offset = 0; i < N - 1; i++, offset += 7) {
355
0
    result += static_cast<uint64>(buffer[i] - 0x80) << offset;
356
0
  }
357
0
  *value = result;
358
0
  return buffer + N;
359
0
}
Unexecuted instantiation: coded_stream.cc:unsigned char const* google::protobuf::io::(anonymous namespace)::DecodeVarint64KnownSize<2ul>(unsigned char const*, unsigned long*)
Unexecuted instantiation: coded_stream.cc:unsigned char const* google::protobuf::io::(anonymous namespace)::DecodeVarint64KnownSize<3ul>(unsigned char const*, unsigned long*)
Unexecuted instantiation: coded_stream.cc:unsigned char const* google::protobuf::io::(anonymous namespace)::DecodeVarint64KnownSize<4ul>(unsigned char const*, unsigned long*)
Unexecuted instantiation: coded_stream.cc:unsigned char const* google::protobuf::io::(anonymous namespace)::DecodeVarint64KnownSize<5ul>(unsigned char const*, unsigned long*)
Unexecuted instantiation: coded_stream.cc:unsigned char const* google::protobuf::io::(anonymous namespace)::DecodeVarint64KnownSize<6ul>(unsigned char const*, unsigned long*)
Unexecuted instantiation: coded_stream.cc:unsigned char const* google::protobuf::io::(anonymous namespace)::DecodeVarint64KnownSize<7ul>(unsigned char const*, unsigned long*)
Unexecuted instantiation: coded_stream.cc:unsigned char const* google::protobuf::io::(anonymous namespace)::DecodeVarint64KnownSize<8ul>(unsigned char const*, unsigned long*)
Unexecuted instantiation: coded_stream.cc:unsigned char const* google::protobuf::io::(anonymous namespace)::DecodeVarint64KnownSize<9ul>(unsigned char const*, unsigned long*)
Unexecuted instantiation: coded_stream.cc:unsigned char const* google::protobuf::io::(anonymous namespace)::DecodeVarint64KnownSize<10ul>(unsigned char const*, unsigned long*)
360
361
// Read a varint from the given buffer, write it to *value, and return a pair.
362
// The first part of the pair is true iff the read was successful.  The second
363
// part is buffer + (number of bytes read).  This function is always inlined,
364
// so returning a pair is costless.
365
PROTOBUF_ALWAYS_INLINE
366
::std::pair<bool, const uint8*> ReadVarint32FromArray(uint32 first_byte,
367
                                                      const uint8* buffer,
368
                                                      uint32* value);
369
inline ::std::pair<bool, const uint8*> ReadVarint32FromArray(
370
0
    uint32 first_byte, const uint8* buffer, uint32* value) {
371
  // Fast path:  We have enough bytes left in the buffer to guarantee that
372
  // this read won't cross the end, so we can skip the checks.
373
0
  GOOGLE_DCHECK_EQ(*buffer, first_byte);
374
0
  GOOGLE_DCHECK_EQ(first_byte & 0x80, 0x80) << first_byte;
375
0
  const uint8* ptr = buffer;
376
0
  uint32 b;
377
0
  uint32 result = first_byte - 0x80;
378
0
  ++ptr;  // We just processed the first byte.  Move on to the second.
379
0
  b = *(ptr++);
380
0
  result += b << 7;
381
0
  if (!(b & 0x80)) goto done;
382
0
  result -= 0x80 << 7;
383
0
  b = *(ptr++);
384
0
  result += b << 14;
385
0
  if (!(b & 0x80)) goto done;
386
0
  result -= 0x80 << 14;
387
0
  b = *(ptr++);
388
0
  result += b << 21;
389
0
  if (!(b & 0x80)) goto done;
390
0
  result -= 0x80 << 21;
391
0
  b = *(ptr++);
392
0
  result += b << 28;
393
0
  if (!(b & 0x80)) goto done;
394
  // "result -= 0x80 << 28" is irrevelant.
395
396
  // If the input is larger than 32 bits, we still need to read it all
397
  // and discard the high-order bits.
398
0
  for (int i = 0; i < kMaxVarintBytes - kMaxVarint32Bytes; i++) {
399
0
    b = *(ptr++);
400
0
    if (!(b & 0x80)) goto done;
401
0
  }
402
403
  // We have overrun the maximum size of a varint (10 bytes).  Assume
404
  // the data is corrupt.
405
0
  return std::make_pair(false, ptr);
406
407
0
done:
408
0
  *value = result;
409
0
  return std::make_pair(true, ptr);
410
0
}
411
412
PROTOBUF_ALWAYS_INLINE::std::pair<bool, const uint8*> ReadVarint64FromArray(
413
    const uint8* buffer, uint64* value);
414
inline ::std::pair<bool, const uint8*> ReadVarint64FromArray(
415
0
    const uint8* buffer, uint64* value) {
416
  // Assumes varint64 is at least 2 bytes.
417
0
  GOOGLE_DCHECK_GE(buffer[0], 128);
418
419
0
  const uint8* next;
420
0
  if (buffer[1] < 128) {
421
0
    next = DecodeVarint64KnownSize<2>(buffer, value);
422
0
  } else if (buffer[2] < 128) {
423
0
    next = DecodeVarint64KnownSize<3>(buffer, value);
424
0
  } else if (buffer[3] < 128) {
425
0
    next = DecodeVarint64KnownSize<4>(buffer, value);
426
0
  } else if (buffer[4] < 128) {
427
0
    next = DecodeVarint64KnownSize<5>(buffer, value);
428
0
  } else if (buffer[5] < 128) {
429
0
    next = DecodeVarint64KnownSize<6>(buffer, value);
430
0
  } else if (buffer[6] < 128) {
431
0
    next = DecodeVarint64KnownSize<7>(buffer, value);
432
0
  } else if (buffer[7] < 128) {
433
0
    next = DecodeVarint64KnownSize<8>(buffer, value);
434
0
  } else if (buffer[8] < 128) {
435
0
    next = DecodeVarint64KnownSize<9>(buffer, value);
436
0
  } else if (buffer[9] < 128) {
437
0
    next = DecodeVarint64KnownSize<10>(buffer, value);
438
0
  } else {
439
    // We have overrun the maximum size of a varint (10 bytes). Assume
440
    // the data is corrupt.
441
0
    return std::make_pair(false, buffer + 11);
442
0
  }
443
444
0
  return std::make_pair(true, next);
445
0
}
446
447
}  // namespace
448
449
0
bool CodedInputStream::ReadVarint32Slow(uint32* value) {
450
  // Directly invoke ReadVarint64Fallback, since we already tried to optimize
451
  // for one-byte varints.
452
0
  std::pair<uint64, bool> p = ReadVarint64Fallback();
453
0
  *value = static_cast<uint32>(p.first);
454
0
  return p.second;
455
0
}
456
457
0
int64 CodedInputStream::ReadVarint32Fallback(uint32 first_byte_or_zero) {
458
0
  if (BufferSize() >= kMaxVarintBytes ||
459
      // Optimization:  We're also safe if the buffer is non-empty and it ends
460
      // with a byte that would terminate a varint.
461
0
      (buffer_end_ > buffer_ && !(buffer_end_[-1] & 0x80))) {
462
0
    GOOGLE_DCHECK_NE(first_byte_or_zero, 0)
463
0
        << "Caller should provide us with *buffer_ when buffer is non-empty";
464
0
    uint32 temp;
465
0
    ::std::pair<bool, const uint8*> p =
466
0
        ReadVarint32FromArray(first_byte_or_zero, buffer_, &temp);
467
0
    if (!p.first) return -1;
468
0
    buffer_ = p.second;
469
0
    return temp;
470
0
  } else {
471
    // Really slow case: we will incur the cost of an extra function call here,
472
    // but moving this out of line reduces the size of this function, which
473
    // improves the common case. In micro benchmarks, this is worth about 10-15%
474
0
    uint32 temp;
475
0
    return ReadVarint32Slow(&temp) ? static_cast<int64>(temp) : -1;
476
0
  }
477
0
}
478
479
0
int CodedInputStream::ReadVarintSizeAsIntSlow() {
480
  // Directly invoke ReadVarint64Fallback, since we already tried to optimize
481
  // for one-byte varints.
482
0
  std::pair<uint64, bool> p = ReadVarint64Fallback();
483
0
  if (!p.second || p.first > static_cast<uint64>(INT_MAX)) return -1;
484
0
  return p.first;
485
0
}
486
487
0
int CodedInputStream::ReadVarintSizeAsIntFallback() {
488
0
  if (BufferSize() >= kMaxVarintBytes ||
489
      // Optimization:  We're also safe if the buffer is non-empty and it ends
490
      // with a byte that would terminate a varint.
491
0
      (buffer_end_ > buffer_ && !(buffer_end_[-1] & 0x80))) {
492
0
    uint64 temp;
493
0
    ::std::pair<bool, const uint8*> p = ReadVarint64FromArray(buffer_, &temp);
494
0
    if (!p.first || temp > static_cast<uint64>(INT_MAX)) return -1;
495
0
    buffer_ = p.second;
496
0
    return temp;
497
0
  } else {
498
    // Really slow case: we will incur the cost of an extra function call here,
499
    // but moving this out of line reduces the size of this function, which
500
    // improves the common case. In micro benchmarks, this is worth about 10-15%
501
0
    return ReadVarintSizeAsIntSlow();
502
0
  }
503
0
}
504
505
0
uint32 CodedInputStream::ReadTagSlow() {
506
0
  if (buffer_ == buffer_end_) {
507
    // Call refresh.
508
0
    if (!Refresh()) {
509
      // Refresh failed.  Make sure that it failed due to EOF, not because
510
      // we hit total_bytes_limit_, which, unlike normal limits, is not a
511
      // valid place to end a message.
512
0
      int current_position = total_bytes_read_ - buffer_size_after_limit_;
513
0
      if (current_position >= total_bytes_limit_) {
514
        // Hit total_bytes_limit_.  But if we also hit the normal limit,
515
        // we're still OK.
516
0
        legitimate_message_end_ = current_limit_ == total_bytes_limit_;
517
0
      } else {
518
0
        legitimate_message_end_ = true;
519
0
      }
520
0
      return 0;
521
0
    }
522
0
  }
523
524
  // For the slow path, just do a 64-bit read. Try to optimize for one-byte tags
525
  // again, since we have now refreshed the buffer.
526
0
  uint64 result = 0;
527
0
  if (!ReadVarint64(&result)) return 0;
528
0
  return static_cast<uint32>(result);
529
0
}
530
531
0
uint32 CodedInputStream::ReadTagFallback(uint32 first_byte_or_zero) {
532
0
  const int buf_size = BufferSize();
533
0
  if (buf_size >= kMaxVarintBytes ||
534
      // Optimization:  We're also safe if the buffer is non-empty and it ends
535
      // with a byte that would terminate a varint.
536
0
      (buf_size > 0 && !(buffer_end_[-1] & 0x80))) {
537
0
    GOOGLE_DCHECK_EQ(first_byte_or_zero, buffer_[0]);
538
0
    if (first_byte_or_zero == 0) {
539
0
      ++buffer_;
540
0
      return 0;
541
0
    }
542
0
    uint32 tag;
543
0
    ::std::pair<bool, const uint8*> p =
544
0
        ReadVarint32FromArray(first_byte_or_zero, buffer_, &tag);
545
0
    if (!p.first) {
546
0
      return 0;
547
0
    }
548
0
    buffer_ = p.second;
549
0
    return tag;
550
0
  } else {
551
    // We are commonly at a limit when attempting to read tags. Try to quickly
552
    // detect this case without making another function call.
553
0
    if ((buf_size == 0) &&
554
0
        ((buffer_size_after_limit_ > 0) ||
555
0
         (total_bytes_read_ == current_limit_)) &&
556
        // Make sure that the limit we hit is not total_bytes_limit_, since
557
        // in that case we still need to call Refresh() so that it prints an
558
        // error.
559
0
        total_bytes_read_ - buffer_size_after_limit_ < total_bytes_limit_) {
560
      // We hit a byte limit.
561
0
      legitimate_message_end_ = true;
562
0
      return 0;
563
0
    }
564
0
    return ReadTagSlow();
565
0
  }
566
0
}
567
568
0
bool CodedInputStream::ReadVarint64Slow(uint64* value) {
569
  // Slow path:  This read might cross the end of the buffer, so we
570
  // need to check and refresh the buffer if and when it does.
571
572
0
  uint64 result = 0;
573
0
  int count = 0;
574
0
  uint32 b;
575
576
0
  do {
577
0
    if (count == kMaxVarintBytes) {
578
0
      *value = 0;
579
0
      return false;
580
0
    }
581
0
    while (buffer_ == buffer_end_) {
582
0
      if (!Refresh()) {
583
0
        *value = 0;
584
0
        return false;
585
0
      }
586
0
    }
587
0
    b = *buffer_;
588
0
    result |= static_cast<uint64>(b & 0x7F) << (7 * count);
589
0
    Advance(1);
590
0
    ++count;
591
0
  } while (b & 0x80);
592
593
0
  *value = result;
594
0
  return true;
595
0
}
596
597
0
std::pair<uint64, bool> CodedInputStream::ReadVarint64Fallback() {
598
0
  if (BufferSize() >= kMaxVarintBytes ||
599
      // Optimization:  We're also safe if the buffer is non-empty and it ends
600
      // with a byte that would terminate a varint.
601
0
      (buffer_end_ > buffer_ && !(buffer_end_[-1] & 0x80))) {
602
0
    uint64 temp;
603
0
    ::std::pair<bool, const uint8*> p = ReadVarint64FromArray(buffer_, &temp);
604
0
    if (!p.first) {
605
0
      return std::make_pair(0, false);
606
0
    }
607
0
    buffer_ = p.second;
608
0
    return std::make_pair(temp, true);
609
0
  } else {
610
0
    uint64 temp;
611
0
    bool success = ReadVarint64Slow(&temp);
612
0
    return std::make_pair(temp, success);
613
0
  }
614
0
}
615
616
0
bool CodedInputStream::Refresh() {
617
0
  GOOGLE_DCHECK_EQ(0, BufferSize());
618
619
0
  if (buffer_size_after_limit_ > 0 || overflow_bytes_ > 0 ||
620
0
      total_bytes_read_ == current_limit_) {
621
    // We've hit a limit.  Stop.
622
0
    int current_position = total_bytes_read_ - buffer_size_after_limit_;
623
624
0
    if (current_position >= total_bytes_limit_ &&
625
0
        total_bytes_limit_ != current_limit_) {
626
      // Hit total_bytes_limit_.
627
0
      PrintTotalBytesLimitError();
628
0
    }
629
630
0
    return false;
631
0
  }
632
633
0
  const void* void_buffer;
634
0
  int buffer_size;
635
0
  if (NextNonEmpty(input_, &void_buffer, &buffer_size)) {
636
0
    buffer_ = reinterpret_cast<const uint8*>(void_buffer);
637
0
    buffer_end_ = buffer_ + buffer_size;
638
0
    GOOGLE_CHECK_GE(buffer_size, 0);
639
640
0
    if (total_bytes_read_ <= INT_MAX - buffer_size) {
641
0
      total_bytes_read_ += buffer_size;
642
0
    } else {
643
      // Overflow.  Reset buffer_end_ to not include the bytes beyond INT_MAX.
644
      // We can't get that far anyway, because total_bytes_limit_ is guaranteed
645
      // to be less than it.  We need to keep track of the number of bytes
646
      // we discarded, though, so that we can call input_->BackUp() to back
647
      // up over them on destruction.
648
649
      // The following line is equivalent to:
650
      //   overflow_bytes_ = total_bytes_read_ + buffer_size - INT_MAX;
651
      // except that it avoids overflows.  Signed integer overflow has
652
      // undefined results according to the C standard.
653
0
      overflow_bytes_ = total_bytes_read_ - (INT_MAX - buffer_size);
654
0
      buffer_end_ -= overflow_bytes_;
655
0
      total_bytes_read_ = INT_MAX;
656
0
    }
657
658
0
    RecomputeBufferLimits();
659
0
    return true;
660
0
  } else {
661
0
    buffer_ = NULL;
662
0
    buffer_end_ = NULL;
663
0
    return false;
664
0
  }
665
0
}
666
667
// CodedOutputStream =================================================
668
669
0
void EpsCopyOutputStream::EnableAliasing(bool enabled) {
670
0
  aliasing_enabled_ = enabled && stream_->AllowsAliasing();
671
0
}
672
673
0
int64 EpsCopyOutputStream::ByteCount(uint8* ptr) const {
674
  // Calculate the current offset relative to the end of the stream buffer.
675
0
  int delta = (end_ - ptr) + (buffer_end_ ? 0 : kSlopBytes);
676
0
  return stream_->ByteCount() - delta;
677
0
}
678
679
// Flushes what's written out to the underlying ZeroCopyOutputStream buffers.
680
// Returns the size remaining in the buffer and sets buffer_end_ to the start
681
// of the remaining buffer, ie. [buffer_end_, buffer_end_ + return value)
682
0
int EpsCopyOutputStream::Flush(uint8* ptr) {
683
0
  while (buffer_end_ && ptr > end_) {
684
0
    int overrun = ptr - end_;
685
0
    GOOGLE_DCHECK(!had_error_);
686
0
    GOOGLE_DCHECK(overrun <= kSlopBytes);  // NOLINT
687
0
    ptr = Next() + overrun;
688
0
    if (had_error_) return 0;
689
0
  }
690
0
  int s;
691
0
  if (buffer_end_) {
692
0
    std::memcpy(buffer_end_, buffer_, ptr - buffer_);
693
0
    buffer_end_ += ptr - buffer_;
694
0
    s = end_ - ptr;
695
0
  } else {
696
    // The stream is writing directly in the ZeroCopyOutputStream buffer.
697
0
    s = end_ + kSlopBytes - ptr;
698
0
    buffer_end_ = ptr;
699
0
  }
700
0
  GOOGLE_DCHECK(s >= 0);  // NOLINT
701
0
  return s;
702
0
}
703
704
0
uint8* EpsCopyOutputStream::Trim(uint8* ptr) {
705
0
  if (had_error_) return ptr;
706
0
  int s = Flush(ptr);
707
0
  if (s) stream_->BackUp(s);
708
  // Reset to initial state (expecting new buffer)
709
0
  buffer_end_ = end_ = buffer_;
710
0
  return buffer_;
711
0
}
712
713
714
0
uint8* EpsCopyOutputStream::FlushAndResetBuffer(uint8* ptr) {
715
0
  if (had_error_) return buffer_;
716
0
  int s = Flush(ptr);
717
0
  if (had_error_) return buffer_;
718
0
  return SetInitialBuffer(buffer_end_, s);
719
0
}
720
721
0
bool EpsCopyOutputStream::Skip(int count, uint8** pp) {
722
0
  if (count < 0) return false;
723
0
  if (had_error_) {
724
0
    *pp = buffer_;
725
0
    return false;
726
0
  }
727
0
  int size = Flush(*pp);
728
0
  if (had_error_) {
729
0
    *pp = buffer_;
730
0
    return false;
731
0
  }
732
0
  void* data = buffer_end_;
733
0
  while (count > size) {
734
0
    count -= size;
735
0
    if (!stream_->Next(&data, &size)) {
736
0
      *pp = Error();
737
0
      return false;
738
0
    }
739
0
  }
740
0
  *pp = SetInitialBuffer(static_cast<uint8*>(data) + count, size - count);
741
0
  return true;
742
0
}
743
744
bool EpsCopyOutputStream::GetDirectBufferPointer(void** data, int* size,
745
0
                                                 uint8** pp) {
746
0
  if (had_error_) {
747
0
    *pp = buffer_;
748
0
    return false;
749
0
  }
750
0
  *size = Flush(*pp);
751
0
  if (had_error_) {
752
0
    *pp = buffer_;
753
0
    return false;
754
0
  }
755
0
  *data = buffer_end_;
756
0
  while (*size == 0) {
757
0
    if (!stream_->Next(data, size)) {
758
0
      *pp = Error();
759
0
      return false;
760
0
    }
761
0
  }
762
0
  *pp = SetInitialBuffer(*data, *size);
763
0
  return true;
764
0
}
765
766
uint8* EpsCopyOutputStream::GetDirectBufferForNBytesAndAdvance(int size,
767
0
                                                               uint8** pp) {
768
0
  if (had_error_) {
769
0
    *pp = buffer_;
770
0
    return nullptr;
771
0
  }
772
0
  int s = Flush(*pp);
773
0
  if (had_error_) {
774
0
    *pp = buffer_;
775
0
    return nullptr;
776
0
  }
777
0
  if (s >= size) {
778
0
    auto res = buffer_end_;
779
0
    *pp = SetInitialBuffer(buffer_end_ + size, s - size);
780
0
    return res;
781
0
  } else {
782
0
    *pp = SetInitialBuffer(buffer_end_, s);
783
0
    return nullptr;
784
0
  }
785
0
}
786
787
0
uint8* EpsCopyOutputStream::Next() {
788
0
  GOOGLE_DCHECK(!had_error_);  // NOLINT
789
0
  if (PROTOBUF_PREDICT_FALSE(stream_ == nullptr)) return Error();
790
0
  if (buffer_end_) {
791
    // We're in the patch buffer and need to fill up the previous buffer.
792
0
    std::memcpy(buffer_end_, buffer_, end_ - buffer_);
793
0
    uint8* ptr;
794
0
    int size;
795
0
    do {
796
0
      void* data;
797
0
      if (PROTOBUF_PREDICT_FALSE(!stream_->Next(&data, &size))) {
798
        // Stream has an error, we use the patch buffer to continue to be
799
        // able to write.
800
0
        return Error();
801
0
      }
802
0
      ptr = static_cast<uint8*>(data);
803
0
    } while (size == 0);
804
0
    if (PROTOBUF_PREDICT_TRUE(size > kSlopBytes)) {
805
0
      std::memcpy(ptr, end_, kSlopBytes);
806
0
      end_ = ptr + size - kSlopBytes;
807
0
      buffer_end_ = nullptr;
808
0
      return ptr;
809
0
    } else {
810
0
      GOOGLE_DCHECK(size > 0);  // NOLINT
811
      // Buffer to small
812
0
      std::memmove(buffer_, end_, kSlopBytes);
813
0
      buffer_end_ = ptr;
814
0
      end_ = buffer_ + size;
815
0
      return buffer_;
816
0
    }
817
0
  } else {
818
0
    std::memcpy(buffer_, end_, kSlopBytes);
819
0
    buffer_end_ = end_;
820
0
    end_ = buffer_ + kSlopBytes;
821
0
    return buffer_;
822
0
  }
823
0
}
824
825
0
uint8* EpsCopyOutputStream::EnsureSpaceFallback(uint8* ptr) {
826
0
  do {
827
0
    if (PROTOBUF_PREDICT_FALSE(had_error_)) return buffer_;
828
0
    int overrun = ptr - end_;
829
0
    GOOGLE_DCHECK(overrun >= 0);           // NOLINT
830
0
    GOOGLE_DCHECK(overrun <= kSlopBytes);  // NOLINT
831
0
    ptr = Next() + overrun;
832
0
  } while (ptr >= end_);
833
0
  GOOGLE_DCHECK(ptr < end_);  // NOLINT
834
0
  return ptr;
835
0
}
836
837
uint8* EpsCopyOutputStream::WriteRawFallback(const void* data, int size,
838
0
                                             uint8* ptr) {
839
0
  int s = GetSize(ptr);
840
0
  while (s < size) {
841
0
    std::memcpy(ptr, data, s);
842
0
    size -= s;
843
0
    data = static_cast<const uint8*>(data) + s;
844
0
    ptr = EnsureSpaceFallback(ptr + s);
845
0
    s = GetSize(ptr);
846
0
  }
847
0
  std::memcpy(ptr, data, size);
848
0
  return ptr + size;
849
0
}
850
851
uint8* EpsCopyOutputStream::WriteAliasedRaw(const void* data, int size,
852
0
                                            uint8* ptr) {
853
0
  if (size < GetSize(ptr)
854
0
  ) {
855
0
    return WriteRaw(data, size, ptr);
856
0
  } else {
857
0
    ptr = Trim(ptr);
858
0
    if (stream_->WriteAliasedRaw(data, size)) return ptr;
859
0
    return Error();
860
0
  }
861
0
}
862
863
#ifndef PROTOBUF_LITTLE_ENDIAN
864
uint8* EpsCopyOutputStream::WriteRawLittleEndian32(const void* data, int size,
865
                                                   uint8* ptr) {
866
  auto p = static_cast<const uint8*>(data);
867
  auto end = p + size;
868
  while (end - p >= kSlopBytes) {
869
    ptr = EnsureSpace(ptr);
870
    uint32 buffer[4];
871
    static_assert(sizeof(buffer) == kSlopBytes, "Buffer must be kSlopBytes");
872
    std::memcpy(buffer, p, kSlopBytes);
873
    p += kSlopBytes;
874
    for (auto x : buffer)
875
      ptr = CodedOutputStream::WriteLittleEndian32ToArray(x, ptr);
876
  }
877
  while (p < end) {
878
    ptr = EnsureSpace(ptr);
879
    uint32 buffer;
880
    std::memcpy(&buffer, p, 4);
881
    p += 4;
882
    ptr = CodedOutputStream::WriteLittleEndian32ToArray(buffer, ptr);
883
  }
884
  return ptr;
885
}
886
887
uint8* EpsCopyOutputStream::WriteRawLittleEndian64(const void* data, int size,
888
                                                   uint8* ptr) {
889
  auto p = static_cast<const uint8*>(data);
890
  auto end = p + size;
891
  while (end - p >= kSlopBytes) {
892
    ptr = EnsureSpace(ptr);
893
    uint64 buffer[2];
894
    static_assert(sizeof(buffer) == kSlopBytes, "Buffer must be kSlopBytes");
895
    std::memcpy(buffer, p, kSlopBytes);
896
    p += kSlopBytes;
897
    for (auto x : buffer)
898
      ptr = CodedOutputStream::WriteLittleEndian64ToArray(x, ptr);
899
  }
900
  while (p < end) {
901
    ptr = EnsureSpace(ptr);
902
    uint64 buffer;
903
    std::memcpy(&buffer, p, 8);
904
    p += 8;
905
    ptr = CodedOutputStream::WriteLittleEndian64ToArray(buffer, ptr);
906
  }
907
  return ptr;
908
}
909
#endif
910
911
912
uint8* EpsCopyOutputStream::WriteStringMaybeAliasedOutline(uint32 num,
913
                                                           const std::string& s,
914
0
                                                           uint8* ptr) {
915
0
  ptr = EnsureSpace(ptr);
916
0
  uint32 size = s.size();
917
0
  ptr = WriteLengthDelim(num, size, ptr);
918
0
  return WriteRawMaybeAliased(s.data(), size, ptr);
919
0
}
920
921
uint8* EpsCopyOutputStream::WriteStringOutline(uint32 num, const std::string& s,
922
0
                                               uint8* ptr) {
923
0
  ptr = EnsureSpace(ptr);
924
0
  uint32 size = s.size();
925
0
  ptr = WriteLengthDelim(num, size, ptr);
926
0
  return WriteRaw(s.data(), size, ptr);
927
0
}
928
929
std::atomic<bool> CodedOutputStream::default_serialization_deterministic_{
930
    false};
931
932
CodedOutputStream::CodedOutputStream(ZeroCopyOutputStream* stream,
933
                                     bool do_eager_refresh)
934
0
    : impl_(stream, IsDefaultSerializationDeterministic(), &cur_),
935
0
      start_count_(stream->ByteCount()) {
936
0
  if (do_eager_refresh) {
937
0
    void* data;
938
0
    int size;
939
0
    if (!stream->Next(&data, &size) || size == 0) return;
940
0
    cur_ = impl_.SetInitialBuffer(data, size);
941
0
  }
942
0
}
943
944
0
CodedOutputStream::~CodedOutputStream() { Trim(); }
945
946
947
uint8* CodedOutputStream::WriteStringWithSizeToArray(const std::string& str,
948
0
                                                     uint8* target) {
949
0
  GOOGLE_DCHECK_LE(str.size(), kuint32max);
950
0
  target = WriteVarint32ToArray(str.size(), target);
951
0
  return WriteStringToArray(str, target);
952
0
}
953
954
}  // namespace io
955
}  // namespace protobuf
956
}  // namespace google