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