LCOV - code coverage report
Current view: directory - ipc/chromium/src/base - pickle.cc (source / functions) Found Hit Coverage
Test: app.info Lines: 306 99 32.4 %
Date: 2012-06-02 Functions: 37 16 43.2 %

       1                 : // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
       2                 : // Use of this source code is governed by a BSD-style license that can be
       3                 : // found in the LICENSE file.
       4                 : 
       5                 : #include "base/pickle.h"
       6                 : 
       7                 : #include <stdlib.h>
       8                 : 
       9                 : #include <limits>
      10                 : #include <string>
      11                 : 
      12                 : //------------------------------------------------------------------------------
      13                 : 
      14                 : // static
      15                 : const int Pickle::kPayloadUnit = 64;
      16                 : 
      17                 : // We mark a read only pickle with a special capacity_.
      18                 : static const uint32 kCapacityReadOnly = (uint32) -1;
      19                 : 
      20                 : // Payload is uint32 aligned.
      21                 : 
      22               2 : Pickle::Pickle()
      23                 :     : header_(NULL),
      24                 :       header_size_(sizeof(Header)),
      25                 :       capacity_(0),
      26               2 :       variable_buffer_offset_(0) {
      27               2 :   Resize(kPayloadUnit);
      28               2 :   header_->payload_size = 0;
      29               2 : }
      30                 : 
      31               2 : Pickle::Pickle(int header_size)
      32                 :     : header_(NULL),
      33               2 :       header_size_(AlignInt(header_size, sizeof(uint32))),
      34                 :       capacity_(0),
      35               4 :       variable_buffer_offset_(0) {
      36               2 :   DCHECK(static_cast<uint32>(header_size) >= sizeof(Header));
      37               2 :   DCHECK(header_size <= kPayloadUnit);
      38               2 :   Resize(kPayloadUnit);
      39               2 :   header_->payload_size = 0;
      40               2 : }
      41                 : 
      42               2 : Pickle::Pickle(const char* data, int data_len)
      43                 :     : header_(reinterpret_cast<Header*>(const_cast<char*>(data))),
      44                 :       header_size_(data_len - header_->payload_size),
      45                 :       capacity_(kCapacityReadOnly),
      46               2 :       variable_buffer_offset_(0) {
      47               2 :   DCHECK(header_size_ >= sizeof(Header));
      48               2 :   DCHECK(header_size_ == AlignInt(header_size_, sizeof(uint32)));
      49               2 : }
      50                 : 
      51               0 : Pickle::Pickle(const Pickle& other)
      52                 :     : header_(NULL),
      53                 :       header_size_(other.header_size_),
      54                 :       capacity_(0),
      55               0 :       variable_buffer_offset_(other.variable_buffer_offset_) {
      56               0 :   uint32 payload_size = header_size_ + other.header_->payload_size;
      57               0 :   bool resized = Resize(payload_size);
      58               0 :   CHECK(resized);  // Realloc failed.
      59               0 :   memcpy(header_, other.header_, payload_size);
      60               0 : }
      61                 : 
      62               4 : Pickle::~Pickle() {
      63               4 :   if (capacity_ != kCapacityReadOnly)
      64               2 :     free(header_);
      65               4 : }
      66                 : 
      67               0 : Pickle& Pickle::operator=(const Pickle& other) {
      68               0 :   if (header_size_ != other.header_size_ && capacity_ != kCapacityReadOnly) {
      69               0 :     free(header_);
      70               0 :     header_ = NULL;
      71               0 :     header_size_ = other.header_size_;
      72                 :   }
      73               0 :   bool resized = Resize(other.header_size_ + other.header_->payload_size);
      74               0 :   CHECK(resized);  // Realloc failed.
      75               0 :   memcpy(header_, other.header_, header_size_ + other.header_->payload_size);
      76               0 :   variable_buffer_offset_ = other.variable_buffer_offset_;
      77               0 :   return *this;
      78                 : }
      79                 : 
      80               0 : bool Pickle::ReadBool(void** iter, bool* result) const {
      81               0 :   DCHECK(iter);
      82                 : 
      83                 :   int tmp;
      84               0 :   if (!ReadInt(iter, &tmp))
      85               0 :     return false;
      86               0 :   DCHECK(0 == tmp || 1 == tmp);
      87               0 :   *result = tmp ? true : false;
      88               0 :   return true;
      89                 : }
      90                 : 
      91               0 : bool Pickle::ReadInt16(void** iter, int16* result) const {
      92               0 :   DCHECK(iter);
      93               0 :   if (!*iter)
      94               0 :     *iter = const_cast<char*>(payload());
      95                 : 
      96               0 :   if (!IteratorHasRoomFor(*iter, sizeof(*result)))
      97               0 :     return false;
      98                 : 
      99               0 :   memcpy(result, *iter, sizeof(*result));
     100                 : 
     101               0 :   UpdateIter(iter, sizeof(*result));
     102               0 :   return true;
     103                 : }
     104                 : 
     105               0 : bool Pickle::ReadUInt16(void** iter, uint16* result) const {
     106               0 :   DCHECK(iter);
     107               0 :   if (!*iter)
     108               0 :     *iter = const_cast<char*>(payload());
     109                 : 
     110               0 :   if (!IteratorHasRoomFor(*iter, sizeof(*result)))
     111               0 :     return false;
     112                 : 
     113               0 :   memcpy(result, *iter, sizeof(*result));
     114                 : 
     115               0 :   UpdateIter(iter, sizeof(*result));
     116               0 :   return true;
     117                 : }
     118                 : 
     119           41885 : bool Pickle::ReadInt(void** iter, int* result) const {
     120           41885 :   DCHECK(iter);
     121           41885 :   if (!*iter)
     122               0 :     *iter = const_cast<char*>(payload());
     123                 : 
     124           41885 :   if (!IteratorHasRoomFor(*iter, sizeof(*result)))
     125               0 :     return false;
     126                 : 
     127                 :   // TODO(jar) bug 1129285: Pickle should be cleaned up, and not dependent on
     128                 :   // alignment.
     129                 :   // Next line is otherwise the same as: memcpy(result, *iter, sizeof(*result));
     130           41885 :   *result = *reinterpret_cast<int*>(*iter);
     131                 : 
     132           41885 :   UpdateIter(iter, sizeof(*result));
     133           41885 :   return true;
     134                 : }
     135                 : 
     136                 : // Always written as a 64-bit value since the size for this type can
     137                 : // differ between architectures.
     138               0 : bool Pickle::ReadLong(void** iter, long* result) const {
     139               0 :   DCHECK(iter);
     140               0 :   if (!*iter)
     141               0 :     *iter = const_cast<char*>(payload());
     142                 : 
     143               0 :   int64 bigResult = 0;
     144               0 :   if (!IteratorHasRoomFor(*iter, sizeof(bigResult)))
     145               0 :     return false;
     146                 : 
     147                 :   // TODO(jar) bug 1129285: Pickle should be cleaned up, and not dependent on
     148                 :   // alignment.
     149               0 :   memcpy(&bigResult, *iter, sizeof(bigResult));
     150               0 :   DCHECK(bigResult <= LONG_MAX && bigResult >= LONG_MIN);
     151               0 :   *result = static_cast<long>(bigResult);
     152                 : 
     153               0 :   UpdateIter(iter, sizeof(bigResult));
     154               0 :   return true;
     155                 : }
     156                 : 
     157                 : // Always written as a 64-bit value since the size for this type can
     158                 : // differ between architectures.
     159               0 : bool Pickle::ReadULong(void** iter, unsigned long* result) const {
     160               0 :   DCHECK(iter);
     161               0 :   if (!*iter)
     162               0 :     *iter = const_cast<char*>(payload());
     163                 : 
     164               0 :   uint64 bigResult = 0;
     165               0 :   if (!IteratorHasRoomFor(*iter, sizeof(bigResult)))
     166               0 :     return false;
     167                 : 
     168                 :   // TODO(jar) bug 1129285: Pickle should be cleaned up, and not dependent on
     169                 :   // alignment.
     170               0 :   memcpy(&bigResult, *iter, sizeof(bigResult));
     171               0 :   DCHECK(bigResult <= ULONG_MAX);
     172               0 :   *result = static_cast<unsigned long>(bigResult);
     173                 : 
     174               0 :   UpdateIter(iter, sizeof(bigResult));
     175               0 :   return true;
     176                 : }
     177                 : 
     178              76 : bool Pickle::ReadLength(void** iter, int* result) const {
     179              76 :   if (!ReadInt(iter, result))
     180               0 :     return false;
     181              76 :   return ((*result) >= 0);
     182                 : }
     183                 : 
     184                 : // Always written as a 64-bit value since the size for this type can
     185                 : // differ between architectures.
     186              74 : bool Pickle::ReadSize(void** iter, size_t* result) const {
     187              74 :   DCHECK(iter);
     188              74 :   if (!*iter)
     189               0 :     *iter = const_cast<char*>(payload());
     190                 : 
     191              74 :   uint64 bigResult = 0;
     192              74 :   if (!IteratorHasRoomFor(*iter, sizeof(bigResult)))
     193               0 :     return false;
     194                 : 
     195                 :   // TODO(jar) bug 1129285: Pickle should be cleaned up, and not dependent on
     196                 :   // alignment.
     197              74 :   memcpy(&bigResult, *iter, sizeof(bigResult));
     198              74 :   DCHECK(bigResult <= std::numeric_limits<size_t>::max());
     199              74 :   *result = static_cast<size_t>(bigResult);
     200                 : 
     201              74 :   UpdateIter(iter, sizeof(bigResult));
     202              74 :   return true;
     203                 : }
     204                 : 
     205               0 : bool Pickle::ReadInt32(void** iter, int32* result) const {
     206               0 :   DCHECK(iter);
     207               0 :   if (!*iter)
     208               0 :     *iter = const_cast<char*>(payload());
     209                 : 
     210               0 :   if (!IteratorHasRoomFor(*iter, sizeof(*result)))
     211               0 :     return false;
     212                 : 
     213               0 :   memcpy(result, *iter, sizeof(*result));
     214                 : 
     215               0 :   UpdateIter(iter, sizeof(*result));
     216               0 :   return true;
     217                 : }
     218                 : 
     219               4 : bool Pickle::ReadUInt32(void** iter, uint32* result) const {
     220               4 :   DCHECK(iter);
     221               4 :   if (!*iter)
     222               2 :     *iter = const_cast<char*>(payload());
     223                 : 
     224               4 :   if (!IteratorHasRoomFor(*iter, sizeof(*result)))
     225               0 :     return false;
     226                 : 
     227               4 :   memcpy(result, *iter, sizeof(*result));
     228                 : 
     229               4 :   UpdateIter(iter, sizeof(*result));
     230               4 :   return true;
     231                 : }
     232                 : 
     233             148 : bool Pickle::ReadInt64(void** iter, int64* result) const {
     234             148 :   DCHECK(iter);
     235             148 :   if (!*iter)
     236               0 :     *iter = const_cast<char*>(payload());
     237                 : 
     238             148 :   if (!IteratorHasRoomFor(*iter, sizeof(*result)))
     239               0 :     return false;
     240                 : 
     241             148 :   memcpy(result, *iter, sizeof(*result));
     242                 : 
     243             148 :   UpdateIter(iter, sizeof(*result));
     244             148 :   return true;
     245                 : }
     246                 : 
     247               0 : bool Pickle::ReadUInt64(void** iter, uint64* result) const {
     248               0 :   DCHECK(iter);
     249               0 :   if (!*iter)
     250               0 :     *iter = const_cast<char*>(payload());
     251                 : 
     252               0 :   if (!IteratorHasRoomFor(*iter, sizeof(*result)))
     253               0 :     return false;
     254                 : 
     255               0 :   memcpy(result, *iter, sizeof(*result));
     256                 : 
     257               0 :   UpdateIter(iter, sizeof(*result));
     258               0 :   return true;
     259                 : }
     260                 : 
     261               0 : bool Pickle::ReadDouble(void** iter, double* result) const {
     262               0 :   DCHECK(iter);
     263               0 :   if (!*iter)
     264               0 :     *iter = const_cast<char*>(payload());
     265                 : 
     266               0 :   if (!IteratorHasRoomFor(*iter, sizeof(*result)))
     267               0 :     return false;
     268                 : 
     269               0 :   memcpy(result, *iter, sizeof(*result));
     270                 : 
     271               0 :   UpdateIter(iter, sizeof(*result));
     272               0 :   return true;
     273                 : }
     274                 : 
     275                 : // Always written as a 64-bit value since the size for this type can
     276                 : // differ between architectures.
     277               0 : bool Pickle::ReadIntPtr(void** iter, intptr_t* result) const {
     278               0 :   DCHECK(iter);
     279               0 :   if (!*iter)
     280               0 :     *iter = const_cast<char*>(payload());
     281                 : 
     282               0 :   int64 bigResult = 0;
     283               0 :   if (!IteratorHasRoomFor(*iter, sizeof(bigResult)))
     284               0 :     return false;
     285                 : 
     286               0 :   memcpy(&bigResult, *iter, sizeof(bigResult));
     287               0 :   DCHECK(bigResult <= std::numeric_limits<intptr_t>::max() && bigResult >= std::numeric_limits<intptr_t>::min());
     288               0 :   *result = static_cast<intptr_t>(bigResult);
     289                 : 
     290               0 :   UpdateIter(iter, sizeof(bigResult));
     291               0 :   return true;
     292                 : }
     293                 : 
     294               0 : bool Pickle::ReadUnsignedChar(void** iter, unsigned char* result) const {
     295               0 :   DCHECK(iter);
     296               0 :   if (!*iter)
     297               0 :     *iter = const_cast<char*>(payload());
     298                 : 
     299               0 :   if (!IteratorHasRoomFor(*iter, sizeof(*result)))
     300               0 :     return false;
     301                 : 
     302               0 :   memcpy(result, *iter, sizeof(*result));
     303                 : 
     304               0 :   UpdateIter(iter, sizeof(*result));
     305               0 :   return true;
     306                 : }
     307                 : 
     308               0 : bool Pickle::ReadString(void** iter, std::string* result) const {
     309               0 :   DCHECK(iter);
     310               0 :   if (!*iter)
     311               0 :     *iter = const_cast<char*>(payload());
     312                 : 
     313                 :   int len;
     314               0 :   if (!ReadLength(iter, &len))
     315               0 :     return false;
     316               0 :   if (!IteratorHasRoomFor(*iter, len))
     317               0 :     return false;
     318                 : 
     319               0 :   char* chars = reinterpret_cast<char*>(*iter);
     320               0 :   result->assign(chars, len);
     321                 : 
     322               0 :   UpdateIter(iter, len);
     323               0 :   return true;
     324                 : }
     325                 : 
     326               0 : bool Pickle::ReadWString(void** iter, std::wstring* result) const {
     327               0 :   DCHECK(iter);
     328               0 :   if (!*iter)
     329               0 :     *iter = const_cast<char*>(payload());
     330                 : 
     331                 :   int len;
     332               0 :   if (!ReadLength(iter, &len))
     333               0 :     return false;
     334               0 :   if (!IteratorHasRoomFor(*iter, len * sizeof(wchar_t)))
     335               0 :     return false;
     336                 : 
     337               0 :   wchar_t* chars = reinterpret_cast<wchar_t*>(*iter);
     338               0 :   result->assign(chars, len);
     339                 : 
     340               0 :   UpdateIter(iter, len * sizeof(wchar_t));
     341               0 :   return true;
     342                 : }
     343                 : 
     344               0 : bool Pickle::ReadString16(void** iter, string16* result) const {
     345               0 :   DCHECK(iter);
     346               0 :   if (!*iter)
     347               0 :     *iter = const_cast<char*>(payload());
     348                 : 
     349                 :   int len;
     350               0 :   if (!ReadLength(iter, &len))
     351               0 :     return false;
     352               0 :   if (!IteratorHasRoomFor(*iter, len))
     353               0 :     return false;
     354                 : 
     355               0 :   char16* chars = reinterpret_cast<char16*>(*iter);
     356               0 :   result->assign(chars, len);
     357                 : 
     358               0 :   UpdateIter(iter, len * sizeof(char16));
     359               0 :   return true;
     360                 : }
     361                 : 
     362              76 : bool Pickle::ReadBytes(void** iter, const char** data, int length) const {
     363              76 :   DCHECK(iter);
     364              76 :   DCHECK(data);
     365              76 :   if (!*iter)
     366               0 :     *iter = const_cast<char*>(payload());
     367                 : 
     368              76 :   if (!IteratorHasRoomFor(*iter, length))
     369               0 :     return false;
     370                 : 
     371              76 :   *data = reinterpret_cast<const char*>(*iter);
     372                 : 
     373              76 :   UpdateIter(iter, length);
     374              76 :   return true;
     375                 : }
     376                 : 
     377              76 : bool Pickle::ReadData(void** iter, const char** data, int* length) const {
     378              76 :   DCHECK(iter);
     379              76 :   DCHECK(data);
     380              76 :   DCHECK(length);
     381              76 :   if (!*iter)
     382               0 :     *iter = const_cast<char*>(payload());
     383                 : 
     384              76 :   if (!ReadLength(iter, length))
     385               0 :     return false;
     386                 : 
     387              76 :   return ReadBytes(iter, data, *length);
     388                 : }
     389                 : 
     390           42188 : char* Pickle::BeginWrite(uint32 length) {
     391                 :   // write at a uint32-aligned offset from the beginning of the header
     392           42188 :   uint32 offset = AlignInt(header_->payload_size, sizeof(uint32));
     393           42188 :   uint32 new_size = offset + AlignInt(length, sizeof(uint32));
     394           42188 :   uint32 needed_size = header_size_ + new_size;
     395                 : 
     396           42188 :   if (needed_size > capacity_ && !Resize(std::max(capacity_ * 2, needed_size)))
     397               0 :     return NULL;
     398                 : 
     399                 : #ifdef ARCH_CPU_64_BITS
     400                 :   DCHECK_LE(length, std::numeric_limits<uint32>::max());
     401                 : #endif
     402                 : 
     403           42188 :   header_->payload_size = static_cast<uint32>(new_size);
     404           42188 :   return payload() + offset;
     405                 : }
     406                 : 
     407           42188 : void Pickle::EndWrite(char* dest, int length) {
     408                 :   // Zero-pad to keep tools like purify from complaining about uninitialized
     409                 :   // memory.
     410           42188 :   if (length % sizeof(uint32))
     411              54 :     memset(dest + length, 0, sizeof(uint32) - (length % sizeof(uint32)));
     412           42188 : }
     413                 : 
     414           42188 : bool Pickle::WriteBytes(const void* data, int data_len) {
     415           42188 :   DCHECK(capacity_ != kCapacityReadOnly) << "oops: pickle is readonly";
     416                 : 
     417           42188 :   char* dest = BeginWrite(data_len);
     418           42188 :   if (!dest)
     419               0 :     return false;
     420                 : 
     421           42188 :   memcpy(dest, data, data_len);
     422                 : 
     423           42188 :   EndWrite(dest, data_len);
     424           42188 :   return true;
     425                 : }
     426                 : 
     427               0 : bool Pickle::WriteString(const std::string& value) {
     428               0 :   if (!WriteInt(static_cast<int>(value.size())))
     429               0 :     return false;
     430                 : 
     431               0 :   return WriteBytes(value.data(), static_cast<int>(value.size()));
     432                 : }
     433                 : 
     434               0 : bool Pickle::WriteWString(const std::wstring& value) {
     435               0 :   if (!WriteInt(static_cast<int>(value.size())))
     436               0 :     return false;
     437                 : 
     438               0 :   return WriteBytes(value.data(),
     439               0 :                     static_cast<int>(value.size() * sizeof(wchar_t)));
     440                 : }
     441                 : 
     442               0 : bool Pickle::WriteString16(const string16& value) {
     443               0 :   if (!WriteInt(static_cast<int>(value.size())))
     444               0 :     return false;
     445                 : 
     446               0 :   return WriteBytes(value.data(),
     447               0 :                     static_cast<int>(value.size()) * sizeof(char16));
     448                 : }
     449                 : 
     450              76 : bool Pickle::WriteData(const char* data, int length) {
     451              76 :   return WriteInt(length) && WriteBytes(data, length);
     452                 : }
     453                 : 
     454               0 : char* Pickle::BeginWriteData(int length) {
     455               0 :   DCHECK_EQ(variable_buffer_offset_, 0U) <<
     456               0 :     "There can only be one variable buffer in a Pickle";
     457                 : 
     458               0 :   if (!WriteInt(length))
     459               0 :     return false;
     460                 : 
     461               0 :   char *data_ptr = BeginWrite(length);
     462               0 :   if (!data_ptr)
     463               0 :     return NULL;
     464                 : 
     465                 :   variable_buffer_offset_ =
     466               0 :       data_ptr - reinterpret_cast<char*>(header_) - sizeof(int);
     467                 : 
     468                 :   // EndWrite doesn't necessarily have to be called after the write operation,
     469                 :   // so we call it here to pad out what the caller will eventually write.
     470               0 :   EndWrite(data_ptr, length);
     471               0 :   return data_ptr;
     472                 : }
     473                 : 
     474               0 : void Pickle::TrimWriteData(int new_length) {
     475               0 :   DCHECK(variable_buffer_offset_ != 0);
     476                 : 
     477                 :   // Fetch the the variable buffer size
     478                 :   int* cur_length = reinterpret_cast<int*>(
     479               0 :       reinterpret_cast<char*>(header_) + variable_buffer_offset_);
     480                 : 
     481               0 :   if (new_length < 0 || new_length > *cur_length) {
     482               0 :     NOTREACHED() << "Invalid length in TrimWriteData.";
     483               0 :     return;
     484                 :   }
     485                 : 
     486                 :   // Update the payload size and variable buffer size
     487               0 :   header_->payload_size -= (*cur_length - new_length);
     488               0 :   *cur_length = new_length;
     489                 : }
     490                 : 
     491              20 : bool Pickle::Resize(uint32 new_capacity) {
     492              20 :   new_capacity = AlignInt(new_capacity, kPayloadUnit);
     493                 : 
     494              20 :   void* p = realloc(header_, new_capacity);
     495              20 :   if (!p)
     496               0 :     return false;
     497                 : 
     498              20 :   header_ = reinterpret_cast<Header*>(p);
     499              20 :   capacity_ = new_capacity;
     500              20 :   return true;
     501                 : }
     502                 : 
     503                 : // static
     504               0 : const char* Pickle::FindNext(uint32 header_size,
     505                 :                              const char* start,
     506                 :                              const char* end) {
     507               0 :   DCHECK(header_size == AlignInt(header_size, sizeof(uint32)));
     508               0 :   DCHECK(header_size <= static_cast<uint32>(kPayloadUnit));
     509                 : 
     510               0 :   const Header* hdr = reinterpret_cast<const Header*>(start);
     511               0 :   const char* payload_base = start + header_size;
     512               0 :   const char* payload_end = payload_base + hdr->payload_size;
     513               0 :   if (payload_end < payload_base)
     514               0 :     return NULL;
     515                 : 
     516               0 :   return (payload_end > end) ? NULL : payload_end;
     517                 : }

Generated by: LCOV version 1.7