mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-08-15 06:29:05 +00:00
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
This commit is contained in:
@@ -182,9 +182,17 @@ public:
|
|||||||
/// Appends the two values, which are required to be metadata
|
/// Appends the two values, which are required to be metadata
|
||||||
/// nodes. However, duplicate entries in the second list are dropped
|
/// nodes. However, duplicate entries in the second list are dropped
|
||||||
/// during the append operation.
|
/// 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 {
|
struct ModuleFlagEntry {
|
||||||
ModFlagBehavior Behavior;
|
ModFlagBehavior Behavior;
|
||||||
MDString *Key;
|
MDString *Key;
|
||||||
|
@@ -259,6 +259,17 @@ void Module::eraseNamedMetadata(NamedMDNode *NMD) {
|
|||||||
NamedMDList.erase(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.
|
/// getModuleFlagsMetadata - Returns the module flags in the provided vector.
|
||||||
void Module::
|
void Module::
|
||||||
getModuleFlagsMetadata(SmallVectorImpl<ModuleFlagEntry> &Flags) const {
|
getModuleFlagsMetadata(SmallVectorImpl<ModuleFlagEntry> &Flags) const {
|
||||||
@@ -266,15 +277,15 @@ getModuleFlagsMetadata(SmallVectorImpl<ModuleFlagEntry> &Flags) const {
|
|||||||
if (!ModFlags) return;
|
if (!ModFlags) return;
|
||||||
|
|
||||||
for (const MDNode *Flag : ModFlags->operands()) {
|
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))) {
|
isa<MDString>(Flag->getOperand(1))) {
|
||||||
// Check the operands of the MDNode before accessing the operands.
|
// Check the operands of the MDNode before accessing the operands.
|
||||||
// The verifier will actually catch these failures.
|
// The verifier will actually catch these failures.
|
||||||
ConstantInt *Behavior = cast<ConstantInt>(Flag->getOperand(0));
|
|
||||||
MDString *Key = cast<MDString>(Flag->getOperand(1));
|
MDString *Key = cast<MDString>(Flag->getOperand(1));
|
||||||
Value *Val = Flag->getOperand(2);
|
Value *Val = Flag->getOperand(2);
|
||||||
Flags.push_back(ModuleFlagEntry(ModFlagBehavior(Behavior->getZExtValue()),
|
Flags.push_back(ModuleFlagEntry(MFB, Key, Val));
|
||||||
Key, Val));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -673,24 +673,23 @@ Verifier::visitModuleFlag(const MDNode *Op,
|
|||||||
// constant int), the flag ID (an MDString), and the value.
|
// constant int), the flag ID (an MDString), and the value.
|
||||||
Assert1(Op->getNumOperands() == 3,
|
Assert1(Op->getNumOperands() == 3,
|
||||||
"incorrect number of operands in module flag", Op);
|
"incorrect number of operands in module flag", Op);
|
||||||
ConstantInt *Behavior = dyn_cast<ConstantInt>(Op->getOperand(0));
|
Module::ModFlagBehavior MFB;
|
||||||
MDString *ID = dyn_cast<MDString>(Op->getOperand(1));
|
if (!Module::isValidModFlagBehavior(Op->getOperand(0), MFB)) {
|
||||||
Assert1(Behavior,
|
Assert1(
|
||||||
|
dyn_cast<ConstantInt>(Op->getOperand(0)),
|
||||||
"invalid behavior operand in module flag (expected constant integer)",
|
"invalid behavior operand in module flag (expected constant integer)",
|
||||||
Op->getOperand(0));
|
Op->getOperand(0));
|
||||||
unsigned BehaviorValue = Behavior->getZExtValue();
|
Assert1(false,
|
||||||
|
"invalid behavior operand in module flag (unexpected constant)",
|
||||||
|
Op->getOperand(0));
|
||||||
|
}
|
||||||
|
MDString *ID = dyn_cast<MDString>(Op->getOperand(1));
|
||||||
Assert1(ID,
|
Assert1(ID,
|
||||||
"invalid ID operand in module flag (expected metadata string)",
|
"invalid ID operand in module flag (expected metadata string)",
|
||||||
Op->getOperand(1));
|
Op->getOperand(1));
|
||||||
|
|
||||||
// Sanity check the values for behaviors with additional requirements.
|
// Sanity check the values for behaviors with additional requirements.
|
||||||
switch (BehaviorValue) {
|
switch (MFB) {
|
||||||
default:
|
|
||||||
Assert1(false,
|
|
||||||
"invalid behavior operand in module flag (unexpected constant)",
|
|
||||||
Op->getOperand(0));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Module::Error:
|
case Module::Error:
|
||||||
case Module::Warning:
|
case Module::Warning:
|
||||||
case Module::Override:
|
case Module::Override:
|
||||||
@@ -726,7 +725,7 @@ Verifier::visitModuleFlag(const MDNode *Op,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Unless this is a "requires" flag, check the ID is unique.
|
// 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;
|
bool Inserted = SeenIDs.insert(std::make_pair(ID, Op)).second;
|
||||||
Assert1(Inserted,
|
Assert1(Inserted,
|
||||||
"module flag identifiers must be unique (or of 'require' type)",
|
"module flag identifiers must be unique (or of 'require' type)",
|
||||||
|
Reference in New Issue
Block a user