summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexey Samsonov <vonosmas@gmail.com>2014-09-08 19:16:28 +0000
committerAlexey Samsonov <vonosmas@gmail.com>2014-09-08 19:16:28 +0000
commitaf023adb86d326f7efeebbbbf28d659e7f73b94f (patch)
tree9123f3a575f5cae7993d4b490a64bb4df4d1afee
parent82944983b4aca8389441f3a1aadce51ff572759d (diff)
downloadbcm5719-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.h10
-rw-r--r--llvm/lib/IR/Module.cpp19
-rw-r--r--llvm/lib/IR/Verifier.cpp25
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)",
OpenPOWER on IntegriCloud