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