LCOV - code coverage report
Current view: top level - toolkit/components/protobuf/src/google/protobuf/io - coded_stream.cc (source / functions) Hit Total Coverage
Test: output.info Lines: 54 452 11.9 %
Date: 2017-07-14 16:53:18 Functions: 6 42 14.3 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13