Skip to content

Commit 2b6d2be

Browse files
committed
MachineVerifier: Check stack protector is top-most in frame
Mitigate against potential bugs that might place it elsewhere and render the mechanism useless.
1 parent ba93ecc commit 2b6d2be

File tree

2 files changed

+63
-1
lines changed

2 files changed

+63
-1
lines changed

llvm/lib/CodeGen/MachineVerifier.cpp

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,8 @@ struct MachineVerifier {
353353
LaneBitmask LaneMask = LaneBitmask::getNone());
354354

355355
void verifyStackFrame();
356+
// Check that the stack protector is the top-most object in the stack.
357+
void verifyStackProtector();
356358

357359
void verifySlotIndexes() const;
358360
void verifyProperties(const MachineFunction &MF);
@@ -709,8 +711,10 @@ void MachineVerifier::visitMachineFunctionBefore() {
709711
// Check that the register use lists are sane.
710712
MRI->verifyUseLists();
711713

712-
if (!MF->empty())
714+
if (!MF->empty()) {
713715
verifyStackFrame();
716+
verifyStackProtector();
717+
}
714718
}
715719

716720
void
@@ -4038,3 +4042,44 @@ void MachineVerifier::verifyStackFrame() {
40384042
}
40394043
}
40404044
}
4045+
4046+
void MachineVerifier::verifyStackProtector() {
4047+
const MachineFrameInfo &MFI = MF->getFrameInfo();
4048+
if (!MFI.hasStackProtectorIndex())
4049+
return;
4050+
// Only applicable when the offsets of frame objects have been determined,
4051+
// which is indicated by a non-zero stack size.
4052+
if (!MFI.getStackSize())
4053+
return;
4054+
const TargetFrameLowering &TFI = *MF->getSubtarget().getFrameLowering();
4055+
bool StackGrowsDown =
4056+
TFI.getStackGrowthDirection() == TargetFrameLowering::StackGrowsDown;
4057+
assert(StackGrowsDown && "Only support stack growth down");
4058+
// Collect the frame indices of the callee-saved registers which are spilled
4059+
// to the stack. These are the registers that are stored above the stack
4060+
// protector.
4061+
SmallSet<unsigned, 4> CalleeSavedFrameIndices;
4062+
if (MFI.isCalleeSavedInfoValid()) {
4063+
for (const CalleeSavedInfo &Info : MFI.getCalleeSavedInfo()) {
4064+
if (!Info.isSpilledToReg())
4065+
CalleeSavedFrameIndices.insert(Info.getFrameIdx());
4066+
}
4067+
}
4068+
unsigned FI = MFI.getStackProtectorIndex();
4069+
int64_t SPOffset = MFI.getObjectOffset(FI);
4070+
for (unsigned I = 0, E = MFI.getObjectIndexEnd(); I != E; ++I) {
4071+
if (I == FI)
4072+
continue;
4073+
// Variable-sized objects do not have a fixed offset.
4074+
if (MFI.isVariableSizedObjectIndex(I))
4075+
continue;
4076+
if (CalleeSavedFrameIndices.contains(I))
4077+
continue;
4078+
if (SPOffset < MFI.getObjectOffset(I)) {
4079+
report("Stack protector is not the top-most object on the stack", MF);
4080+
OS << "Stack protector is not the top-most object on the stack in "
4081+
<< MF->getName() << '\n';
4082+
break;
4083+
}
4084+
}
4085+
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# RUN: not --crash llc -mtriple=aarch64 -run-pass=machineverifier -o - %s 2>&1 | FileCheck %s
2+
# REQUIRES: aarch64-registered-target
3+
4+
# CHECK: *** Bad machine code: Stack protector is not the top-most object on the stack ***
5+
6+
---
7+
name: main
8+
frameInfo:
9+
stackSize: 16
10+
stackProtector: '%stack.1'
11+
isCalleeSavedInfoValid: true
12+
stack:
13+
- { id: 0, offset: -16, size: 8, alignment: 8, stack-id: default }
14+
- { id: 1, offset: -32, size: 8, alignment: 8, stack-id: default }
15+
body: |
16+
bb.0:
17+
...

0 commit comments

Comments
 (0)