Bug 939157 - RotateLeft with shift of zero gives undefined behavior. r=waldo, a=ritu
authorSean Stangl <sstangl@mozilla.com>
Tue, 03 Nov 2015 14:25:48 -0800
changeset 303813 52c158ae017886ecdf45f971522452cf13b2cf6e
parent 303812 c20f357d2bbc41f9ab11a748129eb760f36a8362
child 303814 0b9508fe071f1654d18c87bb0b4fb7c32b174e75
push id5392
push userraliiev@mozilla.com
push dateMon, 14 Dec 2015 20:08:23 +0000
treeherdermozilla-beta@16ce8562a975 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerswaldo, ritu
bugs939157
milestone44.0a2
Bug 939157 - RotateLeft with shift of zero gives undefined behavior. r=waldo, a=ritu
js/src/jit/arm/Assembler-arm.h
mfbt/MathAlgorithms.h
--- a/js/src/jit/arm/Assembler-arm.h
+++ b/js/src/jit/arm/Assembler-arm.h
@@ -642,19 +642,23 @@ class Imm8 : public Operand2
 {
   public:
     explicit Imm8(uint32_t imm)
       : Operand2(EncodeImm(imm))
     { }
 
   public:
     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,
         // 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);
             if (rotimm <= 0xFF)
                 return datastore::Imm8mData(rotimm, rot);
         }
         return datastore::Imm8mData();
     }
 
     // Pair template?
--- a/mfbt/MathAlgorithms.h
+++ b/mfbt/MathAlgorithms.h
@@ -479,28 +479,30 @@ RoundUpPow2(size_t aValue)
 /**
  * Rotates the bits of the given value left by the amount of the shift width.
  */
 template<typename T>
 inline T
 RotateLeft(const T aValue, uint_fast8_t aShift)
 {
   MOZ_ASSERT(aShift < sizeof(T) * CHAR_BIT, "Shift value is too large!");
+  MOZ_ASSERT(aShift > 0, "Right shift by value size undefined (See Bug 939157).");
   static_assert(IsUnsigned<T>::value, "Rotates require unsigned values");
   return (aValue << aShift) | (aValue >> (sizeof(T) * CHAR_BIT - aShift));
 }
 
 /**
  * Rotates the bits of the given value right by the amount of the shift width.
  */
 template<typename T>
 inline T
 RotateRight(const T aValue, uint_fast8_t aShift)
 {
   MOZ_ASSERT(aShift < sizeof(T) * CHAR_BIT, "Shift value is too large!");
+  MOZ_ASSERT(aShift > 0, "Left shift by value size undefined (See Bug 939157).");
   static_assert(IsUnsigned<T>::value, "Rotates require unsigned values");
   return (aValue >> aShift) | (aValue << (sizeof(T) * CHAR_BIT - aShift));
 }
 
 /**
  * Returns true if |x| is a power of two.
  * Zero is not an integer power of two. (-Inf is not an integer)
  */