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