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