diff --git a/include/llvm/IR/Value.h b/include/llvm/IR/Value.h index 517dd26d300..b7213a67220 100644 --- a/include/llvm/IR/Value.h +++ b/include/llvm/IR/Value.h @@ -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. /// diff --git a/lib/Bitcode/Reader/BitcodeReader.cpp b/lib/Bitcode/Reader/BitcodeReader.cpp index bb6ba6fc6e1..3b3a6eb43d1 100644 --- a/lib/Bitcode/Reader/BitcodeReader.cpp +++ b/lib/Bitcode/Reader/BitcodeReader.cpp @@ -794,6 +794,16 @@ static Attribute::AttrKind GetAttrFromCode(uint64_t Code) { } } +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(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::ParseModule(bool Resume) { 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::ParseModule(bool Resume) { 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::ParseFunctionBody(Function *F) { dyn_cast_or_null(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::ParseFunctionBody(Function *F) { 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::ParseFunctionBody(Function *F) { 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::ParseFunctionBody(Function *F) { cast(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::ParseFunctionBody(Function *F) { 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; } diff --git a/lib/Bitcode/Reader/BitcodeReader.h b/lib/Bitcode/Reader/BitcodeReader.h index 5090be48450..9803e78b929 100644 --- a/lib/Bitcode/Reader/BitcodeReader.h +++ b/lib/Bitcode/Reader/BitcodeReader.h @@ -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(); diff --git a/test/Bitcode/Inputs/invalid-align.bc b/test/Bitcode/Inputs/invalid-align.bc new file mode 100644 index 00000000000..e84fa6cdda5 Binary files /dev/null and b/test/Bitcode/Inputs/invalid-align.bc differ diff --git a/test/Bitcode/invalid.test b/test/Bitcode/invalid.test index 84bc9278d91..fb818884eed 100644 --- a/test/Bitcode/invalid.test +++ b/test/Bitcode/invalid.test @@ -10,6 +10,8 @@ RUN: not llvm-dis -disable-output %p/Inputs/invalid-type-table-forward-ref.bc 2> 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