| OLD | NEW |
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "base/pickle.h" | 5 #include "base/pickle.h" |
| 6 | 6 |
| 7 #include <stdlib.h> | 7 #include <stdlib.h> |
| 8 | 8 |
| 9 #include <algorithm> // for max() | 9 #include <algorithm> // for max() |
| 10 #include <limits> | 10 #include <limits> |
| (...skipping 12 matching lines...) Expand all Loading... |
| 23 : payload_(pickle.payload()), | 23 : payload_(pickle.payload()), |
| 24 read_index_(0), | 24 read_index_(0), |
| 25 end_index_(pickle.payload_size()) { | 25 end_index_(pickle.payload_size()) { |
| 26 } | 26 } |
| 27 | 27 |
| 28 template <typename Type> | 28 template <typename Type> |
| 29 inline bool PickleIterator::ReadBuiltinType(Type* result) { | 29 inline bool PickleIterator::ReadBuiltinType(Type* result) { |
| 30 const char* read_from = GetReadPointerAndAdvance<Type>(); | 30 const char* read_from = GetReadPointerAndAdvance<Type>(); |
| 31 if (!read_from) | 31 if (!read_from) |
| 32 return false; | 32 return false; |
| 33 if (sizeof(Type) > sizeof(uint32)) | 33 if (sizeof(Type) > sizeof(uint32_t)) |
| 34 memcpy(result, read_from, sizeof(*result)); | 34 memcpy(result, read_from, sizeof(*result)); |
| 35 else | 35 else |
| 36 *result = *reinterpret_cast<const Type*>(read_from); | 36 *result = *reinterpret_cast<const Type*>(read_from); |
| 37 return true; | 37 return true; |
| 38 } | 38 } |
| 39 | 39 |
| 40 inline void PickleIterator::Advance(size_t size) { | 40 inline void PickleIterator::Advance(size_t size) { |
| 41 size_t aligned_size = bits::Align(size, sizeof(uint32_t)); | 41 size_t aligned_size = bits::Align(size, sizeof(uint32_t)); |
| 42 if (end_index_ - read_index_ < aligned_size) { | 42 if (end_index_ - read_index_ < aligned_size) { |
| 43 read_index_ = end_index_; | 43 read_index_ = end_index_; |
| (...skipping 21 matching lines...) Expand all Loading... |
| 65 } | 65 } |
| 66 const char* current_read_ptr = payload_ + read_index_; | 66 const char* current_read_ptr = payload_ + read_index_; |
| 67 Advance(num_bytes); | 67 Advance(num_bytes); |
| 68 return current_read_ptr; | 68 return current_read_ptr; |
| 69 } | 69 } |
| 70 | 70 |
| 71 inline const char* PickleIterator::GetReadPointerAndAdvance( | 71 inline const char* PickleIterator::GetReadPointerAndAdvance( |
| 72 int num_elements, | 72 int num_elements, |
| 73 size_t size_element) { | 73 size_t size_element) { |
| 74 // Check for int32 overflow. | 74 // Check for int32 overflow. |
| 75 int64 num_bytes = static_cast<int64>(num_elements) * size_element; | 75 int64_t num_bytes = static_cast<int64_t>(num_elements) * size_element; |
| 76 int num_bytes32 = static_cast<int>(num_bytes); | 76 int num_bytes32 = static_cast<int>(num_bytes); |
| 77 if (num_bytes != static_cast<int64>(num_bytes32)) | 77 if (num_bytes != static_cast<int64_t>(num_bytes32)) |
| 78 return NULL; | 78 return NULL; |
| 79 return GetReadPointerAndAdvance(num_bytes32); | 79 return GetReadPointerAndAdvance(num_bytes32); |
| 80 } | 80 } |
| 81 | 81 |
| 82 bool PickleIterator::ReadBool(bool* result) { | 82 bool PickleIterator::ReadBool(bool* result) { |
| 83 return ReadBuiltinType(result); | 83 return ReadBuiltinType(result); |
| 84 } | 84 } |
| 85 | 85 |
| 86 bool PickleIterator::ReadInt(int* result) { | 86 bool PickleIterator::ReadInt(int* result) { |
| 87 return ReadBuiltinType(result); | 87 return ReadBuiltinType(result); |
| 88 } | 88 } |
| 89 | 89 |
| 90 bool PickleIterator::ReadLong(long* result) { | 90 bool PickleIterator::ReadLong(long* result) { |
| 91 return ReadBuiltinType(result); | 91 return ReadBuiltinType(result); |
| 92 } | 92 } |
| 93 | 93 |
| 94 bool PickleIterator::ReadUInt16(uint16* result) { | 94 bool PickleIterator::ReadUInt16(uint16_t* result) { |
| 95 return ReadBuiltinType(result); | 95 return ReadBuiltinType(result); |
| 96 } | 96 } |
| 97 | 97 |
| 98 bool PickleIterator::ReadUInt32(uint32* result) { | 98 bool PickleIterator::ReadUInt32(uint32_t* result) { |
| 99 return ReadBuiltinType(result); | 99 return ReadBuiltinType(result); |
| 100 } | 100 } |
| 101 | 101 |
| 102 bool PickleIterator::ReadInt64(int64* result) { | 102 bool PickleIterator::ReadInt64(int64_t* result) { |
| 103 return ReadBuiltinType(result); | 103 return ReadBuiltinType(result); |
| 104 } | 104 } |
| 105 | 105 |
| 106 bool PickleIterator::ReadUInt64(uint64* result) { | 106 bool PickleIterator::ReadUInt64(uint64_t* result) { |
| 107 return ReadBuiltinType(result); | 107 return ReadBuiltinType(result); |
| 108 } | 108 } |
| 109 | 109 |
| 110 bool PickleIterator::ReadSizeT(size_t* result) { | 110 bool PickleIterator::ReadSizeT(size_t* result) { |
| 111 // Always read size_t as a 64-bit value to ensure compatibility between 32-bit | 111 // Always read size_t as a 64-bit value to ensure compatibility between 32-bit |
| 112 // and 64-bit processes. | 112 // and 64-bit processes. |
| 113 uint64 result_uint64 = 0; | 113 uint64_t result_uint64 = 0; |
| 114 bool success = ReadBuiltinType(&result_uint64); | 114 bool success = ReadBuiltinType(&result_uint64); |
| 115 *result = static_cast<size_t>(result_uint64); | 115 *result = static_cast<size_t>(result_uint64); |
| 116 // Fail if the cast above truncates the value. | 116 // Fail if the cast above truncates the value. |
| 117 return success && (*result == result_uint64); | 117 return success && (*result == result_uint64); |
| 118 } | 118 } |
| 119 | 119 |
| 120 bool PickleIterator::ReadFloat(float* result) { | 120 bool PickleIterator::ReadFloat(float* result) { |
| 121 // crbug.com/315213 | 121 // crbug.com/315213 |
| 122 // The source data may not be properly aligned, and unaligned float reads | 122 // The source data may not be properly aligned, and unaligned float reads |
| 123 // cause SIGBUS on some ARM platforms, so force using memcpy to copy the data | 123 // cause SIGBUS on some ARM platforms, so force using memcpy to copy the data |
| (...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 200 } | 200 } |
| 201 | 201 |
| 202 bool PickleIterator::ReadBytes(const char** data, int length) { | 202 bool PickleIterator::ReadBytes(const char** data, int length) { |
| 203 const char* read_from = GetReadPointerAndAdvance(length); | 203 const char* read_from = GetReadPointerAndAdvance(length); |
| 204 if (!read_from) | 204 if (!read_from) |
| 205 return false; | 205 return false; |
| 206 *data = read_from; | 206 *data = read_from; |
| 207 return true; | 207 return true; |
| 208 } | 208 } |
| 209 | 209 |
| 210 // Payload is uint32 aligned. | 210 // Payload is uint32_t aligned. |
| 211 | 211 |
| 212 Pickle::Pickle() | 212 Pickle::Pickle() |
| 213 : header_(NULL), | 213 : header_(NULL), |
| 214 header_size_(sizeof(Header)), | 214 header_size_(sizeof(Header)), |
| 215 capacity_after_header_(0), | 215 capacity_after_header_(0), |
| 216 write_offset_(0) { | 216 write_offset_(0) { |
| 217 static_assert((Pickle::kPayloadUnit & (Pickle::kPayloadUnit - 1)) == 0, | 217 static_assert((Pickle::kPayloadUnit & (Pickle::kPayloadUnit - 1)) == 0, |
| 218 "Pickle::kPayloadUnit must be a power of two"); | 218 "Pickle::kPayloadUnit must be a power of two"); |
| 219 Resize(kPayloadUnit); | 219 Resize(kPayloadUnit); |
| 220 header_->payload_size = 0; | 220 header_->payload_size = 0; |
| 221 } | 221 } |
| 222 | 222 |
| 223 Pickle::Pickle(int header_size) | 223 Pickle::Pickle(int header_size) |
| 224 : header_(NULL), | 224 : header_(NULL), |
| 225 header_size_(bits::Align(header_size, sizeof(uint32))), | 225 header_size_(bits::Align(header_size, sizeof(uint32_t))), |
| 226 capacity_after_header_(0), | 226 capacity_after_header_(0), |
| 227 write_offset_(0) { | 227 write_offset_(0) { |
| 228 DCHECK_GE(static_cast<size_t>(header_size), sizeof(Header)); | 228 DCHECK_GE(static_cast<size_t>(header_size), sizeof(Header)); |
| 229 DCHECK_LE(header_size, kPayloadUnit); | 229 DCHECK_LE(header_size, kPayloadUnit); |
| 230 Resize(kPayloadUnit); | 230 Resize(kPayloadUnit); |
| 231 header_->payload_size = 0; | 231 header_->payload_size = 0; |
| 232 } | 232 } |
| 233 | 233 |
| 234 Pickle::Pickle(const char* data, int data_len) | 234 Pickle::Pickle(const char* data, int data_len) |
| 235 : header_(reinterpret_cast<Header*>(const_cast<char*>(data))), | 235 : header_(reinterpret_cast<Header*>(const_cast<char*>(data))), |
| 236 header_size_(0), | 236 header_size_(0), |
| 237 capacity_after_header_(kCapacityReadOnly), | 237 capacity_after_header_(kCapacityReadOnly), |
| 238 write_offset_(0) { | 238 write_offset_(0) { |
| 239 if (data_len >= static_cast<int>(sizeof(Header))) | 239 if (data_len >= static_cast<int>(sizeof(Header))) |
| 240 header_size_ = data_len - header_->payload_size; | 240 header_size_ = data_len - header_->payload_size; |
| 241 | 241 |
| 242 if (header_size_ > static_cast<unsigned int>(data_len)) | 242 if (header_size_ > static_cast<unsigned int>(data_len)) |
| 243 header_size_ = 0; | 243 header_size_ = 0; |
| 244 | 244 |
| 245 if (header_size_ != bits::Align(header_size_, sizeof(uint32))) | 245 if (header_size_ != bits::Align(header_size_, sizeof(uint32_t))) |
| 246 header_size_ = 0; | 246 header_size_ = 0; |
| 247 | 247 |
| 248 // If there is anything wrong with the data, we're not going to use it. | 248 // If there is anything wrong with the data, we're not going to use it. |
| 249 if (!header_size_) | 249 if (!header_size_) |
| 250 header_ = NULL; | 250 header_ = NULL; |
| 251 } | 251 } |
| 252 | 252 |
| 253 Pickle::Pickle(const Pickle& other) | 253 Pickle::Pickle(const Pickle& other) |
| 254 : header_(NULL), | 254 : header_(NULL), |
| 255 header_size_(other.header_size_), | 255 header_size_(other.header_size_), |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 303 bool Pickle::WriteData(const char* data, int length) { | 303 bool Pickle::WriteData(const char* data, int length) { |
| 304 return length >= 0 && WriteInt(length) && WriteBytes(data, length); | 304 return length >= 0 && WriteInt(length) && WriteBytes(data, length); |
| 305 } | 305 } |
| 306 | 306 |
| 307 bool Pickle::WriteBytes(const void* data, int length) { | 307 bool Pickle::WriteBytes(const void* data, int length) { |
| 308 WriteBytesCommon(data, length); | 308 WriteBytesCommon(data, length); |
| 309 return true; | 309 return true; |
| 310 } | 310 } |
| 311 | 311 |
| 312 void Pickle::Reserve(size_t length) { | 312 void Pickle::Reserve(size_t length) { |
| 313 size_t data_len = bits::Align(length, sizeof(uint32)); | 313 size_t data_len = bits::Align(length, sizeof(uint32_t)); |
| 314 DCHECK_GE(data_len, length); | 314 DCHECK_GE(data_len, length); |
| 315 #ifdef ARCH_CPU_64_BITS | 315 #ifdef ARCH_CPU_64_BITS |
| 316 DCHECK_LE(data_len, kuint32max); | 316 DCHECK_LE(data_len, std::numeric_limits<uint32_t>::max()); |
| 317 #endif | 317 #endif |
| 318 DCHECK_LE(write_offset_, kuint32max - data_len); | 318 DCHECK_LE(write_offset_, std::numeric_limits<uint32_t>::max() - data_len); |
| 319 size_t new_size = write_offset_ + data_len; | 319 size_t new_size = write_offset_ + data_len; |
| 320 if (new_size > capacity_after_header_) | 320 if (new_size > capacity_after_header_) |
| 321 Resize(capacity_after_header_ * 2 + new_size); | 321 Resize(capacity_after_header_ * 2 + new_size); |
| 322 } | 322 } |
| 323 | 323 |
| 324 void Pickle::Resize(size_t new_capacity) { | 324 void Pickle::Resize(size_t new_capacity) { |
| 325 CHECK_NE(capacity_after_header_, kCapacityReadOnly); | 325 CHECK_NE(capacity_after_header_, kCapacityReadOnly); |
| 326 capacity_after_header_ = bits::Align(new_capacity, kPayloadUnit); | 326 capacity_after_header_ = bits::Align(new_capacity, kPayloadUnit); |
| 327 void* p = realloc(header_, GetTotalAllocatedSize()); | 327 void* p = realloc(header_, GetTotalAllocatedSize()); |
| 328 CHECK(p); | 328 CHECK(p); |
| (...skipping 18 matching lines...) Expand all Loading... |
| 347 return NULL; | 347 return NULL; |
| 348 | 348 |
| 349 return start + pickle_size; | 349 return start + pickle_size; |
| 350 } | 350 } |
| 351 | 351 |
| 352 // static | 352 // static |
| 353 bool Pickle::PeekNext(size_t header_size, | 353 bool Pickle::PeekNext(size_t header_size, |
| 354 const char* start, | 354 const char* start, |
| 355 const char* end, | 355 const char* end, |
| 356 size_t* pickle_size) { | 356 size_t* pickle_size) { |
| 357 DCHECK_EQ(header_size, bits::Align(header_size, sizeof(uint32))); | 357 DCHECK_EQ(header_size, bits::Align(header_size, sizeof(uint32_t))); |
| 358 DCHECK_GE(header_size, sizeof(Header)); | 358 DCHECK_GE(header_size, sizeof(Header)); |
| 359 DCHECK_LE(header_size, static_cast<size_t>(kPayloadUnit)); | 359 DCHECK_LE(header_size, static_cast<size_t>(kPayloadUnit)); |
| 360 | 360 |
| 361 size_t length = static_cast<size_t>(end - start); | 361 size_t length = static_cast<size_t>(end - start); |
| 362 if (length < sizeof(Header)) | 362 if (length < sizeof(Header)) |
| 363 return false; | 363 return false; |
| 364 | 364 |
| 365 const Header* hdr = reinterpret_cast<const Header*>(start); | 365 const Header* hdr = reinterpret_cast<const Header*>(start); |
| 366 if (length < header_size) | 366 if (length < header_size) |
| 367 return false; | 367 return false; |
| (...skipping 13 matching lines...) Expand all Loading... |
| 381 } | 381 } |
| 382 | 382 |
| 383 template void Pickle::WriteBytesStatic<2>(const void* data); | 383 template void Pickle::WriteBytesStatic<2>(const void* data); |
| 384 template void Pickle::WriteBytesStatic<4>(const void* data); | 384 template void Pickle::WriteBytesStatic<4>(const void* data); |
| 385 template void Pickle::WriteBytesStatic<8>(const void* data); | 385 template void Pickle::WriteBytesStatic<8>(const void* data); |
| 386 | 386 |
| 387 inline void Pickle::WriteBytesCommon(const void* data, size_t length) { | 387 inline void Pickle::WriteBytesCommon(const void* data, size_t length) { |
| 388 DCHECK_NE(kCapacityReadOnly, capacity_after_header_) | 388 DCHECK_NE(kCapacityReadOnly, capacity_after_header_) |
| 389 << "oops: pickle is readonly"; | 389 << "oops: pickle is readonly"; |
| 390 MSAN_CHECK_MEM_IS_INITIALIZED(data, length); | 390 MSAN_CHECK_MEM_IS_INITIALIZED(data, length); |
| 391 size_t data_len = bits::Align(length, sizeof(uint32)); | 391 size_t data_len = bits::Align(length, sizeof(uint32_t)); |
| 392 DCHECK_GE(data_len, length); | 392 DCHECK_GE(data_len, length); |
| 393 #ifdef ARCH_CPU_64_BITS | 393 #ifdef ARCH_CPU_64_BITS |
| 394 DCHECK_LE(data_len, kuint32max); | 394 DCHECK_LE(data_len, std::numeric_limits<uint32_t>::max()); |
| 395 #endif | 395 #endif |
| 396 DCHECK_LE(write_offset_, kuint32max - data_len); | 396 DCHECK_LE(write_offset_, std::numeric_limits<uint32_t>::max() - data_len); |
| 397 size_t new_size = write_offset_ + data_len; | 397 size_t new_size = write_offset_ + data_len; |
| 398 if (new_size > capacity_after_header_) { | 398 if (new_size > capacity_after_header_) { |
| 399 size_t new_capacity = capacity_after_header_ * 2; | 399 size_t new_capacity = capacity_after_header_ * 2; |
| 400 const size_t kPickleHeapAlign = 4096; | 400 const size_t kPickleHeapAlign = 4096; |
| 401 if (new_capacity > kPickleHeapAlign) | 401 if (new_capacity > kPickleHeapAlign) |
| 402 new_capacity = bits::Align(new_capacity, kPickleHeapAlign) - kPayloadUnit; | 402 new_capacity = bits::Align(new_capacity, kPickleHeapAlign) - kPayloadUnit; |
| 403 Resize(std::max(new_capacity, new_size)); | 403 Resize(std::max(new_capacity, new_size)); |
| 404 } | 404 } |
| 405 | 405 |
| 406 char* write = mutable_payload() + write_offset_; | 406 char* write = mutable_payload() + write_offset_; |
| 407 memcpy(write, data, length); | 407 memcpy(write, data, length); |
| 408 memset(write + length, 0, data_len - length); | 408 memset(write + length, 0, data_len - length); |
| 409 header_->payload_size = static_cast<uint32>(new_size); | 409 header_->payload_size = static_cast<uint32_t>(new_size); |
| 410 write_offset_ = new_size; | 410 write_offset_ = new_size; |
| 411 } | 411 } |
| 412 | 412 |
| 413 } // namespace base | 413 } // namespace base |
| OLD | NEW |