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