From: Marco Bettini Date: Mon, 29 Nov 2021 14:05:29 +0000 (+0100) Subject: lib: bits_rotXYY() - Replace signed expression with UNSIGNED_MINUS() macro for unsign... X-Git-Tag: 2.3.18~101 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=668bdc6838d64bb68e63c16d28ee8c620f40bff2;p=thirdparty%2Fdovecot%2Fcore.git lib: bits_rotXYY() - Replace signed expression with UNSIGNED_MINUS() macro for unsigned 2's complement Found by code analysis tool --- diff --git a/src/lib/bits.h b/src/lib/bits.h index 3b761f11b6..2e84755be0 100644 --- a/src/lib/bits.h +++ b/src/lib/bits.h @@ -17,6 +17,10 @@ /* ((val & bits) == bits) is uncommon */ #define HAS_ALL_BITS(val,bits) ((~(val) & (bits)) == 0) +/* negation implemented without using the subtraction operator + ~(x - 1) = 1 + ~x these are equivalent by -(-x) == ~(~(x)) == x */ +#define UNSIGNED_MINUS(x) (1 + ~(x)) + /* Returns x, such that x is the smallest power of 2 >= num. */ size_t nearest_power(size_t num) ATTR_CONST; @@ -84,7 +88,7 @@ bits_rotl64(uint64_t num, unsigned int count) { const unsigned int mask = CHAR_BIT*sizeof(num) - 1; count &= mask; - return (num << count) | (num >> (-count & mask)); + return (num << count) | (num >> (UNSIGNED_MINUS(count) & mask)); } static inline uint32_t ATTR_NO_SANITIZE_INTEGER @@ -93,7 +97,7 @@ bits_rotl32(uint32_t num, unsigned int count) { const unsigned int mask = CHAR_BIT*sizeof(num) - 1; count &= mask; - return (num << count) | (num >> (-count & mask)); + return (num << count) | (num >> (UNSIGNED_MINUS(count) & mask)); } static inline uint64_t ATTR_NO_SANITIZE_INTEGER @@ -102,7 +106,7 @@ bits_rotr64(uint64_t num, unsigned int count) { const unsigned int mask = CHAR_BIT*sizeof(num) - 1; count &= mask; - return (num >> count) | (num << (-count & mask)); + return (num >> count) | (num << (UNSIGNED_MINUS(count) & mask)); } static inline uint32_t ATTR_NO_SANITIZE_INTEGER @@ -111,7 +115,7 @@ bits_rotr32(uint32_t num, unsigned int count) { const unsigned int mask = CHAR_BIT*sizeof(num) - 1; count &= mask; - return (num >> count) | (num << (-count & mask)); + return (num >> count) | (num << (UNSIGNED_MINUS(count) & mask)); } /* These functions look too big to be inline, but in almost all expected diff --git a/src/lib/test-bits.c b/src/lib/test-bits.c index c43209aa6b..d091dc5bc7 100644 --- a/src/lib/test-bits.c +++ b/src/lib/test-bits.c @@ -6,6 +6,44 @@ #include +static void test_bits_unsigned_minus(void) +{ + test_begin("bits_unsigned_minus()"); + + // 32 bit + test_assert(UNSIGNED_MINUS(0x00000000U) == 0x00000000U); + + test_assert(UNSIGNED_MINUS(0x00000001U) == 0xffffffffU); + test_assert(UNSIGNED_MINUS(0x00000002U) == 0xfffffffeU); + test_assert(UNSIGNED_MINUS(0x00000003U) == 0xfffffffdU); + //.. + test_assert(UNSIGNED_MINUS(0x7fffffffU) == 0x80000001U); + test_assert(UNSIGNED_MINUS(0x80000000U) == 0x80000000U); + test_assert(UNSIGNED_MINUS(0x80000001U) == 0x7fffffffU); + //.. + test_assert(UNSIGNED_MINUS(0xffffffffU) == 0x00000001U); + test_assert(UNSIGNED_MINUS(0xfffffffeU) == 0x00000002U); + test_assert(UNSIGNED_MINUS(0xfffffffdU) == 0x00000003U); + + // 64 bit + test_assert(UNSIGNED_MINUS(0x0000000000000000ULL) == 0x0000000000000000ULL); + + test_assert(UNSIGNED_MINUS(0x0000000000000001ULL) == 0xffffffffffffffffULL); + test_assert(UNSIGNED_MINUS(0x0000000000000002ULL) == 0xfffffffffffffffeULL); + test_assert(UNSIGNED_MINUS(0x0000000000000003ULL) == 0xfffffffffffffffdULL); + //.. + test_assert(UNSIGNED_MINUS(0x7fffffffffffffffULL) == 0x8000000000000001ULL); + test_assert(UNSIGNED_MINUS(0x8000000000000000ULL) == 0x8000000000000000ULL); + test_assert(UNSIGNED_MINUS(0x8000000000000001ULL) == 0x7fffffffffffffffULL); + //.. + test_assert(UNSIGNED_MINUS(0xffffffffffffffffULL) == 0x0000000000000001ULL); + test_assert(UNSIGNED_MINUS(0xfffffffffffffffeULL) == 0x0000000000000002ULL); + test_assert(UNSIGNED_MINUS(0xfffffffffffffffdULL) == 0x0000000000000003ULL); + + test_end(); +} + + /* nearest_power(0) = error bits_requiredXX(0) = 0 nearest_power(1) = 1 = 1<<0 bits_requiredXX(1) = 1 nearest_power(2) = 2 = 1<<1 bits_requiredXX(2) = 2 @@ -156,6 +194,7 @@ static void test_bits_rotl32(void) test_assert(bits_rotl32(0x1c00000eU, 3) == 0xe0000070U); test_assert(bits_rotl32(0xe0000070U, 5) == 0x00000e1cU); test_assert(bits_rotl32(0x00000e1cU, 0) == 0x00000e1cU); + test_assert(bits_rotl32(0x1c00000eU, 3 + 32) == 0xe0000070U); test_end(); } @@ -167,6 +206,7 @@ static void test_bits_rotl64(void) test_assert(bits_rotl64(0x1c0000000000000eUL, 3) == 0xe000000000000070UL); test_assert(bits_rotl64(0xe000000000000070UL, 5) == 0x0000000000000e1cUL); test_assert(bits_rotl64(0x0000000000000e1cUL, 0) == 0x0000000000000e1cUL); + test_assert(bits_rotl64(0x1c0000000000000eUL, 3 + 64) == 0xe000000000000070UL); test_end(); } @@ -178,6 +218,7 @@ static void test_bits_rotr32(void) test_assert(bits_rotr32(0x1c00000eU, 3) == 0xc3800001U); test_assert(bits_rotr32(0xc3800001U, 5) == 0x0e1c0000U); test_assert(bits_rotr32(0x00000e1cU, 0) == 0x00000e1cU); + test_assert(bits_rotr32(0x1c00000eU, 3 + 32) == 0xc3800001U); test_end(); } @@ -189,6 +230,7 @@ static void test_bits_rotr64(void) test_assert(bits_rotr64(0x1c0000000000000eUL, 3) == 0xc380000000000001UL); test_assert(bits_rotr64(0xc380000000000001UL, 5) == 0x0e1c000000000000UL); test_assert(bits_rotr64(0x0000000000000e1cUL, 0) == 0x0000000000000e1cUL); + test_assert(bits_rotr64(0x1c0000000000000eUL, 3 + 64) == 0xc380000000000001UL); test_end(); } @@ -224,6 +266,7 @@ static void test_bit_tests(void) void test_bits(void) { + test_bits_unsigned_minus(); test_nearest_power(); test_bits_is_power_of_two(); test_bits_requiredXX();