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