• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
NextNonEmpty(ZeroCopyInputStream * input,const void ** data,int * size)69 inline bool NextNonEmpty(ZeroCopyInputStream* input, const void** data,
70                          int* size) {
71   bool success;
72   do {
73     success = input->Next(data, size);
74   } while (success && *size == 0);
75   return success;
76 }
77 
78 }  // namespace
79 
80 // CodedInputStream ==================================================
81 
~CodedInputStream()82 CodedInputStream::~CodedInputStream() {
83   if (input_ != NULL) {
84     BackUpInputToCurrentPosition();
85   }
86 }
87 
88 // Static.
89 int CodedInputStream::default_recursion_limit_ = 100;
90 
91 
BackUpInputToCurrentPosition()92 void CodedInputStream::BackUpInputToCurrentPosition() {
93   int backup_bytes = BufferSize() + buffer_size_after_limit_ + overflow_bytes_;
94   if (backup_bytes > 0) {
95     input_->BackUp(backup_bytes);
96 
97     // total_bytes_read_ doesn't include overflow_bytes_.
98     total_bytes_read_ -= BufferSize() + buffer_size_after_limit_;
99     buffer_end_ = buffer_;
100     buffer_size_after_limit_ = 0;
101     overflow_bytes_ = 0;
102   }
103 }
104 
RecomputeBufferLimits()105 inline void CodedInputStream::RecomputeBufferLimits() {
106   buffer_end_ += buffer_size_after_limit_;
107   int closest_limit = std::min(current_limit_, total_bytes_limit_);
108   if (closest_limit < total_bytes_read_) {
109     // The limit position is in the current buffer.  We must adjust
110     // the buffer size accordingly.
111     buffer_size_after_limit_ = total_bytes_read_ - closest_limit;
112     buffer_end_ -= buffer_size_after_limit_;
113   } else {
114     buffer_size_after_limit_ = 0;
115   }
116 }
117 
PushLimit(int byte_limit)118 CodedInputStream::Limit CodedInputStream::PushLimit(int byte_limit) {
119   // Current position relative to the beginning of the stream.
120   int current_position = CurrentPosition();
121 
122   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   if (PROTOBUF_PREDICT_TRUE(byte_limit >= 0 &&
128                             byte_limit <= INT_MAX - current_position &&
129                             byte_limit < current_limit_ - current_position)) {
130     current_limit_ = current_position + byte_limit;
131     RecomputeBufferLimits();
132   }
133 
134   return old_limit;
135 }
136 
PopLimit(Limit limit)137 void CodedInputStream::PopLimit(Limit limit) {
138   // The limit passed in is actually the *old* limit, which we returned from
139   // PushLimit().
140   current_limit_ = limit;
141   RecomputeBufferLimits();
142 
143   // We may no longer be at a legitimate message end.  ReadTag() needs to be
144   // called again to find out.
145   legitimate_message_end_ = false;
146 }
147 
148 std::pair<CodedInputStream::Limit, int>
IncrementRecursionDepthAndPushLimit(int byte_limit)149 CodedInputStream::IncrementRecursionDepthAndPushLimit(int byte_limit) {
150   return std::make_pair(PushLimit(byte_limit), --recursion_budget_);
151 }
152 
ReadLengthAndPushLimit()153 CodedInputStream::Limit CodedInputStream::ReadLengthAndPushLimit() {
154   uint32 length;
155   return PushLimit(ReadVarint32(&length) ? length : 0);
156 }
157 
DecrementRecursionDepthAndPopLimit(Limit limit)158 bool CodedInputStream::DecrementRecursionDepthAndPopLimit(Limit limit) {
159   bool result = ConsumedEntireMessage();
160   PopLimit(limit);
161   GOOGLE_DCHECK_LT(recursion_budget_, recursion_limit_);
162   ++recursion_budget_;
163   return result;
164 }
165 
CheckEntireMessageConsumedAndPopLimit(Limit limit)166 bool CodedInputStream::CheckEntireMessageConsumedAndPopLimit(Limit limit) {
167   bool result = ConsumedEntireMessage();
168   PopLimit(limit);
169   return result;
170 }
171 
BytesUntilLimit() const172 int CodedInputStream::BytesUntilLimit() const {
173   if (current_limit_ == INT_MAX) return -1;
174   int current_position = CurrentPosition();
175 
176   return current_limit_ - current_position;
177 }
178 
SetTotalBytesLimit(int total_bytes_limit)179 void CodedInputStream::SetTotalBytesLimit(int total_bytes_limit) {
180   // Make sure the limit isn't already past, since this could confuse other
181   // code.
182   int current_position = CurrentPosition();
183   total_bytes_limit_ = std::max(current_position, total_bytes_limit);
184   RecomputeBufferLimits();
185 }
186 
BytesUntilTotalBytesLimit() const187 int CodedInputStream::BytesUntilTotalBytesLimit() const {
188   if (total_bytes_limit_ == INT_MAX) return -1;
189   return total_bytes_limit_ - CurrentPosition();
190 }
191 
PrintTotalBytesLimitError()192 void CodedInputStream::PrintTotalBytesLimitError() {
193   GOOGLE_LOG(ERROR)
194       << "A protocol message was rejected because it was too "
195          "big (more than "
196       << total_bytes_limit_
197       << " bytes).  To increase the limit (or to disable these "
198          "warnings), see CodedInputStream::SetTotalBytesLimit() "
199          "in third_party/protobuf/src/google/protobuf/io/coded_stream.h.";
200 }
201 
SkipFallback(int count,int original_buffer_size)202 bool CodedInputStream::SkipFallback(int count, int original_buffer_size) {
203   if (buffer_size_after_limit_ > 0) {
204     // We hit a limit inside this buffer.  Advance to the limit and fail.
205     Advance(original_buffer_size);
206     return false;
207   }
208 
209   count -= original_buffer_size;
210   buffer_ = NULL;
211   buffer_end_ = buffer_;
212 
213   // Make sure this skip doesn't try to skip past the current limit.
214   int closest_limit = std::min(current_limit_, total_bytes_limit_);
215   int bytes_until_limit = closest_limit - total_bytes_read_;
216   if (bytes_until_limit < count) {
217     // We hit the limit.  Skip up to it then fail.
218     if (bytes_until_limit > 0) {
219       total_bytes_read_ = closest_limit;
220       input_->Skip(bytes_until_limit);
221     }
222     return false;
223   }
224 
225   if (!input_->Skip(count)) {
226     total_bytes_read_ = input_->ByteCount();
227     return false;
228   }
229   total_bytes_read_ += count;
230   return true;
231 }
232 
GetDirectBufferPointer(const void ** data,int * size)233 bool CodedInputStream::GetDirectBufferPointer(const void** data, int* size) {
234   if (BufferSize() == 0 && !Refresh()) return false;
235 
236   *data = buffer_;
237   *size = BufferSize();
238   return true;
239 }
240 
ReadRaw(void * buffer,int size)241 bool CodedInputStream::ReadRaw(void* buffer, int size) {
242   int current_buffer_size;
243   while ((current_buffer_size = BufferSize()) < size) {
244     // Reading past end of buffer.  Copy what we have, then refresh.
245     memcpy(buffer, buffer_, current_buffer_size);
246     buffer = reinterpret_cast<uint8*>(buffer) + current_buffer_size;
247     size -= current_buffer_size;
248     Advance(current_buffer_size);
249     if (!Refresh()) return false;
250   }
251 
252   memcpy(buffer, buffer_, size);
253   Advance(size);
254 
255   return true;
256 }
257 
ReadString(std::string * buffer,int size)258 bool CodedInputStream::ReadString(std::string* buffer, int size) {
259   if (size < 0) return false;  // security: size is often user-supplied
260 
261   if (BufferSize() >= size) {
262     STLStringResizeUninitialized(buffer, size);
263     std::pair<char*, bool> z = as_string_data(buffer);
264     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       GOOGLE_DCHECK(z.first != NULL);
268       memcpy(z.first, buffer_, size);
269       Advance(size);
270     }
271     return true;
272   }
273 
274   return ReadStringFallback(buffer, size);
275 }
276 
ReadStringFallback(std::string * buffer,int size)277 bool CodedInputStream::ReadStringFallback(std::string* buffer, int size) {
278   if (!buffer->empty()) {
279     buffer->clear();
280   }
281 
282   int closest_limit = std::min(current_limit_, total_bytes_limit_);
283   if (closest_limit != INT_MAX) {
284     int bytes_to_limit = closest_limit - CurrentPosition();
285     if (bytes_to_limit > 0 && size > 0 && size <= bytes_to_limit) {
286       buffer->reserve(size);
287     }
288   }
289 
290   int current_buffer_size;
291   while ((current_buffer_size = BufferSize()) < size) {
292     // Some STL implementations "helpfully" crash on buffer->append(NULL, 0).
293     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       buffer->append(reinterpret_cast<const char*>(buffer_),
297                      current_buffer_size);
298     }
299     size -= current_buffer_size;
300     Advance(current_buffer_size);
301     if (!Refresh()) return false;
302   }
303 
304   buffer->append(reinterpret_cast<const char*>(buffer_), size);
305   Advance(size);
306 
307   return true;
308 }
309 
310 
ReadLittleEndian32Fallback(uint32 * value)311 bool CodedInputStream::ReadLittleEndian32Fallback(uint32* value) {
312   uint8 bytes[sizeof(*value)];
313 
314   const uint8* ptr;
315   if (BufferSize() >= sizeof(*value)) {
316     // Fast path:  Enough bytes in the buffer to read directly.
317     ptr = buffer_;
318     Advance(sizeof(*value));
319   } else {
320     // Slow path:  Had to read past the end of the buffer.
321     if (!ReadRaw(bytes, sizeof(*value))) return false;
322     ptr = bytes;
323   }
324   ReadLittleEndian32FromArray(ptr, value);
325   return true;
326 }
327 
ReadLittleEndian64Fallback(uint64 * value)328 bool CodedInputStream::ReadLittleEndian64Fallback(uint64* value) {
329   uint8 bytes[sizeof(*value)];
330 
331   const uint8* ptr;
332   if (BufferSize() >= sizeof(*value)) {
333     // Fast path:  Enough bytes in the buffer to read directly.
334     ptr = buffer_;
335     Advance(sizeof(*value));
336   } else {
337     // Slow path:  Had to read past the end of the buffer.
338     if (!ReadRaw(bytes, sizeof(*value))) return false;
339     ptr = bytes;
340   }
341   ReadLittleEndian64FromArray(ptr, value);
342   return true;
343 }
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>
DecodeVarint64KnownSize(const uint8 * buffer,uint64 * value)351 const uint8* DecodeVarint64KnownSize(const uint8* buffer, uint64* value) {
352   GOOGLE_DCHECK_GT(N, 0);
353   uint64 result = static_cast<uint64>(buffer[N - 1]) << (7 * (N - 1));
354   for (int i = 0, offset = 0; i < N - 1; i++, offset += 7) {
355     result += static_cast<uint64>(buffer[i] - 0x80) << offset;
356   }
357   *value = result;
358   return buffer + N;
359 }
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);
ReadVarint32FromArray(uint32 first_byte,const uint8 * buffer,uint32 * value)369 inline ::std::pair<bool, const uint8*> ReadVarint32FromArray(
370     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   GOOGLE_DCHECK_EQ(*buffer, first_byte);
374   GOOGLE_DCHECK_EQ(first_byte & 0x80, 0x80) << first_byte;
375   const uint8* ptr = buffer;
376   uint32 b;
377   uint32 result = first_byte - 0x80;
378   ++ptr;  // We just processed the first byte.  Move on to the second.
379   b = *(ptr++);
380   result += b << 7;
381   if (!(b & 0x80)) goto done;
382   result -= 0x80 << 7;
383   b = *(ptr++);
384   result += b << 14;
385   if (!(b & 0x80)) goto done;
386   result -= 0x80 << 14;
387   b = *(ptr++);
388   result += b << 21;
389   if (!(b & 0x80)) goto done;
390   result -= 0x80 << 21;
391   b = *(ptr++);
392   result += b << 28;
393   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   for (int i = 0; i < kMaxVarintBytes - kMaxVarint32Bytes; i++) {
399     b = *(ptr++);
400     if (!(b & 0x80)) goto done;
401   }
402 
403   // We have overrun the maximum size of a varint (10 bytes).  Assume
404   // the data is corrupt.
405   return std::make_pair(false, ptr);
406 
407 done:
408   *value = result;
409   return std::make_pair(true, ptr);
410 }
411 
412 PROTOBUF_ALWAYS_INLINE::std::pair<bool, const uint8*> ReadVarint64FromArray(
413     const uint8* buffer, uint64* value);
ReadVarint64FromArray(const uint8 * buffer,uint64 * value)414 inline ::std::pair<bool, const uint8*> ReadVarint64FromArray(
415     const uint8* buffer, uint64* value) {
416   // Assumes varint64 is at least 2 bytes.
417   GOOGLE_DCHECK_GE(buffer[0], 128);
418 
419   const uint8* next;
420   if (buffer[1] < 128) {
421     next = DecodeVarint64KnownSize<2>(buffer, value);
422   } else if (buffer[2] < 128) {
423     next = DecodeVarint64KnownSize<3>(buffer, value);
424   } else if (buffer[3] < 128) {
425     next = DecodeVarint64KnownSize<4>(buffer, value);
426   } else if (buffer[4] < 128) {
427     next = DecodeVarint64KnownSize<5>(buffer, value);
428   } else if (buffer[5] < 128) {
429     next = DecodeVarint64KnownSize<6>(buffer, value);
430   } else if (buffer[6] < 128) {
431     next = DecodeVarint64KnownSize<7>(buffer, value);
432   } else if (buffer[7] < 128) {
433     next = DecodeVarint64KnownSize<8>(buffer, value);
434   } else if (buffer[8] < 128) {
435     next = DecodeVarint64KnownSize<9>(buffer, value);
436   } else if (buffer[9] < 128) {
437     next = DecodeVarint64KnownSize<10>(buffer, value);
438   } else {
439     // We have overrun the maximum size of a varint (10 bytes). Assume
440     // the data is corrupt.
441     return std::make_pair(false, buffer + 11);
442   }
443 
444   return std::make_pair(true, next);
445 }
446 
447 }  // namespace
448 
ReadVarint32Slow(uint32 * value)449 bool CodedInputStream::ReadVarint32Slow(uint32* value) {
450   // Directly invoke ReadVarint64Fallback, since we already tried to optimize
451   // for one-byte varints.
452   std::pair<uint64, bool> p = ReadVarint64Fallback();
453   *value = static_cast<uint32>(p.first);
454   return p.second;
455 }
456 
ReadVarint32Fallback(uint32 first_byte_or_zero)457 int64 CodedInputStream::ReadVarint32Fallback(uint32 first_byte_or_zero) {
458   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       (buffer_end_ > buffer_ && !(buffer_end_[-1] & 0x80))) {
462     GOOGLE_DCHECK_NE(first_byte_or_zero, 0)
463         << "Caller should provide us with *buffer_ when buffer is non-empty";
464     uint32 temp;
465     ::std::pair<bool, const uint8*> p =
466         ReadVarint32FromArray(first_byte_or_zero, buffer_, &temp);
467     if (!p.first) return -1;
468     buffer_ = p.second;
469     return temp;
470   } 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     uint32 temp;
475     return ReadVarint32Slow(&temp) ? static_cast<int64>(temp) : -1;
476   }
477 }
478 
ReadVarintSizeAsIntSlow()479 int CodedInputStream::ReadVarintSizeAsIntSlow() {
480   // Directly invoke ReadVarint64Fallback, since we already tried to optimize
481   // for one-byte varints.
482   std::pair<uint64, bool> p = ReadVarint64Fallback();
483   if (!p.second || p.first > static_cast<uint64>(INT_MAX)) return -1;
484   return p.first;
485 }
486 
ReadVarintSizeAsIntFallback()487 int CodedInputStream::ReadVarintSizeAsIntFallback() {
488   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       (buffer_end_ > buffer_ && !(buffer_end_[-1] & 0x80))) {
492     uint64 temp;
493     ::std::pair<bool, const uint8*> p = ReadVarint64FromArray(buffer_, &temp);
494     if (!p.first || temp > static_cast<uint64>(INT_MAX)) return -1;
495     buffer_ = p.second;
496     return temp;
497   } 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     return ReadVarintSizeAsIntSlow();
502   }
503 }
504 
ReadTagSlow()505 uint32 CodedInputStream::ReadTagSlow() {
506   if (buffer_ == buffer_end_) {
507     // Call refresh.
508     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       int current_position = total_bytes_read_ - buffer_size_after_limit_;
513       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         legitimate_message_end_ = current_limit_ == total_bytes_limit_;
517       } else {
518         legitimate_message_end_ = true;
519       }
520       return 0;
521     }
522   }
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   uint64 result = 0;
527   if (!ReadVarint64(&result)) return 0;
528   return static_cast<uint32>(result);
529 }
530 
ReadTagFallback(uint32 first_byte_or_zero)531 uint32 CodedInputStream::ReadTagFallback(uint32 first_byte_or_zero) {
532   const int buf_size = BufferSize();
533   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       (buf_size > 0 && !(buffer_end_[-1] & 0x80))) {
537     GOOGLE_DCHECK_EQ(first_byte_or_zero, buffer_[0]);
538     if (first_byte_or_zero == 0) {
539       ++buffer_;
540       return 0;
541     }
542     uint32 tag;
543     ::std::pair<bool, const uint8*> p =
544         ReadVarint32FromArray(first_byte_or_zero, buffer_, &tag);
545     if (!p.first) {
546       return 0;
547     }
548     buffer_ = p.second;
549     return tag;
550   } 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     if ((buf_size == 0) &&
554         ((buffer_size_after_limit_ > 0) ||
555          (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         total_bytes_read_ - buffer_size_after_limit_ < total_bytes_limit_) {
560       // We hit a byte limit.
561       legitimate_message_end_ = true;
562       return 0;
563     }
564     return ReadTagSlow();
565   }
566 }
567 
ReadVarint64Slow(uint64 * value)568 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   uint64 result = 0;
573   int count = 0;
574   uint32 b;
575 
576   do {
577     if (count == kMaxVarintBytes) {
578       *value = 0;
579       return false;
580     }
581     while (buffer_ == buffer_end_) {
582       if (!Refresh()) {
583         *value = 0;
584         return false;
585       }
586     }
587     b = *buffer_;
588     result |= static_cast<uint64>(b & 0x7F) << (7 * count);
589     Advance(1);
590     ++count;
591   } while (b & 0x80);
592 
593   *value = result;
594   return true;
595 }
596 
ReadVarint64Fallback()597 std::pair<uint64, bool> CodedInputStream::ReadVarint64Fallback() {
598   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       (buffer_end_ > buffer_ && !(buffer_end_[-1] & 0x80))) {
602     uint64 temp;
603     ::std::pair<bool, const uint8*> p = ReadVarint64FromArray(buffer_, &temp);
604     if (!p.first) {
605       return std::make_pair(0, false);
606     }
607     buffer_ = p.second;
608     return std::make_pair(temp, true);
609   } else {
610     uint64 temp;
611     bool success = ReadVarint64Slow(&temp);
612     return std::make_pair(temp, success);
613   }
614 }
615 
Refresh()616 bool CodedInputStream::Refresh() {
617   GOOGLE_DCHECK_EQ(0, BufferSize());
618 
619   if (buffer_size_after_limit_ > 0 || overflow_bytes_ > 0 ||
620       total_bytes_read_ == current_limit_) {
621     // We've hit a limit.  Stop.
622     int current_position = total_bytes_read_ - buffer_size_after_limit_;
623 
624     if (current_position >= total_bytes_limit_ &&
625         total_bytes_limit_ != current_limit_) {
626       // Hit total_bytes_limit_.
627       PrintTotalBytesLimitError();
628     }
629 
630     return false;
631   }
632 
633   const void* void_buffer;
634   int buffer_size;
635   if (NextNonEmpty(input_, &void_buffer, &buffer_size)) {
636     buffer_ = reinterpret_cast<const uint8*>(void_buffer);
637     buffer_end_ = buffer_ + buffer_size;
638     GOOGLE_CHECK_GE(buffer_size, 0);
639 
640     if (total_bytes_read_ <= INT_MAX - buffer_size) {
641       total_bytes_read_ += buffer_size;
642     } 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       overflow_bytes_ = total_bytes_read_ - (INT_MAX - buffer_size);
654       buffer_end_ -= overflow_bytes_;
655       total_bytes_read_ = INT_MAX;
656     }
657 
658     RecomputeBufferLimits();
659     return true;
660   } else {
661     buffer_ = NULL;
662     buffer_end_ = NULL;
663     return false;
664   }
665 }
666 
667 // CodedOutputStream =================================================
668 
EnableAliasing(bool enabled)669 void EpsCopyOutputStream::EnableAliasing(bool enabled) {
670   aliasing_enabled_ = enabled && stream_->AllowsAliasing();
671 }
672 
ByteCount(uint8 * ptr) const673 int64 EpsCopyOutputStream::ByteCount(uint8* ptr) const {
674   // Calculate the current offset relative to the end of the stream buffer.
675   int delta = (end_ - ptr) + (buffer_end_ ? 0 : kSlopBytes);
676   return stream_->ByteCount() - delta;
677 }
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)
Flush(uint8 * ptr)682 int EpsCopyOutputStream::Flush(uint8* ptr) {
683   while (buffer_end_ && ptr > end_) {
684     int overrun = ptr - end_;
685     GOOGLE_DCHECK(!had_error_);
686     GOOGLE_DCHECK(overrun <= kSlopBytes);  // NOLINT
687     ptr = Next() + overrun;
688     if (had_error_) return 0;
689   }
690   int s;
691   if (buffer_end_) {
692     std::memcpy(buffer_end_, buffer_, ptr - buffer_);
693     buffer_end_ += ptr - buffer_;
694     s = end_ - ptr;
695   } else {
696     // The stream is writing directly in the ZeroCopyOutputStream buffer.
697     s = end_ + kSlopBytes - ptr;
698     buffer_end_ = ptr;
699   }
700   GOOGLE_DCHECK(s >= 0);  // NOLINT
701   return s;
702 }
703 
Trim(uint8 * ptr)704 uint8* EpsCopyOutputStream::Trim(uint8* ptr) {
705   if (had_error_) return ptr;
706   int s = Flush(ptr);
707   if (s) stream_->BackUp(s);
708   // Reset to initial state (expecting new buffer)
709   buffer_end_ = end_ = buffer_;
710   return buffer_;
711 }
712 
713 
FlushAndResetBuffer(uint8 * ptr)714 uint8* EpsCopyOutputStream::FlushAndResetBuffer(uint8* ptr) {
715   if (had_error_) return buffer_;
716   int s = Flush(ptr);
717   if (had_error_) return buffer_;
718   return SetInitialBuffer(buffer_end_, s);
719 }
720 
Skip(int count,uint8 ** pp)721 bool EpsCopyOutputStream::Skip(int count, uint8** pp) {
722   if (count < 0) return false;
723   if (had_error_) {
724     *pp = buffer_;
725     return false;
726   }
727   int size = Flush(*pp);
728   if (had_error_) {
729     *pp = buffer_;
730     return false;
731   }
732   void* data = buffer_end_;
733   while (count > size) {
734     count -= size;
735     if (!stream_->Next(&data, &size)) {
736       *pp = Error();
737       return false;
738     }
739   }
740   *pp = SetInitialBuffer(static_cast<uint8*>(data) + count, size - count);
741   return true;
742 }
743 
GetDirectBufferPointer(void ** data,int * size,uint8 ** pp)744 bool EpsCopyOutputStream::GetDirectBufferPointer(void** data, int* size,
745                                                  uint8** pp) {
746   if (had_error_) {
747     *pp = buffer_;
748     return false;
749   }
750   *size = Flush(*pp);
751   if (had_error_) {
752     *pp = buffer_;
753     return false;
754   }
755   *data = buffer_end_;
756   while (*size == 0) {
757     if (!stream_->Next(data, size)) {
758       *pp = Error();
759       return false;
760     }
761   }
762   *pp = SetInitialBuffer(*data, *size);
763   return true;
764 }
765 
GetDirectBufferForNBytesAndAdvance(int size,uint8 ** pp)766 uint8* EpsCopyOutputStream::GetDirectBufferForNBytesAndAdvance(int size,
767                                                                uint8** pp) {
768   if (had_error_) {
769     *pp = buffer_;
770     return nullptr;
771   }
772   int s = Flush(*pp);
773   if (had_error_) {
774     *pp = buffer_;
775     return nullptr;
776   }
777   if (s >= size) {
778     auto res = buffer_end_;
779     *pp = SetInitialBuffer(buffer_end_ + size, s - size);
780     return res;
781   } else {
782     *pp = SetInitialBuffer(buffer_end_, s);
783     return nullptr;
784   }
785 }
786 
Next()787 uint8* EpsCopyOutputStream::Next() {
788   GOOGLE_DCHECK(!had_error_);  // NOLINT
789   if (PROTOBUF_PREDICT_FALSE(stream_ == nullptr)) return Error();
790   if (buffer_end_) {
791     // We're in the patch buffer and need to fill up the previous buffer.
792     std::memcpy(buffer_end_, buffer_, end_ - buffer_);
793     uint8* ptr;
794     int size;
795     do {
796       void* data;
797       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         return Error();
801       }
802       ptr = static_cast<uint8*>(data);
803     } while (size == 0);
804     if (PROTOBUF_PREDICT_TRUE(size > kSlopBytes)) {
805       std::memcpy(ptr, end_, kSlopBytes);
806       end_ = ptr + size - kSlopBytes;
807       buffer_end_ = nullptr;
808       return ptr;
809     } else {
810       GOOGLE_DCHECK(size > 0);  // NOLINT
811       // Buffer to small
812       std::memmove(buffer_, end_, kSlopBytes);
813       buffer_end_ = ptr;
814       end_ = buffer_ + size;
815       return buffer_;
816     }
817   } else {
818     std::memcpy(buffer_, end_, kSlopBytes);
819     buffer_end_ = end_;
820     end_ = buffer_ + kSlopBytes;
821     return buffer_;
822   }
823 }
824 
EnsureSpaceFallback(uint8 * ptr)825 uint8* EpsCopyOutputStream::EnsureSpaceFallback(uint8* ptr) {
826   do {
827     if (PROTOBUF_PREDICT_FALSE(had_error_)) return buffer_;
828     int overrun = ptr - end_;
829     GOOGLE_DCHECK(overrun >= 0);           // NOLINT
830     GOOGLE_DCHECK(overrun <= kSlopBytes);  // NOLINT
831     ptr = Next() + overrun;
832   } while (ptr >= end_);
833   GOOGLE_DCHECK(ptr < end_);  // NOLINT
834   return ptr;
835 }
836 
WriteRawFallback(const void * data,int size,uint8 * ptr)837 uint8* EpsCopyOutputStream::WriteRawFallback(const void* data, int size,
838                                              uint8* ptr) {
839   int s = GetSize(ptr);
840   while (s < size) {
841     std::memcpy(ptr, data, s);
842     size -= s;
843     data = static_cast<const uint8*>(data) + s;
844     ptr = EnsureSpaceFallback(ptr + s);
845     s = GetSize(ptr);
846   }
847   std::memcpy(ptr, data, size);
848   return ptr + size;
849 }
850 
WriteAliasedRaw(const void * data,int size,uint8 * ptr)851 uint8* EpsCopyOutputStream::WriteAliasedRaw(const void* data, int size,
852                                             uint8* ptr) {
853   if (size < GetSize(ptr)
854   ) {
855     return WriteRaw(data, size, ptr);
856   } else {
857     ptr = Trim(ptr);
858     if (stream_->WriteAliasedRaw(data, size)) return ptr;
859     return Error();
860   }
861 }
862 
863 #ifndef PROTOBUF_LITTLE_ENDIAN
WriteRawLittleEndian32(const void * data,int size,uint8 * ptr)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 
WriteRawLittleEndian64(const void * data,int size,uint8 * ptr)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 
WriteStringMaybeAliasedOutline(uint32 num,const std::string & s,uint8 * ptr)912 uint8* EpsCopyOutputStream::WriteStringMaybeAliasedOutline(uint32 num,
913                                                            const std::string& s,
914                                                            uint8* ptr) {
915   ptr = EnsureSpace(ptr);
916   uint32 size = s.size();
917   ptr = WriteLengthDelim(num, size, ptr);
918   return WriteRawMaybeAliased(s.data(), size, ptr);
919 }
920 
WriteStringOutline(uint32 num,const std::string & s,uint8 * ptr)921 uint8* EpsCopyOutputStream::WriteStringOutline(uint32 num, const std::string& s,
922                                                uint8* ptr) {
923   ptr = EnsureSpace(ptr);
924   uint32 size = s.size();
925   ptr = WriteLengthDelim(num, size, ptr);
926   return WriteRaw(s.data(), size, ptr);
927 }
928 
929 std::atomic<bool> CodedOutputStream::default_serialization_deterministic_{
930     false};
931 
CodedOutputStream(ZeroCopyOutputStream * stream,bool do_eager_refresh)932 CodedOutputStream::CodedOutputStream(ZeroCopyOutputStream* stream,
933                                      bool do_eager_refresh)
934     : impl_(stream, IsDefaultSerializationDeterministic(), &cur_),
935       start_count_(stream->ByteCount()) {
936   if (do_eager_refresh) {
937     void* data;
938     int size;
939     if (!stream->Next(&data, &size) || size == 0) return;
940     cur_ = impl_.SetInitialBuffer(data, size);
941   }
942 }
943 
~CodedOutputStream()944 CodedOutputStream::~CodedOutputStream() { Trim(); }
945 
946 
WriteStringWithSizeToArray(const std::string & str,uint8 * target)947 uint8* CodedOutputStream::WriteStringWithSizeToArray(const std::string& str,
948                                                      uint8* target) {
949   GOOGLE_DCHECK_LE(str.size(), kuint32max);
950   target = WriteVarint32ToArray(str.size(), target);
951   return WriteStringToArray(str, target);
952 }
953 
954 }  // namespace io
955 }  // namespace protobuf
956 }  // namespace google
957