diff options
author | Alexey Samsonov <vonosmas@gmail.com> | 2014-09-08 19:16:28 +0000 |
---|---|---|
committer | Alexey Samsonov <vonosmas@gmail.com> | 2014-09-08 19:16:28 +0000 |
commit | af023adb86d326f7efeebbbbf28d659e7f73b94f (patch) | |
tree | 9123f3a575f5cae7993d4b490a64bb4df4d1afee | |
parent | 82944983b4aca8389441f3a1aadce51ff572759d (diff) | |
download | bcm5719-llvm-af023adb86d326f7efeebbbbf28d659e7f73b94f.tar.gz bcm5719-llvm-af023adb86d326f7efeebbbbf28d659e7f73b94f.zip |
Be more careful in parsing Module::ModFlagBehavior value
to make sure we don't do invalid load of an enum. Share the
conversion code between llvm::Module implementation and the
verifier.
This bug was reported by UBSan.
llvm-svn: 217395
-rw-r--r-- | llvm/include/llvm/IR/Module.h | 10 | ||||
-rw-r--r-- | llvm/lib/IR/Module.cpp | 19 | ||||
-rw-r--r-- | llvm/lib/IR/Verifier.cpp | 25 |
3 files changed, 36 insertions, 18 deletions
diff --git a/llvm/include/llvm/IR/Module.h b/llvm/include/llvm/IR/Module.h index 51d43af6365..76ec1fd1ec8 100644 --- a/llvm/include/llvm/IR/Module.h +++ b/llvm/include/llvm/IR/Module.h @@ -182,9 +182,17 @@ public: /// Appends the two values, which are required to be metadata /// nodes. However, duplicate entries in the second list are dropped /// during the append operation. - AppendUnique = 6 + AppendUnique = 6, + + // Markers: + ModFlagBehaviorFirstVal = Error, + ModFlagBehaviorLastVal = AppendUnique }; + /// Checks if Value represents a valid ModFlagBehavior, and stores the + /// converted result in MFB. + static bool isValidModFlagBehavior(Value *V, ModFlagBehavior &MFB); + struct ModuleFlagEntry { ModFlagBehavior Behavior; MDString *Key; diff --git a/llvm/lib/IR/Module.cpp b/llvm/lib/IR/Module.cpp index 98e4706019c..7f673d07e92 100644 --- a/llvm/lib/IR/Module.cpp +++ b/llvm/lib/IR/Module.cpp @@ -259,6 +259,17 @@ void Module::eraseNamedMetadata(NamedMDNode *NMD) { NamedMDList.erase(NMD); } +bool Module::isValidModFlagBehavior(Value *V, ModFlagBehavior &MFB) { + if (ConstantInt *Behavior = dyn_cast<ConstantInt>(V)) { + uint64_t Val = Behavior->getLimitedValue(); + if (Val >= ModFlagBehaviorFirstVal && Val <= ModFlagBehaviorLastVal) { + MFB = static_cast<ModFlagBehavior>(Val); + return true; + } + } + return false; +} + /// getModuleFlagsMetadata - Returns the module flags in the provided vector. void Module:: getModuleFlagsMetadata(SmallVectorImpl<ModuleFlagEntry> &Flags) const { @@ -266,15 +277,15 @@ getModuleFlagsMetadata(SmallVectorImpl<ModuleFlagEntry> &Flags) const { if (!ModFlags) return; for (const MDNode *Flag : ModFlags->operands()) { - if (Flag->getNumOperands() >= 3 && isa<ConstantInt>(Flag->getOperand(0)) && + ModFlagBehavior MFB; + if (Flag->getNumOperands() >= 3 && + isValidModFlagBehavior(Flag->getOperand(0), MFB) && isa<MDString>(Flag->getOperand(1))) { // Check the operands of the MDNode before accessing the operands. // The verifier will actually catch these failures. - ConstantInt *Behavior = cast<ConstantInt>(Flag->getOperand(0)); MDString *Key = cast<MDString>(Flag->getOperand(1)); Value *Val = Flag->getOperand(2); - Flags.push_back(ModuleFlagEntry(ModFlagBehavior(Behavior->getZExtValue()), - Key, Val)); + Flags.push_back(ModuleFlagEntry(MFB, Key, Val)); } } } diff --git a/llvm/lib/IR/Verifier.cpp b/llvm/lib/IR/Verifier.cpp index 0df257da4a4..1a182db9277 100644 --- a/llvm/lib/IR/Verifier.cpp +++ b/llvm/lib/IR/Verifier.cpp @@ -673,24 +673,23 @@ Verifier::visitModuleFlag(const MDNode *Op, // constant int), the flag ID (an MDString), and the value. Assert1(Op->getNumOperands() == 3, "incorrect number of operands in module flag", Op); - ConstantInt *Behavior = dyn_cast<ConstantInt>(Op->getOperand(0)); + Module::ModFlagBehavior MFB; + if (!Module::isValidModFlagBehavior(Op->getOperand(0), MFB)) { + Assert1( + dyn_cast<ConstantInt>(Op->getOperand(0)), + "invalid behavior operand in module flag (expected constant integer)", + Op->getOperand(0)); + Assert1(false, + "invalid behavior operand in module flag (unexpected constant)", + Op->getOperand(0)); + } MDString *ID = dyn_cast<MDString>(Op->getOperand(1)); - Assert1(Behavior, - "invalid behavior operand in module flag (expected constant integer)", - Op->getOperand(0)); - unsigned BehaviorValue = Behavior->getZExtValue(); Assert1(ID, "invalid ID operand in module flag (expected metadata string)", Op->getOperand(1)); // Sanity check the values for behaviors with additional requirements. - switch (BehaviorValue) { - default: - Assert1(false, - "invalid behavior operand in module flag (unexpected constant)", - Op->getOperand(0)); - break; - + switch (MFB) { case Module::Error: case Module::Warning: case Module::Override: @@ -726,7 +725,7 @@ Verifier::visitModuleFlag(const MDNode *Op, } // Unless this is a "requires" flag, check the ID is unique. - if (BehaviorValue != Module::Require) { + if (MFB != Module::Require) { bool Inserted = SeenIDs.insert(std::make_pair(ID, Op)).second; Assert1(Inserted, "module flag identifiers must be unique (or of 'require' type)", |