[llvm] r217395 - Be more careful in parsing Module::ModFlagBehavior value
Alexey Samsonov
vonosmas at gmail.com
Mon Sep 8 12:16:29 PDT 2014
Author: samsonov
Date: Mon Sep 8 14:16:28 2014
New Revision: 217395
URL: http://llvm.org/viewvc/llvm-project?rev=217395&view=rev
Log:
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.
Modified:
llvm/trunk/include/llvm/IR/Module.h
llvm/trunk/lib/IR/Module.cpp
llvm/trunk/lib/IR/Verifier.cpp
Modified: llvm/trunk/include/llvm/IR/Module.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/IR/Module.h?rev=217395&r1=217394&r2=217395&view=diff
==============================================================================
--- llvm/trunk/include/llvm/IR/Module.h (original)
+++ llvm/trunk/include/llvm/IR/Module.h Mon Sep 8 14:16:28 2014
@@ -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;
Modified: llvm/trunk/lib/IR/Module.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Module.cpp?rev=217395&r1=217394&r2=217395&view=diff
==============================================================================
--- llvm/trunk/lib/IR/Module.cpp (original)
+++ llvm/trunk/lib/IR/Module.cpp Mon Sep 8 14:16:28 2014
@@ -259,6 +259,17 @@ void Module::eraseNamedMetadata(NamedMDN
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<M
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));
}
}
}
Modified: llvm/trunk/lib/IR/Verifier.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/IR/Verifier.cpp?rev=217395&r1=217394&r2=217395&view=diff
==============================================================================
--- llvm/trunk/lib/IR/Verifier.cpp (original)
+++ llvm/trunk/lib/IR/Verifier.cpp Mon Sep 8 14:16:28 2014
@@ -673,24 +673,23 @@ Verifier::visitModuleFlag(const MDNode *
// 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 *
}
// 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)",
More information about the llvm-commits
mailing list