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