mirror of https://github.com/bsnes-emu/bsnes.git
Fix critical undefined bit-shift length operation
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.
This commit is contained in:
parent
4ea984b688
commit
55e05c89c2
|
@ -58,7 +58,8 @@ template<int Precision, int Lo, int Hi> struct BitRange<Precision, Lo, Hi> {
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T> inline auto& operator=(const T& source) {
|
template<typename T> inline auto& operator=(const T& source) {
|
||||||
target = target & ~mask | source << shift & mask;
|
type value = source;
|
||||||
|
target = target & ~mask | value << shift & mask;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,17 +106,20 @@ template<int Precision, int Lo, int Hi> struct BitRange<Precision, Lo, Hi> {
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T> inline auto& operator&=(const T& source) {
|
template<typename T> inline auto& operator&=(const T& source) {
|
||||||
target = target & (~mask | source << shift & mask);
|
type value = source;
|
||||||
|
target = target & (~mask | value << shift & mask);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T> inline auto& operator^=(const T& source) {
|
template<typename T> inline auto& operator^=(const T& source) {
|
||||||
target = target ^ source << shift & mask;
|
type value = source;
|
||||||
|
target = target ^ value << shift & mask;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T> inline auto& operator|=(const T& source) {
|
template<typename T> inline auto& operator|=(const T& source) {
|
||||||
target = target | source << shift & mask;
|
type value = source;
|
||||||
|
target = target | value << shift & mask;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -185,7 +189,8 @@ template<int Precision> struct BitRange<Precision> {
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T> inline auto& operator=(const T& source) {
|
template<typename T> inline auto& operator=(const T& source) {
|
||||||
target = target & ~mask | source << shift & mask;
|
type value = source;
|
||||||
|
target = target & ~mask | value << shift & mask;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -232,17 +237,20 @@ template<int Precision> struct BitRange<Precision> {
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T> inline auto& operator&=(const T& source) {
|
template<typename T> inline auto& operator&=(const T& source) {
|
||||||
target = target & (~mask | source << shift & mask);
|
type value = source;
|
||||||
|
target = target & (~mask | value << shift & mask);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T> inline auto& operator^=(const T& source) {
|
template<typename T> inline auto& operator^=(const T& source) {
|
||||||
target = target ^ source << shift & mask;
|
type value = source;
|
||||||
|
target = target ^ value << shift & mask;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T> inline auto& operator|=(const T& source) {
|
template<typename T> inline auto& operator|=(const T& source) {
|
||||||
target = target | source << shift & mask;
|
type value = source;
|
||||||
|
target = target | value << shift & mask;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue