[llvm] r230180 - Use common parse routine to read alignment values from bitcode

JF Bastien jfb at google.com
Sun Feb 22 11:32:03 PST 2015


Author: jfb
Date: Sun Feb 22 13:32:03 2015
New Revision: 230180

URL: http://llvm.org/viewvc/llvm-project?rev=230180&view=rev
Log:
Use common parse routine to read alignment values from bitcode

While fuzzing LLVM bitcode files, I discovered that (1) the bitcode reader doesn't check that alignments are no larger than 2**29; (2) downstream code doesn't check the range; and (3) for values out of range, corresponding large memory requests (based on alignment size) will fail. This code fixes the bitcode reader to check for valid alignments, fixing this problem.

This CL fixes alignment value on global variables, functions, and instructions: alloca, load, load atomic, store, store atomic.

Patch by Karl Schimpf (kschimpf at google.com).

Added:
    llvm/trunk/test/Bitcode/Inputs/invalid-align.bc
Modified:
    llvm/trunk/include/llvm/IR/Value.h
    llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp
    llvm/trunk/lib/Bitcode/Reader/BitcodeReader.h
    llvm/trunk/test/Bitcode/invalid.test

Modified: llvm/trunk/include/llvm/IR/Value.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/Value.h?rev=230180&r1=230179&r2=230180&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/Value.h (original)
+++ llvm/trunk/include/llvm/IR/Value.h Sun Feb 22 13:32:03 2015
@@ -469,7 +469,8 @@ public:
   ///
   /// This is the greatest alignment value supported by load, store, and alloca
   /// instructions, and global values.
-  static const unsigned MaximumAlignment = 1u << 29;
+  static const unsigned MaxAlignmentExponent = 29;
+  static const unsigned MaximumAlignment = 1u << MaxAlignmentExponent;
 
   /// \brief Mutate the type of this Value to be of the specified type.
   ///

Modified: llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp?rev=230180&r1=230179&r2=230180&view=diff
==============================================================================
--- llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp (original)
+++ llvm/trunk/lib/Bitcode/Reader/BitcodeReader.cpp Sun Feb 22 13:32:03 2015
@@ -794,6 +794,16 @@ static Attribute::AttrKind GetAttrFromCo
   }
 }
 
+std::error_code BitcodeReader::parseAlignmentValue(uint64_t Exponent,
+                                                   unsigned &Alignment) {
+  // Note: Alignment in bitcode files is incremented by 1, so that zero
+  // can be used for default alignment.
+  if (Exponent > Value::MaxAlignmentExponent + 1)
+    return Error("Invalid alignment value");
+  Alignment = (1 << static_cast<unsigned>(Exponent)) >> 1;
+  return std::error_code();
+}
+
 std::error_code BitcodeReader::ParseAttrKind(uint64_t Code,
                                              Attribute::AttrKind *Kind) {
   *Kind = GetAttrFromCode(Code);
@@ -2462,7 +2472,9 @@ std::error_code BitcodeReader::ParseModu
       bool isConstant = Record[1];
       uint64_t RawLinkage = Record[3];
       GlobalValue::LinkageTypes Linkage = getDecodedLinkage(RawLinkage);
-      unsigned Alignment = (1 << Record[4]) >> 1;
+      unsigned Alignment;
+      if (std::error_code EC = parseAlignmentValue(Record[4], Alignment))
+        return EC;
       std::string Section;
       if (Record[5]) {
         if (Record[5]-1 >= SectionTable.size())
@@ -2542,7 +2554,10 @@ std::error_code BitcodeReader::ParseModu
       Func->setLinkage(getDecodedLinkage(RawLinkage));
       Func->setAttributes(getAttributes(Record[4]));
 
-      Func->setAlignment((1 << Record[5]) >> 1);
+      unsigned Alignment;
+      if (std::error_code EC = parseAlignmentValue(Record[5], Alignment))
+        return EC;
+      Func->setAlignment(Alignment);
       if (Record[6]) {
         if (Record[6]-1 >= SectionTable.size())
           return Error("Invalid ID");
@@ -3539,12 +3554,17 @@ std::error_code BitcodeReader::ParseFunc
         dyn_cast_or_null<PointerType>(getTypeByID(Record[0]));
       Type *OpTy = getTypeByID(Record[1]);
       Value *Size = getFnValueByID(Record[2], OpTy);
-      unsigned AlignRecord = Record[3];
-      bool InAlloca = AlignRecord & (1 << 5);
-      unsigned Align = AlignRecord & ((1 << 5) - 1);
+      uint64_t AlignRecord = Record[3];
+      const uint64_t InAllocaMask = uint64_t(1) << 5;
+      bool InAlloca = AlignRecord & InAllocaMask;
+      unsigned Align;
+      if (std::error_code EC =
+          parseAlignmentValue(AlignRecord & ~InAllocaMask, Align)) {
+        return EC;
+      }
       if (!Ty || !Size)
         return Error("Invalid record");
-      AllocaInst *AI = new AllocaInst(Ty->getElementType(), Size, (1 << Align) >> 1);
+      AllocaInst *AI = new AllocaInst(Ty->getElementType(), Size, Align);
       AI->setUsedWithInAlloca(InAlloca);
       I = AI;
       InstructionList.push_back(I);
@@ -3556,8 +3576,10 @@ std::error_code BitcodeReader::ParseFunc
       if (getValueTypePair(Record, OpNum, NextValueNo, Op) ||
           OpNum+2 != Record.size())
         return Error("Invalid record");
-
-      I = new LoadInst(Op, "", Record[OpNum+1], (1 << Record[OpNum]) >> 1);
+      unsigned Align;
+      if (std::error_code EC = parseAlignmentValue(Record[OpNum], Align))
+        return EC;
+      I = new LoadInst(Op, "", Record[OpNum+1], Align);
       InstructionList.push_back(I);
       break;
     }
@@ -3577,8 +3599,10 @@ std::error_code BitcodeReader::ParseFunc
         return Error("Invalid record");
       SynchronizationScope SynchScope = GetDecodedSynchScope(Record[OpNum+3]);
 
-      I = new LoadInst(Op, "", Record[OpNum+1], (1 << Record[OpNum]) >> 1,
-                       Ordering, SynchScope);
+      unsigned Align;
+      if (std::error_code EC = parseAlignmentValue(Record[OpNum], Align))
+        return EC;
+      I = new LoadInst(Op, "", Record[OpNum+1], Align, Ordering, SynchScope);
       InstructionList.push_back(I);
       break;
     }
@@ -3590,8 +3614,10 @@ std::error_code BitcodeReader::ParseFunc
                     cast<PointerType>(Ptr->getType())->getElementType(), Val) ||
           OpNum+2 != Record.size())
         return Error("Invalid record");
