From a1d62691af2d6c77deeba925cfd0e8172f1d106c Mon Sep 17 00:00:00 2001 From: Tom Jackson Date: Thu, 1 Jun 2017 08:33:55 -0700 Subject: [PATCH] Fix UB in folly/experimental/Bits.h Summary: Test output before the fix is applied: ``` folly/experimental/Bits.h:247:59: runtime error: signed integer overflow: -2147483648 - 1 cannot be represented in type 'int' #0 folly/experimental/Bits.h:247 folly::Bits<...>::set(int*, unsigned long, unsigned long, int) #1 folly/experimental/test/BitsTest.cpp:228 std::enable_if<...>::type (anonymous namespace)::testSet<...>(unsigned char*, unsigned long, unsigned long, int) #2 folly/experimental/test/BitsTest.cpp:263 Bits_Boundaries_Test::TestBody() #17 folly/experimental/test/BitsTest.cpp:381 main ``` Reviewed By: philippv Differential Revision: D5160789 fbshipit-source-id: 43f1926d58f1a5c019d4f8794d10a7a80a5c4749 --- folly/experimental/Bits.h | 3 +-- folly/experimental/test/BitsTest.cpp | 11 +++++++++++ 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/folly/experimental/Bits.h b/folly/experimental/Bits.h index 191cb2d2..03a18c56 100644 --- a/folly/experimental/Bits.h +++ b/folly/experimental/Bits.h @@ -242,8 +242,7 @@ inline void Bits::set(T* p, size_t bitStart, size_t count, size_t countInThisBlock = bitsPerBlock - offset; size_t countInNextBlock = count - countInThisBlock; - UnderlyingType thisBlock = - UnderlyingType(value & ((one << countInThisBlock) - 1)); + UnderlyingType thisBlock = UnderlyingType(value & ones(countInThisBlock)); UnderlyingType nextBlock = UnderlyingType(value >> countInThisBlock); if (std::is_signed::value) { nextBlock &= ones(countInNextBlock); diff --git a/folly/experimental/test/BitsTest.cpp b/folly/experimental/test/BitsTest.cpp index aeff9d35..0a1ec16d 100644 --- a/folly/experimental/test/BitsTest.cpp +++ b/folly/experimental/test/BitsTest.cpp @@ -255,6 +255,17 @@ T testValue(int bits) { } } // anonymous namespace +TEST(Bits, Boundaries) { + uint8_t buf[20]; + for (size_t offset = 0; offset <= 64; ++offset) { + for (size_t size = 0; size <= 32; ++size) { + int32_t value = testValue(size); + testSet(buf, offset, size, value); + EXPECT_EQ(value, (testGet(buf, offset, size))); + } + } +} + template void accSize(size_t& w) { for (size_t s = 0; s <= N; ++s) { -- 2.34.1