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