Bug 939157 - RotateLeft with shift of zero gives undefined behavior. r=Waldo

This commit is contained in:
Sean Stangl 2015-11-03 14:25:48 -08:00
parent 9e2d8fdf82
commit 24e061fa5a
2 changed files with 15 additions and 1 deletions

View File

@ -647,9 +647,13 @@ class Imm8 : public Operand2
public: public:
static datastore::Imm8mData EncodeImm(uint32_t imm) { static datastore::Imm8mData EncodeImm(uint32_t imm) {
// RotateLeft below may not be called with a shift of zero.
if (imm <= 0xFF)
return datastore::Imm8mData(imm, 0);
// An encodable integer has a maximum of 8 contiguous set bits, // An encodable integer has a maximum of 8 contiguous set bits,
// with an optional wrapped left rotation to even bit positions. // with an optional wrapped left rotation to even bit positions.
for (int rot = 0; rot < 16; rot++) { for (int rot = 1; rot < 16; rot++) {
uint32_t rotimm = mozilla::RotateLeft(imm, rot*2); uint32_t rotimm = mozilla::RotateLeft(imm, rot*2);
if (rotimm <= 0xFF) if (rotimm <= 0xFF)
return datastore::Imm8mData(rotimm, rot); return datastore::Imm8mData(rotimm, rot);

View File

@ -484,6 +484,11 @@ inline T
RotateLeft(const T aValue, uint_fast8_t aShift) RotateLeft(const T aValue, uint_fast8_t aShift)
{ {
MOZ_ASSERT(aShift < sizeof(T) * CHAR_BIT, "Shift value is too large!"); MOZ_ASSERT(aShift < sizeof(T) * CHAR_BIT, "Shift value is too large!");
MOZ_ASSERT(aShift > 0,
"Rotation by value length is undefined behavior, but compilers "
"do not currently fold a test into the rotate instruction. "
"Please remove this restriction when compilers optimize the "
"zero case (http://blog.regehr.org/archives/1063).");
static_assert(IsUnsigned<T>::value, "Rotates require unsigned values"); static_assert(IsUnsigned<T>::value, "Rotates require unsigned values");
return (aValue << aShift) | (aValue >> (sizeof(T) * CHAR_BIT - aShift)); return (aValue << aShift) | (aValue >> (sizeof(T) * CHAR_BIT - aShift));
} }
@ -496,6 +501,11 @@ inline T
RotateRight(const T aValue, uint_fast8_t aShift) RotateRight(const T aValue, uint_fast8_t aShift)
{ {
MOZ_ASSERT(aShift < sizeof(T) * CHAR_BIT, "Shift value is too large!"); MOZ_ASSERT(aShift < sizeof(T) * CHAR_BIT, "Shift value is too large!");
MOZ_ASSERT(aShift > 0,
"Rotation by value length is undefined behavior, but compilers "
"do not currently fold a test into the rotate instruction. "
"Please remove this restriction when compilers optimize the "
"zero case (http://blog.regehr.org/archives/1063).");
static_assert(IsUnsigned<T>::value, "Rotates require unsigned values"); static_assert(IsUnsigned<T>::value, "Rotates require unsigned values");
return (aValue >> aShift) | (aValue << (sizeof(T) * CHAR_BIT - aShift)); return (aValue >> aShift) | (aValue << (sizeof(T) * CHAR_BIT - aShift));
} }