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