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