From f231bb6aeddd68d5b09d9dbab3f73cf6e716b230 Mon Sep 17 00:00:00 2001 From: Near <77224854+near-san@users.noreply.github.com> Date: Wed, 14 Apr 2021 08:18:25 -0400 Subject: [PATCH] Fix critical undefined bit-shift length operation Natural/Integer.bit() (BitRange) was shifting by whatever type the source was to match the target bit length. But this breaks when the target type is u64/s64 and the source type is u32/s32 or smaller. Shifting by >=32 becomes undefined behavior. We have to cast the input source to the target type first, so that the source< struct BitRange { } template inline auto& operator=(const T& source) { - target = target & ~mask | source << shift & mask; + type value = source; + target = target & ~mask | value << shift & mask; return *this; } @@ -105,17 +106,20 @@ template struct BitRange { } template inline auto& operator&=(const T& source) { - target = target & (~mask | source << shift & mask); + type value = source; + target = target & (~mask | value << shift & mask); return *this; } template inline auto& operator^=(const T& source) { - target = target ^ source << shift & mask; + type value = source; + target = target ^ value << shift & mask; return *this; } template inline auto& operator|=(const T& source) { - target = target | source << shift & mask; + type value = source; + target = target | value << shift & mask; return *this; } @@ -185,7 +189,8 @@ template struct BitRange { } template inline auto& operator=(const T& source) { - target = target & ~mask | source << shift & mask; + type value = source; + target = target & ~mask | value << shift & mask; return *this; } @@ -232,17 +237,20 @@ template struct BitRange { } template inline auto& operator&=(const T& source) { - target = target & (~mask | source << shift & mask); + type value = source; + target = target & (~mask | value << shift & mask); return *this; } template inline auto& operator^=(const T& source) { - target = target ^ source << shift & mask; + type value = source; + target = target ^ value << shift & mask; return *this; } template inline auto& operator|=(const T& source) { - target = target | source << shift & mask; + type value = source; + target = target | value << shift & mask; return *this; }