Skip to content

Commit

Permalink
Fix critical undefined bit-shift length operation
Browse files Browse the repository at this point in the history
Natural/Integer<T>.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<<shift result is valid.
This is safe here regardless of source's signedness, because it's only used in =, &=, ^=, |= operations.
  • Loading branch information
near-san authored and Screwtapello committed Apr 14, 2021
1 parent 029a437 commit 9febc7d
Showing 1 changed file with 16 additions and 8 deletions.
24 changes: 16 additions & 8 deletions nall/primitives/bit-range.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,8 @@ template<int Precision, int Lo, int Hi> struct BitRange {
}

template<typename T> auto& operator=(const T& source) {
target = target & ~mask | source << shift & mask;
type value = source;
target = target & ~mask | value << shift & mask;
return *this;
}

Expand Down Expand Up @@ -104,17 +105,20 @@ template<int Precision, int Lo, int Hi> struct BitRange {
}

template<typename T> auto& operator&=(const T& source) {
target = target & (~mask | source << shift & mask);
type value = source;
target = target & (~mask | value << shift & mask);
return *this;
}

template<typename T> auto& operator^=(const T& source) {
target = target ^ source << shift & mask;
type value = source;
target = target ^ value << shift & mask;
return *this;
}

template<typename T> auto& operator|=(const T& source) {
target = target | source << shift & mask;
type value = source;
target = target | value << shift & mask;
return *this;
}

Expand Down Expand Up @@ -181,7 +185,8 @@ template<typename Type, int Precision = Type::bits()> struct DynamicBitRange {
}

template<typename T> auto& operator=(const T& source) {
target = target & ~mask | source << shift & mask;
type value = source;
target = target & ~mask | value << shift & mask;
return *this;
}

Expand Down Expand Up @@ -228,17 +233,20 @@ template<typename Type, int Precision = Type::bits()> struct DynamicBitRange {
}

template<typename T> auto& operator&=(const T& source) {
target = target & (~mask | source << shift & mask);
type value = source;
target = target & (~mask | value << shift & mask);
return *this;
}

template<typename T> auto& operator^=(const T& source) {
target = target ^ source << shift & mask;
type value = source;
target = target ^ value << shift & mask;
return *this;
}

template<typename T> auto& operator|=(const T& source) {
target = target | source << shift & mask;
type value = source;
target = target | value << shift & mask;
return *this;
}

Expand Down

0 comments on commit 9febc7d

Please sign in to comment.