LCOV - code coverage report
Current view: top level - third_party/protobuf/src/google/protobuf/io - coded_stream.cc (source / functions) Hit Total Coverage
Test: tmp.zDYK9MVh93 Lines: 274 397 69.0 %
Date: 2015-10-10 Functions: 32 45 71.1 %

          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

Generated by: LCOV version 1.10