Be more careful about sign extension in FXSYS_UINT32_GET_MSBFIRST() etc. Make definition consistent with those used in fdrm/, which guard against being applied to a signed char* ptr, getting back, say, a -28, then sign-extending 1s when casting to uint32_t. We don't seem to do this anywhere, but it is a good safeguard. -- Add tests which flunk prior to this change. Change-Id: I9993d6420947e5d0cd7478424747f7e701045428 Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/86974 Commit-Queue: Tom Sepez <tsepez@chromium.org> Reviewed-by: Lei Zhang <thestig@chromium.org>
diff --git a/core/fxcrt/byteorder_unittest.cpp b/core/fxcrt/byteorder_unittest.cpp index 1133a8a..11c3024 100644 --- a/core/fxcrt/byteorder_unittest.cpp +++ b/core/fxcrt/byteorder_unittest.cpp
@@ -25,6 +25,10 @@ uint16_t expected = FXSYS_UINT16_GET_LSBFIRST(reinterpret_cast<const uint8_t*>(&v16)); EXPECT_EQ(expected, ByteSwapToLE16(v16)) << v; + + // Check safety against unexpectedly signed bytes. + expected = FXSYS_UINT16_GET_LSBFIRST(reinterpret_cast<const int8_t*>(&v16)); + EXPECT_EQ(expected, ByteSwapToLE16(v16)) << v; } } @@ -33,6 +37,10 @@ uint32_t expected = FXSYS_UINT32_GET_LSBFIRST(reinterpret_cast<const uint8_t*>(&v)); EXPECT_EQ(expected, ByteSwapToLE32(v)) << v; + + // Check safety against unexpectedly signed bytes. + expected = FXSYS_UINT32_GET_LSBFIRST(reinterpret_cast<const int8_t*>(&v)); + EXPECT_EQ(expected, ByteSwapToLE32(v)) << v; } } @@ -43,6 +51,10 @@ uint16_t expected = FXSYS_UINT16_GET_MSBFIRST(reinterpret_cast<const uint8_t*>(&v16)); EXPECT_EQ(expected, ByteSwapToBE16(v16)) << v; + + // Check safety against unexpectedly signed bytes. + expected = FXSYS_UINT16_GET_MSBFIRST(reinterpret_cast<const int8_t*>(&v16)); + EXPECT_EQ(expected, ByteSwapToBE16(v16)) << v; } } @@ -51,6 +63,10 @@ uint32_t expected = FXSYS_UINT32_GET_MSBFIRST(reinterpret_cast<const uint8_t*>(&v)); EXPECT_EQ(expected, ByteSwapToBE32(v)) << v; + + // Check safety against unexpectedly signed bytes. + expected = FXSYS_UINT32_GET_MSBFIRST(reinterpret_cast<const int8_t*>(&v)); + EXPECT_EQ(expected, ByteSwapToBE32(v)) << v; } }
diff --git a/core/fxcrt/fx_system.h b/core/fxcrt/fx_system.h index b0d4ccf..03ce86b 100644 --- a/core/fxcrt/fx_system.h +++ b/core/fxcrt/fx_system.h
@@ -118,20 +118,24 @@ } // Could be C, but uses C++-style casting. -#define FXSYS_UINT16_GET_LSBFIRST(p) \ - (static_cast<uint16_t>((static_cast<uint32_t>((p)[1]) << 8) | \ - (static_cast<uint32_t>((p)[0])))) -#define FXSYS_UINT16_GET_MSBFIRST(p) \ - (static_cast<uint16_t>((static_cast<uint32_t>((p)[0]) << 8) | \ - (static_cast<uint32_t>((p)[1])))) -#define FXSYS_UINT32_GET_LSBFIRST(p) \ - ((static_cast<uint32_t>((p)[3]) << 24) | \ - (static_cast<uint32_t>((p)[2]) << 16) | \ - (static_cast<uint32_t>((p)[1]) << 8) | (static_cast<uint32_t>((p)[0]))) -#define FXSYS_UINT32_GET_MSBFIRST(p) \ - ((static_cast<uint32_t>((p)[0]) << 24) | \ - (static_cast<uint32_t>((p)[1]) << 16) | \ - (static_cast<uint32_t>((p)[2]) << 8) | (static_cast<uint32_t>((p)[3]))) +#define FXSYS_UINT16_GET_LSBFIRST(p) \ + (static_cast<uint16_t>( \ + (static_cast<uint32_t>(static_cast<uint8_t>((p)[1])) << 8) | \ + (static_cast<uint32_t>(static_cast<uint8_t>((p)[0]))))) +#define FXSYS_UINT16_GET_MSBFIRST(p) \ + (static_cast<uint16_t>( \ + (static_cast<uint32_t>(static_cast<uint8_t>((p)[0])) << 8) | \ + (static_cast<uint32_t>(static_cast<uint8_t>((p)[1]))))) +#define FXSYS_UINT32_GET_LSBFIRST(p) \ + ((static_cast<uint32_t>(static_cast<uint8_t>((p)[3])) << 24) | \ + (static_cast<uint32_t>(static_cast<uint8_t>((p)[2])) << 16) | \ + (static_cast<uint32_t>(static_cast<uint8_t>((p)[1])) << 8) | \ + (static_cast<uint32_t>(static_cast<uint8_t>((p)[0])))) +#define FXSYS_UINT32_GET_MSBFIRST(p) \ + ((static_cast<uint32_t>(static_cast<uint8_t>((p)[0])) << 24) | \ + (static_cast<uint32_t>(static_cast<uint8_t>((p)[1])) << 16) | \ + (static_cast<uint32_t>(static_cast<uint8_t>((p)[2])) << 8) | \ + (static_cast<uint32_t>(static_cast<uint8_t>((p)[3])))) #endif // __cplusplus #endif // CORE_FXCRT_FX_SYSTEM_H_