diff options
author | Guy David <49722543+guy-david@users.noreply.github.com> | 2025-01-10 10:33:02 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2025-01-10 10:33:02 +0200 |
commit | 86b1b0671cafd462c0aa681e2d320ce597300f69 (patch) | |
tree | 6943343a7d57816665241bcdaf53528c42939d7c /llvm/lib/CodeGen/MachineVerifier.cpp | |
parent | 6504546abcd38159256c3030286b1c02b401c4f8 (diff) | |
download | llvm-86b1b0671cafd462c0aa681e2d320ce597300f69.zip llvm-86b1b0671cafd462c0aa681e2d320ce597300f69.tar.gz llvm-86b1b0671cafd462c0aa681e2d320ce597300f69.tar.bz2 |
MachineVerifier: Check stack protector is top-most in frame (#121481)
Somewhat paranoid, but mitigates potential bugs in the future that might
place it elsewhere and render the mechanism useless.
Diffstat (limited to 'llvm/lib/CodeGen/MachineVerifier.cpp')
-rw-r--r-- | llvm/lib/CodeGen/MachineVerifier.cpp | 52 |
1 files changed, 51 insertions, 1 deletions
diff --git a/llvm/lib/CodeGen/MachineVerifier.cpp b/llvm/lib/CodeGen/MachineVerifier.cpp index bec36b7..2558799 100644 --- a/llvm/lib/CodeGen/MachineVerifier.cpp +++ b/llvm/lib/CodeGen/MachineVerifier.cpp @@ -353,6 +353,8 @@ struct MachineVerifier { LaneBitmask LaneMask = LaneBitmask::getNone()); void verifyStackFrame(); + // Check that the stack protector is the top-most object in the stack. + void verifyStackProtector(); void verifySlotIndexes() const; void verifyProperties(const MachineFunction &MF); @@ -709,8 +711,10 @@ void MachineVerifier::visitMachineFunctionBefore() { // Check that the register use lists are sane. MRI->verifyUseLists(); - if (!MF->empty()) + if (!MF->empty()) { verifyStackFrame(); + verifyStackProtector(); + } } void @@ -4038,3 +4042,49 @@ void MachineVerifier::verifyStackFrame() { } } } + +void MachineVerifier::verifyStackProtector() { + const MachineFrameInfo &MFI = MF->getFrameInfo(); + if (!MFI.hasStackProtectorIndex()) + return; + // Only applicable when the offsets of frame objects have been determined, + // which is indicated by a non-zero stack size. + if (!MFI.getStackSize()) + return; + const TargetFrameLowering &TFI = *MF->getSubtarget().getFrameLowering(); + bool StackGrowsDown = + TFI.getStackGrowthDirection() == TargetFrameLowering::StackGrowsDown; + // Collect the frame indices of the callee-saved registers which are spilled + // to the stack. These are the registers that are stored above the stack + // protector. + SmallSet<unsigned, 4> CalleeSavedFrameIndices; + if (MFI.isCalleeSavedInfoValid()) { + for (const CalleeSavedInfo &Info : MFI.getCalleeSavedInfo()) { + if (!Info.isSpilledToReg()) + CalleeSavedFrameIndices.insert(Info.getFrameIdx()); + } + } + unsigned FI = MFI.getStackProtectorIndex(); + int64_t SPStart = MFI.getObjectOffset(FI); + int64_t SPEnd = SPStart + MFI.getObjectSize(FI); + for (unsigned I = 0, E = MFI.getObjectIndexEnd(); I != E; ++I) { + if (I == FI) + continue; + // Variable-sized objects do not have a fixed offset. + if (MFI.isVariableSizedObjectIndex(I)) + continue; + if (CalleeSavedFrameIndices.contains(I)) + continue; + int64_t ObjStart = MFI.getObjectOffset(I); + int64_t ObjEnd = ObjStart + MFI.getObjectSize(I); + if (SPStart < ObjEnd && ObjStart < SPEnd) { + report("Stack protector overlaps with another stack object", MF); + break; + } + if ((StackGrowsDown && SPStart <= ObjStart) || + (!StackGrowsDown && SPStart >= ObjStart)) { + report("Stack protector is not the top-most object on the stack", MF); + break; + } + } +} |