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
This commit is contained in:
Alexey Samsonov 2014-09-08 19:16:28 +00:00
parent 82944983b4
commit af023adb86
3 changed files with 36 additions and 18 deletions

View File

@ -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;

View File

@ -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));
}
}
}

View File

@ -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)",