From e769dc39fd90640b71bb3c5b473eee5291804648 Mon Sep 17 00:00:00 2001 From: Alexey Samsonov Date: Mon, 8 Sep 2014 19:16:28 +0000 Subject: [PATCH] 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. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@217395 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/IR/Module.h | 10 +++++++++- lib/IR/Module.cpp | 19 +++++++++++++++---- lib/IR/Verifier.cpp | 25 ++++++++++++------------- 3 files changed, 36 insertions(+), 18 deletions(-) diff --git a/include/llvm/IR/Module.h b/include/llvm/IR/Module.h index 51d43af6365..76ec1fd1ec8 100644 --- a/include/llvm/IR/Module.h +++ b/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/lib/IR/Module.cpp b/lib/IR/Module.cpp index 98e4706019c..7f673d07e92 100644 --- a/lib/IR/Module.cpp +++ b/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(V)) { + uint64_t Val = Behavior->getLimitedValue(); + if (Val >= ModFlagBehaviorFirstVal && Val <= ModFlagBehaviorLastVal) { + MFB = static_cast(Val); + return true; + } + } + return false; +} + /// getModuleFlagsMetadata - Returns the module flags in the provided vector. void Module:: getModuleFlagsMetadata(SmallVectorImpl &Flags) const { @@ -266,15 +277,15 @@ getModuleFlagsMetadata(SmallVectorImpl &Flags) const { if (!ModFlags) return; for (const MDNode *Flag : ModFlags->operands()) { - if (Flag->getNumOperands() >= 3 && isa(Flag->getOperand(0)) && + ModFlagBehavior MFB; + if (Flag->getNumOperands() >= 3 && + isValidModFlagBehavior(Flag->getOperand(0), MFB) && isa(Flag->getOperand(1))) { // Check the operands of the MDNode before accessing the operands. // The verifier will actually catch these failures. - ConstantInt *Behavior = cast(Flag->getOperand(0)); MDString *Key = cast(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/lib/IR/Verifier.cpp b/lib/IR/Verifier.cpp index 0df257da4a4..1a182db9277 100644 --- a/lib/IR/Verifier.cpp +++ b/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(Op->getOperand(0)); + Module::ModFlagBehavior MFB; + if (!Module::isValidModFlagBehavior(Op->getOperand(0), MFB)) { + Assert1( + dyn_cast(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(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)", -- 2.34.1