[llvm] [LFI][AArch64] Fix Segfault due to infinite recursion in LFI rewriter (PR #210267)

via llvm-commits llvm-commits at lists.llvm.org
Fri Jul 17 01:12:54 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-backend-aarch64

Author: Sharjeel Khan (Sharjeel-Khan)

<details>
<summary>Changes</summary>

When emitting a deferred LR guard, if debug info is enabled, the emission of the guard instruction can trigger temporary labels (e.g. for DWARF line entries), which recursively calls onLabel. Since DeferredLRGuard was only set to false after emission, the nested call would re-emit the guard, causing infinite recursion which leads to a SegFault due to stack overflow. This was detected compiling ubsan_minimal_handlers.cpp in compiler-rt. I fixed it by setting DeferredLRGuard = false before emitting the guard.

---
Full diff: https://github.com/llvm/llvm-project/pull/210267.diff


2 Files Affected:

- (modified) llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCLFIRewriter.cpp (+3-3) 
- (added) llvm/test/MC/AArch64/LFI/debug-info.s (+13) 


``````````diff
diff --git a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCLFIRewriter.cpp b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCLFIRewriter.cpp
index 3c24f5ab62a61..98d82aa43eed3 100644
--- a/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCLFIRewriter.cpp
+++ b/llvm/lib/Target/AArch64/MCTargetDesc/AArch64MCLFIRewriter.cpp
@@ -301,8 +301,8 @@ void AArch64MCLFIRewriter::onLabel(const MCSymbol *, MCStreamer &Out) {
   // Flush a deferred LR guard before the label, since the label is a potential
   // branch target and code reached through it may use LR for control flow.
   if (DeferredLRGuard && LastSTI) {
-    emitAddMask(AArch64::LR, AArch64::LR, Out, *LastSTI);
     DeferredLRGuard = false;
+    emitAddMask(AArch64::LR, AArch64::LR, Out, *LastSTI);
   }
 
   // Invalidate guard state since the label is a potential branch target.
@@ -312,8 +312,8 @@ void AArch64MCLFIRewriter::onLabel(const MCSymbol *, MCStreamer &Out) {
 void AArch64MCLFIRewriter::finish(MCStreamer &Out) {
   // Flush a deferred LR guard at the end of the stream.
   if (DeferredLRGuard && LastSTI) {
-    emitAddMask(AArch64::LR, AArch64::LR, Out, *LastSTI);
     DeferredLRGuard = false;
+    emitAddMask(AArch64::LR, AArch64::LR, Out, *LastSTI);
   }
 }
 
@@ -948,8 +948,8 @@ void AArch64MCLFIRewriter::doRewriteInst(const MCInst &Inst, MCStreamer &Out,
   // modified LR is sandboxed before it can be used to transfer control.
   if (DeferredLRGuard && (isReturn(Inst) || isIndirectBranch(Inst) ||
                           isCall(Inst) || isBranch(Inst))) {
-    emitAddMask(AArch64::LR, AArch64::LR, Out, STI);
     DeferredLRGuard = false;
+    emitAddMask(AArch64::LR, AArch64::LR, Out, STI);
   }
 
   // PAC authenticated branches/calls expand to authenticate + guarded branch.
diff --git a/llvm/test/MC/AArch64/LFI/debug-info.s b/llvm/test/MC/AArch64/LFI/debug-info.s
new file mode 100644
index 0000000000000..9c6efbd79f6a2
--- /dev/null
+++ b/llvm/test/MC/AArch64/LFI/debug-info.s
@@ -0,0 +1,13 @@
+// RUN: llvm-mc -triple aarch64_lfi -filetype=obj %s -o /dev/null
+// RUN: llvm-mc -triple aarch64_lfi %s | FileCheck %s
+
+// CHECK:      mov	x30, x0
+// CHECK:      add	x30, x27, w30, uxtw
+// CHECK:      next_func:
+// CHECK-NEXT: nop
+
+.file 1 "debug-info.s"
+mov x30, x0
+.loc 1 10 0
+next_func:
+  nop

``````````

</details>


https://github.com/llvm/llvm-project/pull/210267


More information about the llvm-commits mailing list