-
-      I = new StoreInst(Val, Ptr, Record[OpNum+1], (1 << Record[OpNum]) >> 1);
+      unsigned Align;
+      if (std::error_code EC = parseAlignmentValue(Record[OpNum], Align))
+        return EC;
+      I = new StoreInst(Val, Ptr, Record[OpNum+1], Align);
       InstructionList.push_back(I);
       break;
     }
@@ -3613,8 +3639,10 @@ std::error_code BitcodeReader::ParseFunc
       if (Ordering != NotAtomic && Record[OpNum] == 0)
         return Error("Invalid record");
 
-      I = new StoreInst(Val, Ptr, Record[OpNum+1], (1 << Record[OpNum]) >> 1,
-                        Ordering, SynchScope);
+      unsigned Align;
+      if (std::error_code EC = parseAlignmentValue(Record[OpNum], Align))
+        return EC;
+      I = new StoreInst(Val, Ptr, Record[OpNum+1], Align, Ordering, SynchScope);
       InstructionList.push_back(I);
       break;
     }

Modified: llvm/trunk/lib/Bitcode/Reader/BitcodeReader.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Bitcode/Reader/BitcodeReader.h?rev=230180&r1=230179&r2=230180&view=diff
==============================================================================
--- llvm/trunk/lib/Bitcode/Reader/BitcodeReader.h (original)
+++ llvm/trunk/lib/Bitcode/Reader/BitcodeReader.h Sun Feb 22 13:32:03 2015
@@ -335,6 +335,10 @@ private:
     return getFnValueByID(ValNo, Ty);
   }
 
+  /// Converts alignment exponent (i.e. power of two (or zero)) to the
+  /// corresponding alignment to use. If alignment is too large, returns
+  /// a corresponding error code.
+  std::error_code parseAlignmentValue(uint64_t Exponent, unsigned &Alignment);
   std::error_code ParseAttrKind(uint64_t Code, Attribute::AttrKind *Kind);
   std::error_code ParseModule(bool Resume);
   std::error_code ParseAttributeBlock();

Added: llvm/trunk/test/Bitcode/Inputs/invalid-align.bc
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Bitcode/Inputs/invalid-align.bc?rev=230180&view=auto
==============================================================================
Binary files llvm/trunk/test/Bitcode/Inputs/invalid-align.bc (added) and llvm/trunk/test/Bitcode/Inputs/invalid-align.bc Sun Feb 22 13:32:03 2015 differ

Modified: llvm/trunk/test/Bitcode/invalid.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Bitcode/invalid.test?rev=230180&r1=230179&r2=230180&view=diff
==============================================================================
--- llvm/trunk/test/Bitcode/invalid.test (original)
+++ llvm/trunk/test/Bitcode/invalid.test Sun Feb 22 13:32:03 2015
@@ -10,6 +10,8 @@ RUN: not llvm-dis -disable-output %p/Inp
 RUN:   FileCheck --check-prefix=BAD-TYPE-TABLE-FORWARD-REF %s
 RUN: not llvm-dis -disable-output %p/Inputs/invalid-bitwidth.bc 2>&1 | \
 RUN:   FileCheck --check-prefix=BAD-BITWIDTH %s
+RUN: not llvm-dis -disable-output %p/Inputs/invalid-align.bc  2>&1 | \
+RUN:   FileCheck --check-prefix=BAD-ALIGN %s
 
 INVALID-ENCODING: Invalid encoding
 BAD-ABBREV: Abbreviation starts with an Array or a Blob
@@ -17,6 +19,7 @@ UNEXPECTED-EOF: Unexpected end of file
 BAD-ABBREV-NUMBER: Invalid abbrev number
 BAD-TYPE-TABLE-FORWARD-REF: Invalid TYPE table: Only named structs can be forward referenced
 BAD-BITWIDTH: Bitwidth for integer type out of range
+BAD-ALIGN: Invalid alignment value
 
 RUN: not llvm-dis -disable-output %p/Inputs/invalid-extractval-array-idx.bc 2>&1 | \
 RUN:   FileCheck --check-prefix=EXTRACT-ARRAY %s





More information about the llvm-commits mailing list