diff options
-rw-r--r-- | base/pickle.cc | 21 | ||||
-rw-r--r-- | base/pickle.h | 20 | ||||
-rw-r--r-- | base/pickle_unittest.cc | 53 | ||||
-rw-r--r-- | ipc/ipc_message_utils.cc | 11 | ||||
-rw-r--r-- | ipc/ipc_message_utils.h | 21 |
5 files changed, 59 insertions, 67 deletions
diff --git a/base/pickle.cc b/base/pickle.cc index b12ec9a..94f3b1c 100644 --- a/base/pickle.cc +++ b/base/pickle.cc @@ -11,6 +11,7 @@ #include "base/bits.h" #include "base/macros.h" +#include "base/numerics/safe_conversions.h" #include "build/build_config.h" namespace base { @@ -89,7 +90,15 @@ bool PickleIterator::ReadInt(int* result) { } bool PickleIterator::ReadLong(long* result) { - return ReadBuiltinType(result); + // Always read long as a 64-bit value to ensure compatibility between 32-bit + // and 64-bit processes. + int64_t result_int64 = 0; + if (!ReadBuiltinType(&result_int64)) + return false; + // CHECK if the cast truncates the value so that we know to change this IPC + // parameter to use int64_t. + *result = base::checked_cast<long>(result_int64); + return true; } bool PickleIterator::ReadUInt16(uint16_t* result) { @@ -108,16 +117,6 @@ bool PickleIterator::ReadUInt64(uint64_t* result) { return ReadBuiltinType(result); } -bool PickleIterator::ReadSizeT(size_t* result) { - // Always read size_t as a 64-bit value to ensure compatibility between 32-bit - // and 64-bit processes. - uint64_t result_uint64 = 0; - bool success = ReadBuiltinType(&result_uint64); - *result = static_cast<size_t>(result_uint64); - // Fail if the cast above truncates the value. - return success && (*result == result_uint64); -} - bool PickleIterator::ReadFloat(float* result) { // crbug.com/315213 // The source data may not be properly aligned, and unaligned float reads diff --git a/base/pickle.h b/base/pickle.h index 18d8afe..eb4888a 100644 --- a/base/pickle.h +++ b/base/pickle.h @@ -45,7 +45,6 @@ class BASE_EXPORT PickleIterator { bool ReadUInt32(uint32_t* result) WARN_UNUSED_RESULT; bool ReadInt64(int64_t* result) WARN_UNUSED_RESULT; bool ReadUInt64(uint64_t* result) WARN_UNUSED_RESULT; - bool ReadSizeT(size_t* result) WARN_UNUSED_RESULT; bool ReadFloat(float* result) WARN_UNUSED_RESULT; bool ReadDouble(double* result) WARN_UNUSED_RESULT; bool ReadString(std::string* result) WARN_UNUSED_RESULT; @@ -122,12 +121,11 @@ class BASE_EXPORT PickleSizer { void AddBool() { return AddInt(); } void AddInt() { AddPOD<int>(); } - void AddLongUsingDangerousNonPortableLessPersistableForm() { AddPOD<long>(); } + void AddLong() { AddPOD<uint64_t>(); } void AddUInt16() { return AddPOD<uint16_t>(); } void AddUInt32() { return AddPOD<uint32_t>(); } void AddInt64() { return AddPOD<int64_t>(); } void AddUInt64() { return AddPOD<uint64_t>(); } - void AddSizeT() { return AddPOD<uint64_t>(); } void AddFloat() { return AddPOD<float>(); } void AddDouble() { return AddPOD<double>(); } void AddString(const StringPiece& value); @@ -229,23 +227,15 @@ class BASE_EXPORT Pickle { bool WriteInt(int value) { return WritePOD(value); } - // WARNING: DO NOT USE THIS METHOD IF PICKLES ARE PERSISTED IN ANY WAY. - // It will write whatever a "long" is on this architecture. On 32-bit - // platforms, it is 32 bits. On 64-bit platforms, it is 64 bits. If persisted - // pickles are still around after upgrading to 64-bit, or if they are copied - // between dissimilar systems, YOUR PICKLES WILL HAVE GONE BAD. - bool WriteLongUsingDangerousNonPortableLessPersistableForm(long value) { - return WritePOD(value); + bool WriteLong(long value) { + // Always write long as a 64-bit value to ensure compatibility between + // 32-bit and 64-bit processes. + return WritePOD(static_cast<int64_t>(value)); } bool WriteUInt16(uint16_t value) { return WritePOD(value); } bool WriteUInt32(uint32_t value) { return WritePOD(value); } bool WriteInt64(int64_t value) { return WritePOD(value); } bool WriteUInt64(uint64_t value) { return WritePOD(value); } - bool WriteSizeT(size_t value) { - // Always write size_t as a 64-bit value to ensure compatibility between - // 32-bit and 64-bit processes. - return WritePOD(static_cast<uint64_t>(value)); - } bool WriteFloat(float value) { return WritePOD(value); } diff --git a/base/pickle_unittest.cc b/base/pickle_unittest.cc index 6dae177..307cb51 100644 --- a/base/pickle_unittest.cc +++ b/base/pickle_unittest.cc @@ -27,7 +27,6 @@ const uint16_t testuint16 = 32123; const uint32_t testuint32 = 1593847192; const int64_t testint64 = -0x7E8CA9253104BDFCLL; const uint64_t testuint64 = 0xCE8CA9253104BDF7ULL; -const size_t testsizet = 0xFEDC7654; const float testfloat = 3.1415926935f; const double testdouble = 2.71828182845904523; const std::string teststring("Hello world"); // note non-aligned string length @@ -73,10 +72,6 @@ void VerifyResult(const Pickle& pickle) { EXPECT_TRUE(iter.ReadUInt64(&outuint64)); EXPECT_EQ(testuint64, outuint64); - size_t outsizet; - EXPECT_TRUE(iter.ReadSizeT(&outsizet)); - EXPECT_EQ(testsizet, outsizet); - float outfloat; EXPECT_TRUE(iter.ReadFloat(&outfloat)); EXPECT_EQ(testfloat, outfloat); @@ -119,13 +114,11 @@ TEST(PickleTest, EncodeDecode) { EXPECT_TRUE(pickle.WriteBool(testbool1)); EXPECT_TRUE(pickle.WriteBool(testbool2)); EXPECT_TRUE(pickle.WriteInt(testint)); - EXPECT_TRUE( - pickle.WriteLongUsingDangerousNonPortableLessPersistableForm(testlong)); + EXPECT_TRUE(pickle.WriteLong(testlong)); EXPECT_TRUE(pickle.WriteUInt16(testuint16)); EXPECT_TRUE(pickle.WriteUInt32(testuint32)); EXPECT_TRUE(pickle.WriteInt64(testint64)); EXPECT_TRUE(pickle.WriteUInt64(testuint64)); - EXPECT_TRUE(pickle.WriteSizeT(testsizet)); EXPECT_TRUE(pickle.WriteFloat(testfloat)); EXPECT_TRUE(pickle.WriteDouble(testdouble)); EXPECT_TRUE(pickle.WriteString(teststring)); @@ -145,25 +138,26 @@ TEST(PickleTest, EncodeDecode) { VerifyResult(pickle3); } -// Tests that reading/writing a size_t works correctly when the source process +// Tests that reading/writing a long works correctly when the source process // is 64-bit. We rely on having both 32- and 64-bit trybots to validate both // arms of the conditional in this test. -TEST(PickleTest, SizeTFrom64Bit) { +TEST(PickleTest, LongFrom64Bit) { Pickle pickle; - // Under the hood size_t is always written as a 64-bit value, so simulate a - // 64-bit size_t even on 32-bit architectures by explicitly writing a - // uint64_t. - EXPECT_TRUE(pickle.WriteUInt64(testuint64)); + // Under the hood long is always written as a 64-bit value, so simulate a + // 64-bit long even on 32-bit architectures by explicitly writing an int64_t. + EXPECT_TRUE(pickle.WriteInt64(testint64)); PickleIterator iter(pickle); - size_t outsizet; - if (sizeof(size_t) < sizeof(uint64_t)) { - // ReadSizeT() should return false when the original written value can't be - // represented as a size_t. - EXPECT_FALSE(iter.ReadSizeT(&outsizet)); + long outlong; + if (sizeof(long) < sizeof(int64_t)) { + // ReadLong() should return false when the original written value can't be + // represented as a long. +#if GTEST_HAS_DEATH_TEST + EXPECT_DEATH(ignore_result(iter.ReadLong(&outlong)), ""); +#endif } else { - EXPECT_TRUE(iter.ReadSizeT(&outsizet)); - EXPECT_EQ(testuint64, outsizet); + EXPECT_TRUE(iter.ReadLong(&outlong)); + EXPECT_EQ(testint64, outlong); } } @@ -556,14 +550,14 @@ TEST(PickleTest, ClaimBytes) { std::string data("Hello, world!"); TestingPickle pickle; - pickle.WriteSizeT(data.size()); + pickle.WriteUInt32(data.size()); void* bytes = pickle.ClaimBytes(data.size()); pickle.WriteInt(42); memcpy(bytes, data.data(), data.size()); PickleIterator iter(pickle); - size_t out_data_length; - EXPECT_TRUE(iter.ReadSizeT(&out_data_length)); + uint32_t out_data_length; + EXPECT_TRUE(iter.ReadUInt32(&out_data_length)); EXPECT_EQ(data.size(), out_data_length); const char* out_data = nullptr; @@ -594,8 +588,8 @@ TEST(PickleTest, PickleSizer) { { TestingPickle pickle; base::PickleSizer sizer; - pickle.WriteLongUsingDangerousNonPortableLessPersistableForm(42); - sizer.AddLongUsingDangerousNonPortableLessPersistableForm(); + pickle.WriteLong(42); + sizer.AddLong(); EXPECT_EQ(sizer.payload_size(), pickle.payload_size()); } { @@ -629,13 +623,6 @@ TEST(PickleTest, PickleSizer) { { TestingPickle pickle; base::PickleSizer sizer; - pickle.WriteSizeT(42); - sizer.AddSizeT(); - EXPECT_EQ(sizer.payload_size(), pickle.payload_size()); - } - { - TestingPickle pickle; - base::PickleSizer sizer; pickle.WriteFloat(42.0f); sizer.AddFloat(); EXPECT_EQ(sizer.payload_size(), pickle.payload_size()); diff --git a/ipc/ipc_message_utils.cc b/ipc/ipc_message_utils.cc index 639cedd..393685b 100644 --- a/ipc/ipc_message_utils.cc +++ b/ipc/ipc_message_utils.cc @@ -414,6 +414,7 @@ void ParamTraits<unsigned int>::Log(const param_type& p, std::string* l) { l->append(base::UintToString(p)); } +#if defined(OS_WIN) || defined(ARCH_CPU_ARM64) || defined(OS_LINUX) void ParamTraits<long>::Log(const param_type& p, std::string* l) { l->append(base::Int64ToString(static_cast<int64_t>(p))); } @@ -421,6 +422,7 @@ void ParamTraits<long>::Log(const param_type& p, std::string* l) { void ParamTraits<unsigned long>::Log(const param_type& p, std::string* l) { l->append(base::Uint64ToString(static_cast<uint64_t>(p))); } +#endif void ParamTraits<long long>::Log(const param_type& p, std::string* l) { l->append(base::Int64ToString(static_cast<int64_t>(p))); @@ -690,7 +692,7 @@ void ParamTraits<base::SharedMemoryHandle>::Write(base::Pickle* m, size_t size = 0; bool result = p.GetSize(&size); DCHECK(result); - ParamTraits<size_t>::Write(m, size); + ParamTraits<uint32_t>::Write(m, static_cast<uint32_t>(size)); // If the caller intended to pass ownership to the IPC stack, release a // reference. @@ -738,11 +740,12 @@ bool ParamTraits<base::SharedMemoryHandle>::Read(const base::Pickle* m, if (!ParamTraits<MachPortMac>::Read(m, iter, &mach_port_mac)) return false; - size_t size; - if (!ParamTraits<size_t>::Read(m, iter, &size)) + uint32_t size; + if (!ParamTraits<uint32_t>::Read(m, iter, &size)) return false; - *r = base::SharedMemoryHandle(mach_port_mac.get_mach_port(), size, + *r = base::SharedMemoryHandle(mach_port_mac.get_mach_port(), + static_cast<size_t>(size), base::GetCurrentProcId()); return true; } diff --git a/ipc/ipc_message_utils.h b/ipc/ipc_message_utils.h index 9ae39c2..ef32e0b 100644 --- a/ipc/ipc_message_utils.h +++ b/ipc/ipc_message_utils.h @@ -182,14 +182,26 @@ struct ParamTraits<unsigned int> { IPC_EXPORT static void Log(const param_type& p, std::string* l); }; +// long isn't safe to send over IPC because it's 4 bytes on 32 bit builds but +// 8 bytes on 64 bit builds. So if a 32 bit and 64 bit process have a channel +// that would cause problem. +// We need to keep this on for a few configs: +// 1) Windows because DWORD is typedef'd to it, which is fine because we have +// very few IPCs that cross this boundary. +// 2) We also need to keep it for Linux for two reasons: int64_t is typedef'd +// to long, and gfx::PluginWindow is long and is used in one GPU IPC. +// 3) Android 64 bit also has int64_t typedef'd to long. +// Since we want to support Android 32<>64 bit IPC, as long as we don't have +// these traits for 32 bit ARM then that'll catch any errors. +#if defined(OS_WIN) || defined(OS_LINUX) || defined(ARCH_CPU_ARM64) template <> struct ParamTraits<long> { typedef long param_type; static void GetSize(base::PickleSizer* sizer, const param_type& p) { - sizer->AddLongUsingDangerousNonPortableLessPersistableForm(); + sizer->AddLong(); } static void Write(base::Pickle* m, const param_type& p) { - m->WriteLongUsingDangerousNonPortableLessPersistableForm(p); + m->WriteLong(p); } static bool Read(const base::Pickle* m, base::PickleIterator* iter, @@ -203,10 +215,10 @@ template <> struct ParamTraits<unsigned long> { typedef unsigned long param_type; static void GetSize(base::PickleSizer* sizer, const param_type& p) { - sizer->AddLongUsingDangerousNonPortableLessPersistableForm(); + sizer->AddLong(); } static void Write(base::Pickle* m, const param_type& p) { - m->WriteLongUsingDangerousNonPortableLessPersistableForm(p); + m->WriteLong(p); } static bool Read(const base::Pickle* m, base::PickleIterator* iter, @@ -215,6 +227,7 @@ struct ParamTraits<unsigned long> { } IPC_EXPORT static void Log(const param_type& p, std::string* l); }; +#endif template <> struct ParamTraits<long long> { |