forked from OSchip/llvm-project
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:
parent
82944983b4
commit
af023adb86
|
@ -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;
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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)",
|
||||
|
|
Loading…
Reference in New Issue