[llvm] [CodeGen] Assert on invalid patchable-function-entry/prefix attributes (PR #194726)
via llvm-commits
llvm-commits at lists.llvm.org
Tue Apr 28 14:01:31 PDT 2026
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-backend-powerpc
Author: JP Hafer (jph-13)
<details>
<summary>Changes</summary>
Replace unchecked getAsInteger() calls for the "patchable-function-entry" and "patchable-function-prefix" function attributes with assertions across AsmPrinter and all backend targets.
The IR Verifier already validates these attributes as unsigned base-10 integers via checkUnsignedBaseTenFuncAttr, so a parse failure at the point of use indicates a verifier bypass or IR corruption. The RISC-V backend already follows this pattern (RISCVAsmPrinter.cpp); this brings the remaining backends in line.
Affected targets: AArch64, ARM, LoongArch, PowerPC, RISC-V, SystemZ, X86.
---
Full diff: https://github.com/llvm/llvm-project/pull/194726.diff
12 Files Affected:
- (modified) llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp (+28-12)
- (modified) llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp (+10-5)
- (modified) llvm/lib/Target/ARM/ARMAsmPrinter.cpp (+10-5)
- (modified) llvm/lib/Target/LoongArch/LoongArchAsmPrinter.cpp (+4-3)
- (modified) llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp (+4-3)
- (modified) llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp (+15-7)
- (modified) llvm/lib/Target/PowerPC/PPCInstrInfo.cpp (+7-3)
- (modified) llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp (+10-5)
- (modified) llvm/lib/Target/RISCV/RISCVInstrInfo.cpp (+4-4)
- (modified) llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp (+4-3)
- (modified) llvm/lib/Target/X86/X86AsmPrinter.cpp (+8-4)
- (modified) llvm/lib/Target/X86/X86MCInstLower.cpp (+12-7)
``````````diff
diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index 8c75ca7c17f7e..766dbed8f8e7a 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -1085,12 +1085,20 @@ void AsmPrinter::emitFunctionHeader() {
// place prefix data before NOPs.
unsigned PatchableFunctionPrefix = 0;
unsigned PatchableFunctionEntry = 0;
- (void)F.getFnAttribute("patchable-function-prefix")
- .getValueAsString()
- .getAsInteger(10, PatchableFunctionPrefix);
- (void)F.getFnAttribute("patchable-function-entry")
- .getValueAsString()
- .getAsInteger(10, PatchableFunctionEntry);
+ if (F.hasFnAttribute("patchable-function-prefix")) {
+ [[maybe_unused]] bool Result =
+ F.getFnAttribute("patchable-function-prefix")
+ .getValueAsString()
+ .getAsInteger(10, PatchableFunctionPrefix);
+ assert(!Result && "Enforced by the verifier");
+ }
+ if (F.hasFnAttribute("patchable-function-entry")) {
+ [[maybe_unused]] bool Result =
+ F.getFnAttribute("patchable-function-entry")
+ .getValueAsString()
+ .getAsInteger(10, PatchableFunctionEntry);
+ assert(!Result && "Enforced by the verifier");
+ }
if (PatchableFunctionPrefix) {
CurrentPatchableFunctionEntrySym =
OutContext.createLinkerPrivateTempSymbol();
@@ -5102,12 +5110,20 @@ void AsmPrinter::recordSled(MCSymbol *Sled, const MachineInstr &MI,
void AsmPrinter::emitPatchableFunctionEntries() {
const Function &F = MF->getFunction();
unsigned PatchableFunctionPrefix = 0, PatchableFunctionEntry = 0;
- (void)F.getFnAttribute("patchable-function-prefix")
- .getValueAsString()
- .getAsInteger(10, PatchableFunctionPrefix);
- (void)F.getFnAttribute("patchable-function-entry")
- .getValueAsString()
- .getAsInteger(10, PatchableFunctionEntry);
+ if (F.hasFnAttribute("patchable-function-prefix")) {
+ [[maybe_unused]] bool Result =
+ F.getFnAttribute("patchable-function-prefix")
+ .getValueAsString()
+ .getAsInteger(10, PatchableFunctionPrefix);
+ assert(!Result && "Enforced by the verifier");
+ }
+ if (F.hasFnAttribute("patchable-function-entry")) {
+ [[maybe_unused]] bool Result =
+ F.getFnAttribute("patchable-function-entry")
+ .getValueAsString()
+ .getAsInteger(10, PatchableFunctionEntry);
+ assert(!Result && "Enforced by the verifier");
+ }
if (!PatchableFunctionPrefix && !PatchableFunctionEntry)
return;
const unsigned PointerSize = getPointerSize();
diff --git a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
index 97edd896c5992..c4d2ec6ca250a 100644
--- a/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
+++ b/llvm/lib/Target/AArch64/AArch64AsmPrinter.cpp
@@ -688,11 +688,16 @@ void AArch64AsmPrinter::LowerKCFI_CHECK(const MachineInstr &MI) {
// Adjust the offset for patchable-function-prefix. This assumes that
// patchable-function-prefix is the same for all functions.
int64_t PrefixNops = 0;
- (void)MI.getMF()
- ->getFunction()
- .getFnAttribute("patchable-function-prefix")
- .getValueAsString()
- .getAsInteger(10, PrefixNops);
+ if (MI.getMF()->getFunction().hasFnAttribute(
+ "patchable-function-prefix")) {
+ [[maybe_unused]] bool Result =
+ MI.getMF()
+ ->getFunction()
+ .getFnAttribute("patchable-function-prefix")
+ .getValueAsString()
+ .getAsInteger(10, PrefixNops);
+ assert(!Result && "Enforced by the verifier");
+ }
// Load the target function type hash.
EmitToStreamer(*OutStreamer, MCInstBuilder(AArch64::LDURWi)
diff --git a/llvm/lib/Target/ARM/ARMAsmPrinter.cpp b/llvm/lib/Target/ARM/ARMAsmPrinter.cpp
index fb2bbb5680156..5844d8cceadce 100644
--- a/llvm/lib/Target/ARM/ARMAsmPrinter.cpp
+++ b/llvm/lib/Target/ARM/ARMAsmPrinter.cpp
@@ -1916,11 +1916,16 @@ void ARMAsmPrinter::LowerKCFI_CHECK(const MachineInstr &MI) {
// Adjust the offset for patchable-function-prefix.
int64_t PrefixNops = 0;
- MI.getMF()
- ->getFunction()
- .getFnAttribute("patchable-function-prefix")
- .getValueAsString()
- .getAsInteger(10, PrefixNops);
+ if (MI.getMF()->getFunction().hasFnAttribute(
+ "patchable-function-prefix")) {
+ [[maybe_unused]] bool Result =
+ MI.getMF()
+ ->getFunction()
+ .getFnAttribute("patchable-function-prefix")
+ .getValueAsString()
+ .getAsInteger(10, PrefixNops);
+ assert(!Result && "Enforced by the verifier");
+ }
// Emit the appropriate instruction sequence based on the opcode variant.
switch (MI.getOpcode()) {
diff --git a/llvm/lib/Target/LoongArch/LoongArchAsmPrinter.cpp b/llvm/lib/Target/LoongArch/LoongArchAsmPrinter.cpp
index 4b5cba716c638..19d2a6e259ade 100644
--- a/llvm/lib/Target/LoongArch/LoongArchAsmPrinter.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchAsmPrinter.cpp
@@ -216,10 +216,11 @@ void LoongArchAsmPrinter::LowerPATCHABLE_FUNCTION_ENTER(
const Function &F = MF->getFunction();
if (F.hasFnAttribute("patchable-function-entry")) {
unsigned Num;
- if (F.getFnAttribute("patchable-function-entry")
+ [[maybe_unused]] bool Result =
+ F.getFnAttribute("patchable-function-entry")
.getValueAsString()
- .getAsInteger(10, Num))
- return;
+ .getAsInteger(10, Num);
+ assert(!Result && "Enforced by the verifier");
emitNops(Num);
return;
}
diff --git a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp
index 631565b963b79..3ad81c5285848 100644
--- a/llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp
+++ b/llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp
@@ -268,10 +268,11 @@ unsigned LoongArchInstrInfo::getInstSizeInBytes(const MachineInstr &MI) const {
const Function &F = MF->getFunction();
if (F.hasFnAttribute("patchable-function-entry")) {
unsigned Num;
- if (F.getFnAttribute("patchable-function-entry")
+ [[maybe_unused]] bool Result =
+ F.getFnAttribute("patchable-function-entry")
.getValueAsString()
- .getAsInteger(10, Num))
- return 0;
+ .getAsInteger(10, Num);
+ assert(!Result && "Enforced by the verifier");
return Num * 4;
}
[[fallthrough]];
diff --git a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
index 49c54fbae1bf0..c2731fa158345 100644
--- a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
+++ b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
@@ -952,10 +952,14 @@ void PPCAsmPrinter::emitInstruction(const MachineInstr *MI) {
assert(!Subtarget->isAIXABI() &&
"AIX does not support patchable function entry!");
const Function &F = MF->getFunction();
- unsigned Num = 0;
- (void)F.getFnAttribute("patchable-function-entry")
- .getValueAsString()
- .getAsInteger(10, Num);
+ if (!F.hasFnAttribute("patchable-function-entry"))
+ return;
+ unsigned Num;
+ [[maybe_unused]] bool Result =
+ F.getFnAttribute("patchable-function-entry")
+ .getValueAsString()
+ .getAsInteger(10, Num);
+ assert(!Result && "Enforced by the verifier");
if (!Num)
return;
emitNops(Num);
@@ -1818,9 +1822,13 @@ void PPCLinuxAsmPrinter::emitInstruction(const MachineInstr *MI) {
// XRAY is only supported on PPC Linux little endian.
const Function &F = MF->getFunction();
unsigned Num = 0;
- (void)F.getFnAttribute("patchable-function-entry")
- .getValueAsString()
- .getAsInteger(10, Num);
+ if (F.hasFnAttribute("patchable-function-entry")) {
+ [[maybe_unused]] bool Result =
+ F.getFnAttribute("patchable-function-entry")
+ .getValueAsString()
+ .getAsInteger(10, Num);
+ assert(!Result && "Enforced by the verifier");
+ }
if (!MAI->isLittleEndian() || Num)
break;
diff --git a/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp b/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp
index f854dca003964..c3c96859225c9 100644
--- a/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp
+++ b/llvm/lib/Target/PowerPC/PPCInstrInfo.cpp
@@ -3024,9 +3024,13 @@ unsigned PPCInstrInfo::getInstSizeInBytes(const MachineInstr &MI) const {
const MachineFunction *MF = MI.getParent()->getParent();
const Function &F = MF->getFunction();
unsigned Num = 0;
- (void)F.getFnAttribute("patchable-function-entry")
- .getValueAsString()
- .getAsInteger(10, Num);
+ if (F.hasFnAttribute("patchable-function-entry")) {
+ [[maybe_unused]] bool Result =
+ F.getFnAttribute("patchable-function-entry")
+ .getValueAsString()
+ .getAsInteger(10, Num);
+ assert(!Result && "Enforced by the verifier");
+ }
if (Num || MF->getTarget().getTargetTriple().isOSAIX() ||
!MF->getTarget().getTargetTriple().isLittleEndian())
return Num * 4;
diff --git a/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp b/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp
index d71fd640be7bc..0baa2f7d1c2a8 100644
--- a/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp
+++ b/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp
@@ -682,11 +682,16 @@ void RISCVAsmPrinter::LowerKCFI_CHECK(const MachineInstr &MI) {
// patchable-function-prefix is the same for all functions.
int NopSize = STI->hasStdExtZca() ? 2 : 4;
int64_t PrefixNops = 0;
- (void)MI.getMF()
- ->getFunction()
- .getFnAttribute("patchable-function-prefix")
- .getValueAsString()
- .getAsInteger(10, PrefixNops);
+ if (MI.getMF()->getFunction().hasFnAttribute(
+ "patchable-function-prefix")) {
+ [[maybe_unused]] bool Result =
+ MI.getMF()
+ ->getFunction()
+ .getFnAttribute("patchable-function-prefix")
+ .getValueAsString()
+ .getAsInteger(10, PrefixNops);
+ assert(!Result && "Enforced by the verifier");
+ }
// Load the target function type hash.
EmitToStreamer(*OutStreamer, MCInstBuilder(RISCV::LW)
diff --git a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
index 6671669a8942b..0d4375906b0ff 100644
--- a/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
+++ b/llvm/lib/Target/RISCV/RISCVInstrInfo.cpp
@@ -2087,11 +2087,11 @@ unsigned RISCVInstrInfo::getInstSizeInBytes(const MachineInstr &MI) const {
if (Opcode == TargetOpcode::PATCHABLE_FUNCTION_ENTER &&
F.hasFnAttribute("patchable-function-entry")) {
unsigned Num;
- if (F.getFnAttribute("patchable-function-entry")
+ [[maybe_unused]] bool Result =
+ F.getFnAttribute("patchable-function-entry")
.getValueAsString()
- .getAsInteger(10, Num))
- return get(Opcode).getSize();
-
+ .getAsInteger(10, Num);
+ assert(!Result && "Enforced by the verifier");
// Number of C.NOP or NOP
return (STI.hasStdExtZca() ? 2 : 4) * Num;
}
diff --git a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
index 7871e4a53de2a..ed745d5c79aa0 100644
--- a/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZAsmPrinter.cpp
@@ -941,10 +941,11 @@ void SystemZAsmPrinter::LowerPATCHABLE_FUNCTION_ENTER(
unsigned Num;
// get M-N from function attribute (CodeGenFunction subtracts N
// from M to yield the correct patchable-function-entry).
- if (F.getFnAttribute("patchable-function-entry")
+ [[maybe_unused]] bool Result =
+ F.getFnAttribute("patchable-function-entry")
.getValueAsString()
- .getAsInteger(10, Num))
- return;
+ .getAsInteger(10, Num);
+ assert(!Result && "Enforced by the verifier");
// Emit M-N 2-byte nops. Use getNop() here instead of emitNops()
// to keep it aligned with the common code implementation emitting
// the prefix nops.
diff --git a/llvm/lib/Target/X86/X86AsmPrinter.cpp b/llvm/lib/Target/X86/X86AsmPrinter.cpp
index 94dd706fe9944..367c87d399289 100644
--- a/llvm/lib/Target/X86/X86AsmPrinter.cpp
+++ b/llvm/lib/Target/X86/X86AsmPrinter.cpp
@@ -154,10 +154,14 @@ void X86AsmPrinter::EmitKCFITypePadding(const MachineFunction &MF,
// Keep the function entry aligned, taking patchable-function-prefix into
// account if set.
int64_t PrefixBytes = 0;
- (void)MF.getFunction()
- .getFnAttribute("patchable-function-prefix")
- .getValueAsString()
- .getAsInteger(10, PrefixBytes);
+ if (MF.getFunction().hasFnAttribute("patchable-function-prefix")) {
+ [[maybe_unused]] bool Result =
+ MF.getFunction()
+ .getFnAttribute("patchable-function-prefix")
+ .getValueAsString()
+ .getAsInteger(10, PrefixBytes);
+ assert(!Result && "Enforced by the verifier");
+ }
// Also take the type identifier into account if we're emitting
// one. Otherwise, just pad with nops. The X86::MOV32ri instruction emitted
diff --git a/llvm/lib/Target/X86/X86MCInstLower.cpp b/llvm/lib/Target/X86/X86MCInstLower.cpp
index 98126ec07b74d..e1c22a9470d6f 100644
--- a/llvm/lib/Target/X86/X86MCInstLower.cpp
+++ b/llvm/lib/Target/X86/X86MCInstLower.cpp
@@ -910,10 +910,14 @@ void X86AsmPrinter::LowerKCFI_CHECK(const MachineInstr &MI) {
// functions.
const MachineFunction &MF = *MI.getMF();
int64_t PrefixNops = 0;
- (void)MF.getFunction()
- .getFnAttribute("patchable-function-prefix")
- .getValueAsString()
- .getAsInteger(10, PrefixNops);
+ if (MF.getFunction().hasFnAttribute("patchable-function-prefix")) {
+ [[maybe_unused]] bool Result =
+ MF.getFunction()
+ .getFnAttribute("patchable-function-prefix")
+ .getValueAsString()
+ .getAsInteger(10, PrefixNops);
+ assert(!Result && "Enforced by the verifier");
+ }
// KCFI allows indirect calls to any location that's preceded by a valid
// type identifier. To avoid encoding the full constant into an instruction,
@@ -1311,10 +1315,11 @@ void X86AsmPrinter::LowerPATCHABLE_FUNCTION_ENTER(const MachineInstr &MI,
const Function &F = MF->getFunction();
if (F.hasFnAttribute("patchable-function-entry")) {
unsigned Num;
- if (F.getFnAttribute("patchable-function-entry")
+ [[maybe_unused]] bool Result =
+ F.getFnAttribute("patchable-function-entry")
.getValueAsString()
- .getAsInteger(10, Num))
- return;
+ .getAsInteger(10, Num);
+ assert(!Result && "Enforced by the verifier");
emitX86Nops(*OutStreamer, Num, Subtarget);
return;
}
``````````
</details>
https://github.com/llvm/llvm-project/pull/194726
More information about the llvm-commits
mailing list