diff options
Diffstat (limited to 'src/google/protobuf/io/coded_stream.cc')
-rw-r--r-- | src/google/protobuf/io/coded_stream.cc | 90 |
1 files changed, 21 insertions, 69 deletions
diff --git a/src/google/protobuf/io/coded_stream.cc b/src/google/protobuf/io/coded_stream.cc index 3c2e0fbd..0851ff0c 100644 --- a/src/google/protobuf/io/coded_stream.cc +++ b/src/google/protobuf/io/coded_stream.cc @@ -76,10 +76,6 @@ CodedInputStream::~CodedInputStream() { if (input_ != NULL) { BackUpInputToCurrentPosition(); } - - if (total_bytes_warning_threshold_ == -2) { - GOOGLE_LOG(WARNING) << "The total number of bytes read was " << total_bytes_read_; - } } // Static. @@ -123,21 +119,15 @@ CodedInputStream::Limit CodedInputStream::PushLimit(int byte_limit) { Limit old_limit = current_limit_; // security: byte_limit is possibly evil, so check for negative values - // and overflow. - if (byte_limit >= 0 && - byte_limit <= INT_MAX - current_position) { + // and overflow. Also check that the new requested limit is before the + // previous limit; otherwise we continue to enforce the previous limit. + if (GOOGLE_PREDICT_TRUE(byte_limit >= 0 && + byte_limit <= INT_MAX - current_position && + byte_limit < current_limit_ - current_position)) { current_limit_ = current_position + byte_limit; - } else { - // Negative or overflow. - current_limit_ = INT_MAX; + RecomputeBufferLimits(); } - // We need to enforce all limits, not just the new one, so if the previous - // limit was before the new requested limit, we continue to enforce the - // previous limit. - current_limit_ = std::min(current_limit_, old_limit); - - RecomputeBufferLimits(); return old_limit; } @@ -183,18 +173,11 @@ int CodedInputStream::BytesUntilLimit() const { return current_limit_ - current_position; } -void CodedInputStream::SetTotalBytesLimit( - int total_bytes_limit, int warning_threshold) { +void CodedInputStream::SetTotalBytesLimit(int total_bytes_limit) { // Make sure the limit isn't already past, since this could confuse other // code. int current_position = CurrentPosition(); total_bytes_limit_ = std::max(current_position, total_bytes_limit); - if (warning_threshold >= 0) { - total_bytes_warning_threshold_ = warning_threshold; - } else { - // warning_threshold is negative - total_bytes_warning_threshold_ = -1; - } RecomputeBufferLimits(); } @@ -211,17 +194,7 @@ void CodedInputStream::PrintTotalBytesLimitError() { "in google/protobuf/io/coded_stream.h."; } -bool CodedInputStream::Skip(int count) { - if (count < 0) return false; // security: count is often user-supplied - - const int original_buffer_size = BufferSize(); - - if (count <= original_buffer_size) { - // Just skipping within the current buffer. Easy. - Advance(count); - return true; - } - +bool CodedInputStream::SkipFallback(int count, int original_buffer_size) { if (buffer_size_after_limit_ > 0) { // We hit a limit inside this buffer. Advance to the limit and fail. Advance(original_buffer_size); @@ -244,8 +217,12 @@ bool CodedInputStream::Skip(int count) { return false; } + if (!input_->Skip(count)) { + total_bytes_read_ = input_->ByteCount(); + return false; + } total_bytes_read_ += count; - return input_->Skip(count); + return true; } bool CodedInputStream::GetDirectBufferPointer(const void** data, int* size) { @@ -339,7 +316,8 @@ namespace { // The first part of the pair is true iff the read was successful. The second // part is buffer + (number of bytes read). This function is always inlined, // so returning a pair is costless. -GOOGLE_ATTRIBUTE_ALWAYS_INLINE ::std::pair<bool, const uint8*> ReadVarint32FromArray( +GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE +::std::pair<bool, const uint8*> ReadVarint32FromArray( uint32 first_byte, const uint8* buffer, uint32* value); inline ::std::pair<bool, const uint8*> ReadVarint32FromArray( @@ -376,8 +354,8 @@ inline ::std::pair<bool, const uint8*> ReadVarint32FromArray( return std::make_pair(true, ptr); } -GOOGLE_ATTRIBUTE_ALWAYS_INLINE::std::pair<bool, const uint8*> ReadVarint64FromArray( - const uint8* buffer, uint64* value); +GOOGLE_PROTOBUF_ATTRIBUTE_ALWAYS_INLINE::std::pair<bool, const uint8*> +ReadVarint64FromArray(const uint8* buffer, uint64* value); inline ::std::pair<bool, const uint8*> ReadVarint64FromArray( const uint8* buffer, uint64* value) { const uint8* ptr = buffer; @@ -605,20 +583,6 @@ bool CodedInputStream::Refresh() { return false; } - if (total_bytes_warning_threshold_ >= 0 && - total_bytes_read_ >= total_bytes_warning_threshold_) { - GOOGLE_LOG(INFO) << "Reading dangerously large protocol message. If the " - "message turns out to be larger than " - << total_bytes_limit_ << " bytes, parsing will be halted " - "for security reasons. To increase the limit (or to " - "disable these warnings), see " - "CodedInputStream::SetTotalBytesLimit() in " - "google/protobuf/io/coded_stream.h."; - - // Don't warn again for this stream, and print total size at the end. - total_bytes_warning_threshold_ = -2; - } - const void* void_buffer; int buffer_size; if (NextNonEmpty(input_, &void_buffer, &buffer_size)) { @@ -655,23 +619,11 @@ bool CodedInputStream::Refresh() { // CodedOutputStream ================================================= -bool CodedOutputStream::default_serialization_deterministic_ = false; +std::atomic<bool> CodedOutputStream::default_serialization_deterministic_{ + false}; CodedOutputStream::CodedOutputStream(ZeroCopyOutputStream* output) - : output_(output), - buffer_(NULL), - buffer_size_(0), - total_bytes_(0), - had_error_(false), - aliasing_enabled_(false), - serialization_deterministic_is_overridden_(false) { - // Eagerly Refresh() so buffer space is immediately available. - Refresh(); - // The Refresh() may have failed. If the client doesn't write any data, - // though, don't consider this an error. If the client does write data, then - // another Refresh() will be attempted and it will set the error once again. - had_error_ = false; -} + : CodedOutputStream(output, true) {} CodedOutputStream::CodedOutputStream(ZeroCopyOutputStream* output, bool do_eager_refresh) @@ -681,7 +633,7 @@ CodedOutputStream::CodedOutputStream(ZeroCopyOutputStream* output, total_bytes_(0), had_error_(false), aliasing_enabled_(false), - serialization_deterministic_is_overridden_(false) { + is_serialization_deterministic_(IsDefaultSerializationDeterministic()) { if (do_eager_refresh) { // Eagerly Refresh() so buffer space is immediately available. Refresh(); |