Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(93)

Side by Side Diff: third_party/protobuf/src/google/protobuf/io/coded_stream.cc

Issue 21208003: Update protobuf to r428, part 1. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 7 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Protocol Buffers - Google's data interchange format 1 // Protocol Buffers - Google's data interchange format
2 // Copyright 2008 Google Inc. All rights reserved. 2 // Copyright 2008 Google Inc. All rights reserved.
3 // http://code.google.com/p/protobuf/ 3 // http://code.google.com/p/protobuf/
4 // 4 //
5 // Redistribution and use in source and binary forms, with or without 5 // Redistribution and use in source and binary forms, with or without
6 // modification, are permitted provided that the following conditions are 6 // modification, are permitted provided that the following conditions are
7 // met: 7 // met:
8 // 8 //
9 // * Redistributions of source code must retain the above copyright 9 // * Redistributions of source code must retain the above copyright
10 // notice, this list of conditions and the following disclaimer. 10 // notice, this list of conditions and the following disclaimer.
(...skipping 25 matching lines...) Expand all
36 // of small values (especially varints) as fast as possible. In 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 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 38 // will not cross the end of the buffer, since we can avoid a lot
39 // of branching in this case. 39 // of branching in this case.
40 40
41 #include <google/protobuf/io/coded_stream_inl.h> 41 #include <google/protobuf/io/coded_stream_inl.h>
42 #include <algorithm> 42 #include <algorithm>
43 #include <limits.h> 43 #include <limits.h>
44 #include <google/protobuf/io/zero_copy_stream.h> 44 #include <google/protobuf/io/zero_copy_stream.h>
45 #include <google/protobuf/stubs/common.h> 45 #include <google/protobuf/stubs/common.h>
46 #include <google/protobuf/stubs/stl_util-inl.h> 46 #include <google/protobuf/stubs/stl_util.h>
47 47
48 48
49 namespace google { 49 namespace google {
50 namespace protobuf { 50 namespace protobuf {
51 namespace io { 51 namespace io {
52 52
53 namespace { 53 namespace {
54 54
55 static const int kMaxVarintBytes = 10; 55 static const int kMaxVarintBytes = 10;
56 static const int kMaxVarint32Bytes = 5; 56 static const int kMaxVarint32Bytes = 5;
57 57
58 58
59 inline bool NextNonEmpty(ZeroCopyInputStream* input, 59 inline bool NextNonEmpty(ZeroCopyInputStream* input,
60 const void** data, int* size) { 60 const void** data, int* size) {
61 bool success; 61 bool success;
62 do { 62 do {
63 success = input->Next(data, size); 63 success = input->Next(data, size);
64 } while (success && *size == 0); 64 } while (success && *size == 0);
65 return success; 65 return success;
66 } 66 }
67 67
68 } // namespace 68 } // namespace
69 69
70 // CodedInputStream ================================================== 70 // CodedInputStream ==================================================
71 71
72 CodedInputStream::~CodedInputStream() {
73 if (input_ != NULL) {
74 BackUpInputToCurrentPosition();
75 }
76
77 if (total_bytes_warning_threshold_ == -2) {
78 GOOGLE_LOG(WARNING) << "The total number of bytes read was " << total_bytes_ read_;
79 }
80 }
81
82 // Static.
83 int CodedInputStream::default_recursion_limit_ = 100;
84
72 85
73 void CodedInputStream::BackUpInputToCurrentPosition() { 86 void CodedInputStream::BackUpInputToCurrentPosition() {
74 int backup_bytes = BufferSize() + buffer_size_after_limit_ + overflow_bytes_; 87 int backup_bytes = BufferSize() + buffer_size_after_limit_ + overflow_bytes_;
75 if (backup_bytes > 0) { 88 if (backup_bytes > 0) {
76 input_->BackUp(backup_bytes); 89 input_->BackUp(backup_bytes);
77 90
78 // total_bytes_read_ doesn't include overflow_bytes_. 91 // total_bytes_read_ doesn't include overflow_bytes_.
79 total_bytes_read_ -= BufferSize() + buffer_size_after_limit_; 92 total_bytes_read_ -= BufferSize() + buffer_size_after_limit_;
80 buffer_end_ = buffer_; 93 buffer_end_ = buffer_;
81 buffer_size_after_limit_ = 0; 94 buffer_size_after_limit_ = 0;
82 overflow_bytes_ = 0; 95 overflow_bytes_ = 0;
83 } 96 }
84 } 97 }
85 98
86 inline void CodedInputStream::RecomputeBufferLimits() { 99 inline void CodedInputStream::RecomputeBufferLimits() {
87 buffer_end_ += buffer_size_after_limit_; 100 buffer_end_ += buffer_size_after_limit_;
88 int closest_limit = min(current_limit_, total_bytes_limit_); 101 int closest_limit = min(current_limit_, total_bytes_limit_);
89 if (closest_limit < total_bytes_read_) { 102 if (closest_limit < total_bytes_read_) {
90 // The limit position is in the current buffer. We must adjust 103 // The limit position is in the current buffer. We must adjust
91 // the buffer size accordingly. 104 // the buffer size accordingly.
92 buffer_size_after_limit_ = total_bytes_read_ - closest_limit; 105 buffer_size_after_limit_ = total_bytes_read_ - closest_limit;
93 buffer_end_ -= buffer_size_after_limit_; 106 buffer_end_ -= buffer_size_after_limit_;
94 } else { 107 } else {
95 buffer_size_after_limit_ = 0; 108 buffer_size_after_limit_ = 0;
96 } 109 }
97 } 110 }
98 111
99 CodedInputStream::Limit CodedInputStream::PushLimit(int byte_limit) { 112 CodedInputStream::Limit CodedInputStream::PushLimit(int byte_limit) {
100 // Current position relative to the beginning of the stream. 113 // Current position relative to the beginning of the stream.
101 int current_position = total_bytes_read_ - 114 int current_position = CurrentPosition();
102 (BufferSize() + buffer_size_after_limit_);
103 115
104 Limit old_limit = current_limit_; 116 Limit old_limit = current_limit_;
105 117
106 // security: byte_limit is possibly evil, so check for negative values 118 // security: byte_limit is possibly evil, so check for negative values
107 // and overflow. 119 // and overflow.
108 if (byte_limit >= 0 && 120 if (byte_limit >= 0 &&
109 byte_limit <= INT_MAX - current_position) { 121 byte_limit <= INT_MAX - current_position) {
110 current_limit_ = current_position + byte_limit; 122 current_limit_ = current_position + byte_limit;
111 } else { 123 } else {
112 // Negative or overflow. 124 // Negative or overflow.
(...skipping 13 matching lines...) Expand all
126 // The limit passed in is actually the *old* limit, which we returned from 138 // The limit passed in is actually the *old* limit, which we returned from
127 // PushLimit(). 139 // PushLimit().
128 current_limit_ = limit; 140 current_limit_ = limit;
129 RecomputeBufferLimits(); 141 RecomputeBufferLimits();
130 142
131 // We may no longer be at a legitimate message end. ReadTag() needs to be 143 // We may no longer be at a legitimate message end. ReadTag() needs to be
132 // called again to find out. 144 // called again to find out.
133 legitimate_message_end_ = false; 145 legitimate_message_end_ = false;
134 } 146 }
135 147
136 int CodedInputStream::BytesUntilLimit() { 148 int CodedInputStream::BytesUntilLimit() const {
137 if (current_limit_ == INT_MAX) return -1; 149 if (current_limit_ == INT_MAX) return -1;
138 int current_position = total_bytes_read_ - 150 int current_position = CurrentPosition();
139 (BufferSize() + buffer_size_after_limit_);
140 151
141 return current_limit_ - current_position; 152 return current_limit_ - current_position;
142 } 153 }
143 154
144 void CodedInputStream::SetTotalBytesLimit( 155 void CodedInputStream::SetTotalBytesLimit(
145 int total_bytes_limit, int warning_threshold) { 156 int total_bytes_limit, int warning_threshold) {
146 // Make sure the limit isn't already past, since this could confuse other 157 // Make sure the limit isn't already past, since this could confuse other
147 // code. 158 // code.
148 int current_position = total_bytes_read_ - 159 int current_position = CurrentPosition();
149 (BufferSize() + buffer_size_after_limit_);
150 total_bytes_limit_ = max(current_position, total_bytes_limit); 160 total_bytes_limit_ = max(current_position, total_bytes_limit);
151 total_bytes_warning_threshold_ = warning_threshold; 161 if (warning_threshold >= 0) {
162 total_bytes_warning_threshold_ = warning_threshold;
163 } else {
164 // warning_threshold is negative
165 total_bytes_warning_threshold_ = -1;
166 }
152 RecomputeBufferLimits(); 167 RecomputeBufferLimits();
153 } 168 }
154 169
155 void CodedInputStream::PrintTotalBytesLimitError() { 170 void CodedInputStream::PrintTotalBytesLimitError() {
156 GOOGLE_LOG(ERROR) << "A protocol message was rejected because it was too " 171 GOOGLE_LOG(ERROR) << "A protocol message was rejected because it was too "
157 "big (more than " << total_bytes_limit_ 172 "big (more than " << total_bytes_limit_
158 << " bytes). To increase the limit (or to disable these " 173 << " bytes). To increase the limit (or to disable these "
159 "warnings), see CodedInputStream::SetTotalBytesLimit() " 174 "warnings), see CodedInputStream::SetTotalBytesLimit() "
160 "in google/protobuf/io/coded_stream.h."; 175 "in google/protobuf/io/coded_stream.h.";
161 } 176 }
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after
361 legitimate_message_end_ = current_limit_ == total_bytes_limit_; 376 legitimate_message_end_ = current_limit_ == total_bytes_limit_;
362 } else { 377 } else {
363 legitimate_message_end_ = true; 378 legitimate_message_end_ = true;
364 } 379 }
365 return 0; 380 return 0;
366 } 381 }
367 } 382 }
368 383
369 // For the slow path, just do a 64-bit read. Try to optimize for one-byte tags 384 // For the slow path, just do a 64-bit read. Try to optimize for one-byte tags
370 // again, since we have now refreshed the buffer. 385 // again, since we have now refreshed the buffer.
371 uint64 result; 386 uint64 result = 0;
372 if (!ReadVarint64(&result)) return 0; 387 if (!ReadVarint64(&result)) return 0;
373 return static_cast<uint32>(result); 388 return static_cast<uint32>(result);
374 } 389 }
375 390
376 uint32 CodedInputStream::ReadTagFallback() { 391 uint32 CodedInputStream::ReadTagFallback() {
377 if (BufferSize() >= kMaxVarintBytes || 392 const int buf_size = BufferSize();
393 if (buf_size >= kMaxVarintBytes ||
378 // Optimization: If the varint ends at exactly the end of the buffer, 394 // Optimization: If the varint ends at exactly the end of the buffer,
379 // we can detect that and still use the fast path. 395 // we can detect that and still use the fast path.
380 (buffer_end_ > buffer_ && !(buffer_end_[-1] & 0x80))) { 396 (buf_size > 0 && !(buffer_end_[-1] & 0x80))) {
381 uint32 tag; 397 uint32 tag;
382 const uint8* end = ReadVarint32FromArray(buffer_, &tag); 398 const uint8* end = ReadVarint32FromArray(buffer_, &tag);
383 if (end == NULL) { 399 if (end == NULL) {
384 return 0; 400 return 0;
385 } 401 }
386 buffer_ = end; 402 buffer_ = end;
387 return tag; 403 return tag;
388 } else { 404 } else {
389 // We are commonly at a limit when attempting to read tags. Try to quickly 405 // We are commonly at a limit when attempting to read tags. Try to quickly
390 // detect this case without making another function call. 406 // detect this case without making another function call.
391 if (buffer_ == buffer_end_ && buffer_size_after_limit_ > 0 && 407 if ((buf_size == 0) &&
408 ((buffer_size_after_limit_ > 0) ||
409 (total_bytes_read_ == current_limit_)) &&
392 // Make sure that the limit we hit is not total_bytes_limit_, since 410 // Make sure that the limit we hit is not total_bytes_limit_, since
393 // in that case we still need to call Refresh() so that it prints an 411 // in that case we still need to call Refresh() so that it prints an
394 // error. 412 // error.
395 total_bytes_read_ - buffer_size_after_limit_ < total_bytes_limit_) { 413 total_bytes_read_ - buffer_size_after_limit_ < total_bytes_limit_) {
396 // We hit a byte limit. 414 // We hit a byte limit.
397 legitimate_message_end_ = true; 415 legitimate_message_end_ = true;
398 return 0; 416 return 0;
399 } 417 }
400 return ReadTagSlow(); 418 return ReadTagSlow();
401 } 419 }
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
485 if (total_bytes_warning_threshold_ >= 0 && 503 if (total_bytes_warning_threshold_ >= 0 &&
486 total_bytes_read_ >= total_bytes_warning_threshold_) { 504 total_bytes_read_ >= total_bytes_warning_threshold_) {
487 GOOGLE_LOG(WARNING) << "Reading dangerously large protocol message. If th e " 505 GOOGLE_LOG(WARNING) << "Reading dangerously large protocol message. If th e "
488 "message turns out to be larger than " 506 "message turns out to be larger than "
489 << total_bytes_limit_ << " bytes, parsing will be halted " 507 << total_bytes_limit_ << " bytes, parsing will be halted "
490 "for security reasons. To increase the limit (or to " 508 "for security reasons. To increase the limit (or to "
491 "disable these warnings), see " 509 "disable these warnings), see "
492 "CodedInputStream::SetTotalBytesLimit() in " 510 "CodedInputStream::SetTotalBytesLimit() in "
493 "google/protobuf/io/coded_stream.h."; 511 "google/protobuf/io/coded_stream.h.";
494 512
495 // Don't warn again for this stream. 513 // Don't warn again for this stream, and print total size at the end.
496 total_bytes_warning_threshold_ = -1; 514 total_bytes_warning_threshold_ = -2;
497 } 515 }
498 516
499 const void* void_buffer; 517 const void* void_buffer;
500 int buffer_size; 518 int buffer_size;
501 if (NextNonEmpty(input_, &void_buffer, &buffer_size)) { 519 if (NextNonEmpty(input_, &void_buffer, &buffer_size)) {
502 buffer_ = reinterpret_cast<const uint8*>(void_buffer); 520 buffer_ = reinterpret_cast<const uint8*>(void_buffer);
503 buffer_end_ = buffer_ + buffer_size; 521 buffer_end_ = buffer_ + buffer_size;
504 GOOGLE_CHECK_GE(buffer_size, 0); 522 GOOGLE_CHECK_GE(buffer_size, 0);
505 523
506 if (total_bytes_read_ <= INT_MAX - buffer_size) { 524 if (total_bytes_read_ <= INT_MAX - buffer_size) {
(...skipping 323 matching lines...) Expand 10 before | Expand all | Expand 10 after
830 return 9; 848 return 9;
831 } else { 849 } else {
832 return 10; 850 return 10;
833 } 851 }
834 } 852 }
835 } 853 }
836 854
837 } // namespace io 855 } // namespace io
838 } // namespace protobuf 856 } // namespace protobuf
839 } // namespace google 857 } // namespace google
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698