• 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 }  // namespace
380 
ReadVarint32Slow(uint32 * value)381 bool CodedInputStream::ReadVarint32Slow(uint32* value) {
382   // Directly invoke ReadVarint64Fallback, since we already tried to optimize
383   // for one-byte varints.
384   std::pair<uint64, bool> p = ReadVarint64Fallback();
385   *value = static_cast<uint32>(p.first);
386   return p.second;
387 }
388 
ReadVarint32Fallback(uint32 first_byte_or_zero)389 int64 CodedInputStream::ReadVarint32Fallback(uint32 first_byte_or_zero) {
390   if (BufferSize() >= kMaxVarintBytes ||
391       // Optimization:  We're also safe if the buffer is non-empty and it ends
392       // with a byte that would terminate a varint.
393       (buffer_end_ > buffer_ && !(buffer_end_[-1] & 0x80))) {
394     GOOGLE_DCHECK_NE(first_byte_or_zero, 0)
395         << "Caller should provide us with *buffer_ when buffer is non-empty";
396     uint32 temp;
397     ::std::pair<bool, const uint8*> p =
398           ReadVarint32FromArray(first_byte_or_zero, buffer_, &temp);
399     if (!p.first) return -1;
400     buffer_ = p.second;
401     return temp;
402   } else {
403     // Really slow case: we will incur the cost of an extra function call here,
404     // but moving this out of line reduces the size of this function, which
405     // improves the common case. In micro benchmarks, this is worth about 10-15%
406     uint32 temp;
407     return ReadVarint32Slow(&temp) ? static_cast<int64>(temp) : -1;
408   }
409 }
410 
ReadTagSlow()411 uint32 CodedInputStream::ReadTagSlow() {
412   if (buffer_ == buffer_end_) {
413     // Call refresh.
414     if (!Refresh()) {
415       // Refresh failed.  Make sure that it failed due to EOF, not because
416       // we hit total_bytes_limit_, which, unlike normal limits, is not a
417       // valid place to end a message.
418       int current_position = total_bytes_read_ - buffer_size_after_limit_;
419       if (current_position >= total_bytes_limit_) {
420         // Hit total_bytes_limit_.  But if we also hit the normal limit,
421         // we're still OK.
422         legitimate_message_end_ = current_limit_ == total_bytes_limit_;
423       } else {
424         legitimate_message_end_ = true;
425       }
426       return 0;
427     }
428   }
429 
430   // For the slow path, just do a 64-bit read. Try to optimize for one-byte tags
431   // again, since we have now refreshed the buffer.
432   uint64 result = 0;
433   if (!ReadVarint64(&result)) return 0;
434   return static_cast<uint32>(result);
435 }
436 
ReadTagFallback(uint32 first_byte_or_zero)437 uint32 CodedInputStream::ReadTagFallback(uint32 first_byte_or_zero) {
438   const int buf_size = BufferSize();
439   if (buf_size >= kMaxVarintBytes ||
440       // Optimization:  We're also safe if the buffer is non-empty and it ends
441       // with a byte that would terminate a varint.
442       (buf_size > 0 && !(buffer_end_[-1] & 0x80))) {
443     GOOGLE_DCHECK_EQ(first_byte_or_zero, buffer_[0]);
444     if (first_byte_or_zero == 0) {
445       ++buffer_;
446       return 0;
447     }
448     uint32 tag;
449     ::std::pair<bool, const uint8*> p =
450         ReadVarint32FromArray(first_byte_or_zero, buffer_, &tag);
451     if (!p.first) {
452       return 0;
453     }
454     buffer_ = p.second;
455     return tag;
456   } else {
457     // We are commonly at a limit when attempting to read tags. Try to quickly
458     // detect this case without making another function call.
459     if ((buf_size == 0) &&
460         ((buffer_size_after_limit_ > 0) ||
461          (total_bytes_read_ == current_limit_)) &&
462         // Make sure that the limit we hit is not total_bytes_limit_, since
463         // in that case we still need to call Refresh() so that it prints an
464         // error.
465         total_bytes_read_ - buffer_size_after_limit_ < total_bytes_limit_) {
466       // We hit a byte limit.
467       legitimate_message_end_ = true;
468       return 0;
469     }
470     return ReadTagSlow();
471   }
472 }
473 
ReadVarint64Slow(uint64 * value)474 bool CodedInputStream::ReadVarint64Slow(uint64* value) {
475   // Slow path:  This read might cross the end of the buffer, so we
476   // need to check and refresh the buffer if and when it does.
477 
478   uint64 result = 0;
479   int count = 0;
480   uint32 b;
481 
482   do {
483     if (count == kMaxVarintBytes) return false;
484     while (buffer_ == buffer_end_) {
485       if (!Refresh()) return false;
486     }
487     b = *buffer_;
488     result |= static_cast<uint64>(b & 0x7F) << (7 * count);
489     Advance(1);
490     ++count;
491   } while (b & 0x80);
492 
493   *value = result;
494   return true;
495 }
496 
ReadVarint64Fallback()497 std::pair<uint64, bool> CodedInputStream::ReadVarint64Fallback() {
498   if (BufferSize() >= kMaxVarintBytes ||
499       // Optimization:  We're also safe if the buffer is non-empty and it ends
500       // with a byte that would terminate a varint.
501       (buffer_end_ > buffer_ && !(buffer_end_[-1] & 0x80))) {
502     // Fast path:  We have enough bytes left in the buffer to guarantee that
503     // this read won't cross the end, so we can skip the checks.
504 
505     const uint8* ptr = buffer_;
506     uint32 b;
507 
508     // Splitting into 32-bit pieces gives better performance on 32-bit
509     // processors.
510     uint32 part0 = 0, part1 = 0, part2 = 0;
511 
512     b = *(ptr++); part0  = b      ; if (!(b & 0x80)) goto done;
513     part0 -= 0x80;
514     b = *(ptr++); part0 += b <<  7; if (!(b & 0x80)) goto done;
515     part0 -= 0x80 << 7;
516     b = *(ptr++); part0 += b << 14; if (!(b & 0x80)) goto done;
517     part0 -= 0x80 << 14;
518     b = *(ptr++); part0 += b << 21; if (!(b & 0x80)) goto done;
519     part0 -= 0x80 << 21;
520     b = *(ptr++); part1  = b      ; if (!(b & 0x80)) goto done;
521     part1 -= 0x80;
522     b = *(ptr++); part1 += b <<  7; if (!(b & 0x80)) goto done;
523     part1 -= 0x80 << 7;
524     b = *(ptr++); part1 += b << 14; if (!(b & 0x80)) goto done;
525     part1 -= 0x80 << 14;
526     b = *(ptr++); part1 += b << 21; if (!(b & 0x80)) goto done;
527     part1 -= 0x80 << 21;
528     b = *(ptr++); part2  = b      ; if (!(b & 0x80)) goto done;
529     part2 -= 0x80;
530     b = *(ptr++); part2 += b <<  7; if (!(b & 0x80)) goto done;
531     // "part2 -= 0x80 << 7" is irrelevant because (0x80 << 7) << 56 is 0.
532 
533     // We have overrun the maximum size of a varint (10 bytes).  The data
534     // must be corrupt.
535     return std::make_pair(0, false);
536 
537    done:
538     Advance(ptr - buffer_);
539     return std::make_pair((static_cast<uint64>(part0)) |
540                               (static_cast<uint64>(part1) << 28) |
541                               (static_cast<uint64>(part2) << 56),
542                           true);
543   } else {
544     uint64 temp;
545     bool success = ReadVarint64Slow(&temp);
546     return std::make_pair(temp, success);
547   }
548 }
549 
Refresh()550 bool CodedInputStream::Refresh() {
551   GOOGLE_DCHECK_EQ(0, BufferSize());
552 
553   if (buffer_size_after_limit_ > 0 || overflow_bytes_ > 0 ||
554       total_bytes_read_ == current_limit_) {
555     // We've hit a limit.  Stop.
556     int current_position = total_bytes_read_ - buffer_size_after_limit_;
557 
558     if (current_position >= total_bytes_limit_ &&
559         total_bytes_limit_ != current_limit_) {
560       // Hit total_bytes_limit_.
561       PrintTotalBytesLimitError();
562     }
563 
564     return false;
565   }
566 
567   if (total_bytes_warning_threshold_ >= 0 &&
568       total_bytes_read_ >= total_bytes_warning_threshold_) {
569       GOOGLE_LOG(WARNING) << "Reading dangerously large protocol message.  If the "
570                       "message turns out to be larger than "
571                    << total_bytes_limit_ << " bytes, parsing will be halted "
572                       "for security reasons.  To increase the limit (or to "
573                       "disable these warnings), see "
574                       "CodedInputStream::SetTotalBytesLimit() in "
575                       "google/protobuf/io/coded_stream.h.";
576 
577     // Don't warn again for this stream, and print total size at the end.
578     total_bytes_warning_threshold_ = -2;
579   }
580 
581   const void* void_buffer;
582   int buffer_size;
583   if (NextNonEmpty(input_, &void_buffer, &buffer_size)) {
584     buffer_ = reinterpret_cast<const uint8*>(void_buffer);
585     buffer_end_ = buffer_ + buffer_size;
586     GOOGLE_CHECK_GE(buffer_size, 0);
587 
588     if (total_bytes_read_ <= INT_MAX - buffer_size) {
589       total_bytes_read_ += buffer_size;
590     } else {
591       // Overflow.  Reset buffer_end_ to not include the bytes beyond INT_MAX.
592       // We can't get that far anyway, because total_bytes_limit_ is guaranteed
593       // to be less than it.  We need to keep track of the number of bytes
594       // we discarded, though, so that we can call input_->BackUp() to back
595       // up over them on destruction.
596 
597       // The following line is equivalent to:
598       //   overflow_bytes_ = total_bytes_read_ + buffer_size - INT_MAX;
599       // except that it avoids overflows.  Signed integer overflow has
600       // undefined results according to the C standard.
601       overflow_bytes_ = total_bytes_read_ - (INT_MAX - buffer_size);
602       buffer_end_ -= overflow_bytes_;
603       total_bytes_read_ = INT_MAX;
604     }
605 
606     RecomputeBufferLimits();
607     return true;
608   } else {
609     buffer_ = NULL;
610     buffer_end_ = NULL;
611     return false;
612   }
613 }
614 
615 // CodedOutputStream =================================================
616 
CodedOutputStream(ZeroCopyOutputStream * output)617 CodedOutputStream::CodedOutputStream(ZeroCopyOutputStream* output)
618   : output_(output),
619     buffer_(NULL),
620     buffer_size_(0),
621     total_bytes_(0),
622     had_error_(false),
623     aliasing_enabled_(false) {
624   // Eagerly Refresh() so buffer space is immediately available.
625   Refresh();
626   // The Refresh() may have failed. If the client doesn't write any data,
627   // though, don't consider this an error. If the client does write data, then
628   // another Refresh() will be attempted and it will set the error once again.
629   had_error_ = false;
630 }
631 
CodedOutputStream(ZeroCopyOutputStream * output,bool do_eager_refresh)632 CodedOutputStream::CodedOutputStream(ZeroCopyOutputStream* output,
633                                      bool do_eager_refresh)
634   : output_(output),
635     buffer_(NULL),
636     buffer_size_(0),
637     total_bytes_(0),
638     had_error_(false),
639     aliasing_enabled_(false) {
640   if (do_eager_refresh) {
641     // Eagerly Refresh() so buffer space is immediately available.
642     Refresh();
643     // The Refresh() may have failed. If the client doesn't write any data,
644     // though, don't consider this an error. If the client does write data, then
645     // another Refresh() will be attempted and it will set the error once again.
646     had_error_ = false;
647   }
648 }
649 
~CodedOutputStream()650 CodedOutputStream::~CodedOutputStream() {
651   Trim();
652 }
653 
Trim()654 void CodedOutputStream::Trim() {
655   if (buffer_size_ > 0) {
656     output_->BackUp(buffer_size_);
657     total_bytes_ -= buffer_size_;
658     buffer_size_ = 0;
659     buffer_ = NULL;
660   }
661 }
662 
Skip(int count)663 bool CodedOutputStream::Skip(int count) {
664   if (count < 0) return false;
665 
666   while (count > buffer_size_) {
667     count -= buffer_size_;
668     if (!Refresh()) return false;
669   }
670 
671   Advance(count);
672   return true;
673 }
674 
GetDirectBufferPointer(void ** data,int * size)675 bool CodedOutputStream::GetDirectBufferPointer(void** data, int* size) {
676   if (buffer_size_ == 0 && !Refresh()) return false;
677 
678   *data = buffer_;
679   *size = buffer_size_;
680   return true;
681 }
682 
WriteRaw(const void * data,int size)683 void CodedOutputStream::WriteRaw(const void* data, int size) {
684   while (buffer_size_ < size) {
685     memcpy(buffer_, data, buffer_size_);
686     size -= buffer_size_;
687     data = reinterpret_cast<const uint8*>(data) + buffer_size_;
688     if (!Refresh()) return;
689   }
690 
691   memcpy(buffer_, data, size);
692   Advance(size);
693 }
694 
WriteRawToArray(const void * data,int size,uint8 * target)695 uint8* CodedOutputStream::WriteRawToArray(
696     const void* data, int size, uint8* target) {
697   memcpy(target, data, size);
698   return target + size;
699 }
700 
701 
WriteAliasedRaw(const void * data,int size)702 void CodedOutputStream::WriteAliasedRaw(const void* data, int size) {
703   if (size < buffer_size_
704       ) {
705     WriteRaw(data, size);
706   } else {
707     Trim();
708 
709     total_bytes_ += size;
710     had_error_ |= !output_->WriteAliasedRaw(data, size);
711   }
712 }
713 
WriteLittleEndian32(uint32 value)714 void CodedOutputStream::WriteLittleEndian32(uint32 value) {
715   uint8 bytes[sizeof(value)];
716 
717   bool use_fast = buffer_size_ >= sizeof(value);
718   uint8* ptr = use_fast ? buffer_ : bytes;
719 
720   WriteLittleEndian32ToArray(value, ptr);
721 
722   if (use_fast) {
723     Advance(sizeof(value));
724   } else {
725     WriteRaw(bytes, sizeof(value));
726   }
727 }
728 
WriteLittleEndian64(uint64 value)729 void CodedOutputStream::WriteLittleEndian64(uint64 value) {
730   uint8 bytes[sizeof(value)];
731 
732   bool use_fast = buffer_size_ >= sizeof(value);
733   uint8* ptr = use_fast ? buffer_ : bytes;
734 
735   WriteLittleEndian64ToArray(value, ptr);
736 
737   if (use_fast) {
738     Advance(sizeof(value));
739   } else {
740     WriteRaw(bytes, sizeof(value));
741   }
742 }
743 
WriteVarint32SlowPath(uint32 value)744 void CodedOutputStream::WriteVarint32SlowPath(uint32 value) {
745   uint8 bytes[kMaxVarint32Bytes];
746   uint8* target = &bytes[0];
747   uint8* end = WriteVarint32ToArray(value, target);
748   int size = end - target;
749   WriteRaw(bytes, size);
750 }
751 
WriteVarint64ToArrayInline(uint64 value,uint8 * target)752 inline uint8* CodedOutputStream::WriteVarint64ToArrayInline(
753     uint64 value, uint8* target) {
754   // Splitting into 32-bit pieces gives better performance on 32-bit
755   // processors.
756   uint32 part0 = static_cast<uint32>(value      );
757   uint32 part1 = static_cast<uint32>(value >> 28);
758   uint32 part2 = static_cast<uint32>(value >> 56);
759 
760   int size;
761 
762   // Here we can't really optimize for small numbers, since the value is
763   // split into three parts.  Cheking for numbers < 128, for instance,
764   // would require three comparisons, since you'd have to make sure part1
765   // and part2 are zero.  However, if the caller is using 64-bit integers,
766   // it is likely that they expect the numbers to often be very large, so
767   // we probably don't want to optimize for small numbers anyway.  Thus,
768   // we end up with a hardcoded binary search tree...
769   if (part2 == 0) {
770     if (part1 == 0) {
771       if (part0 < (1 << 14)) {
772         if (part0 < (1 << 7)) {
773           size = 1; goto size1;
774         } else {
775           size = 2; goto size2;
776         }
777       } else {
778         if (part0 < (1 << 21)) {
779           size = 3; goto size3;
780         } else {
781           size = 4; goto size4;
782         }
783       }
784     } else {
785       if (part1 < (1 << 14)) {
786         if (part1 < (1 << 7)) {
787           size = 5; goto size5;
788         } else {
789           size = 6; goto size6;
790         }
791       } else {
792         if (part1 < (1 << 21)) {
793           size = 7; goto size7;
794         } else {
795           size = 8; goto size8;
796         }
797       }
798     }
799   } else {
800     if (part2 < (1 << 7)) {
801       size = 9; goto size9;
802     } else {
803       size = 10; goto size10;
804     }
805   }
806 
807   GOOGLE_LOG(FATAL) << "Can't get here.";
808 
809   size10: target[9] = static_cast<uint8>((part2 >>  7) | 0x80);
810   size9 : target[8] = static_cast<uint8>((part2      ) | 0x80);
811   size8 : target[7] = static_cast<uint8>((part1 >> 21) | 0x80);
812   size7 : target[6] = static_cast<uint8>((part1 >> 14) | 0x80);
813   size6 : target[5] = static_cast<uint8>((part1 >>  7) | 0x80);
814   size5 : target[4] = static_cast<uint8>((part1      ) | 0x80);
815   size4 : target[3] = static_cast<uint8>((part0 >> 21) | 0x80);
816   size3 : target[2] = static_cast<uint8>((part0 >> 14) | 0x80);
817   size2 : target[1] = static_cast<uint8>((part0 >>  7) | 0x80);
818   size1 : target[0] = static_cast<uint8>((part0      ) | 0x80);
819 
820   target[size-1] &= 0x7F;
821   return target + size;
822 }
823 
WriteVarint64(uint64 value)824 void CodedOutputStream::WriteVarint64(uint64 value) {
825   if (buffer_size_ >= kMaxVarintBytes) {
826     // Fast path:  We have enough bytes left in the buffer to guarantee that
827     // this write won't cross the end, so we can skip the checks.
828     uint8* target = buffer_;
829 
830     uint8* end = WriteVarint64ToArrayInline(value, target);
831     int size = end - target;
832     Advance(size);
833   } else {
834     // Slow path:  This write might cross the end of the buffer, so we
835     // compose the bytes first then use WriteRaw().
836     uint8 bytes[kMaxVarintBytes];
837     int size = 0;
838     while (value > 0x7F) {
839       bytes[size++] = (static_cast<uint8>(value) & 0x7F) | 0x80;
840       value >>= 7;
841     }
842     bytes[size++] = static_cast<uint8>(value) & 0x7F;
843     WriteRaw(bytes, size);
844   }
845 }
846 
WriteVarint64ToArray(uint64 value,uint8 * target)847 uint8* CodedOutputStream::WriteVarint64ToArray(
848     uint64 value, uint8* target) {
849   return WriteVarint64ToArrayInline(value, target);
850 }
851 
Refresh()852 bool CodedOutputStream::Refresh() {
853   void* void_buffer;
854   if (output_->Next(&void_buffer, &buffer_size_)) {
855     buffer_ = reinterpret_cast<uint8*>(void_buffer);
856     total_bytes_ += buffer_size_;
857     return true;
858   } else {
859     buffer_ = NULL;
860     buffer_size_ = 0;
861     had_error_ = true;
862     return false;
863   }
864 }
865 
VarintSize32Fallback(uint32 value)866 int CodedOutputStream::VarintSize32Fallback(uint32 value) {
867   if (value < (1 << 7)) {
868     return 1;
869   } else if (value < (1 << 14)) {
870     return 2;
871   } else if (value < (1 << 21)) {
872     return 3;
873   } else if (value < (1 << 28)) {
874     return 4;
875   } else {
876     return 5;
877   }
878 }
879 
VarintSize64(uint64 value)880 int CodedOutputStream::VarintSize64(uint64 value) {
881   if (value < (1ull << 35)) {
882     if (value < (1ull << 7)) {
883       return 1;
884     } else if (value < (1ull << 14)) {
885       return 2;
886     } else if (value < (1ull << 21)) {
887       return 3;
888     } else if (value < (1ull << 28)) {
889       return 4;
890     } else {
891       return 5;
892     }
893   } else {
894     if (value < (1ull << 42)) {
895       return 6;
896     } else if (value < (1ull << 49)) {
897       return 7;
898     } else if (value < (1ull << 56)) {
899       return 8;
900     } else if (value < (1ull << 63)) {
901       return 9;
902     } else {
903       return 10;
904     }
905   }
906 }
907 
WriteStringWithSizeToArray(const string & str,uint8 * target)908 uint8* CodedOutputStream::WriteStringWithSizeToArray(const string& str,
909                                                      uint8* target) {
910   GOOGLE_DCHECK_LE(str.size(), kuint32max);
911   target = WriteVarint32ToArray(str.size(), target);
912   return WriteStringToArray(str, target);
913 }
914 
915 }  // namespace io
916 }  // namespace protobuf
917 }  // namespace google
918