[llvm] [IR] Fix crash on malformed '@' inline asm constraints (PR #224300)
Daniel Petrovic via llvm-commits
llvm-commits at lists.llvm.org
Tue Sep 22 01:33:59 PDT 2026
https://github.com/daniel-petrovic updated https://github.com/llvm/llvm-project/pull/224300
>From 5f565ea8ff91bae0a9fb18abe2c3cc5459b0a141 Mon Sep 17 00:00:00 2001
From: Daniel Petrovic <daniel-dev at hotmail.de>
Date: Thu, 17 Sep 2026 15:23:47 +0200
Subject: [PATCH] [IR] Fix crash on malformed '@' inline asm constraints
InlineAsm::ConstraintInfo::Parse trusted asserts (compiled out under
NDEBUG) for the '@' multi-letter constraint marker: a non-digit after
'@', a trailing '@', or a count exceeding the remaining characters all
caused an out-of-bounds StringRef read. A release-built llvm-as crashed
on "=@ccz"; verifyModule hit the same read via the C++ API. Replace the
asserts with bounds checks that return a parse error, and reject a
trailing '^' the same way.
Fixes: https://github.com/llvm/llvm-project/issues/223956
---
llvm/lib/IR/InlineAsm.cpp | 13 ++++--
.../Assembler/inline-asm-constraint-error.ll | 43 +++++++++++++++++++
2 files changed, 53 insertions(+), 3 deletions(-)
diff --git a/llvm/lib/IR/InlineAsm.cpp b/llvm/lib/IR/InlineAsm.cpp
index 922081468a7750..6b97384d65081b 100644
--- a/llvm/lib/IR/InlineAsm.cpp
+++ b/llvm/lib/IR/InlineAsm.cpp
@@ -197,17 +197,24 @@ bool InlineAsm::ConstraintInfo::Parse(StringRef Str,
++I;
} else if (*I == '^') {
// Multi-letter constraint
- // FIXME: For now assuming these are 2-character constraints.
+ if (static_cast<int>(E - I) < 3)
+ return true; // "^" + 2 letters.
pCodes->push_back(std::string(StringRef(I + 1, 2)));
I += 3;
} else if (*I == '@') {
// Multi-letter constraint
++I;
+ if (I == E)
+ return true; // "@"
unsigned char C = static_cast<unsigned char>(*I);
- assert(isdigit(C) && "Expected a digit!");
+ if (!isdigit(C))
+ return true; // Expected a digit after '@'.
int N = C - '0';
- assert(N > 0 && "Found a zero letter constraint!");
+ if (N == 0)
+ return true; // Zero-length constraint not allowed.
++I;
+ if (static_cast<int>(E - I) < N)
+ return true; // Not enough characters.
pCodes->push_back(std::string(StringRef(I, N)));
I += N;
} else {
diff --git a/llvm/test/Assembler/inline-asm-constraint-error.ll b/llvm/test/Assembler/inline-asm-constraint-error.ll
index f9d030c0434eb2..e39d337857b833 100644
--- a/llvm/test/Assembler/inline-asm-constraint-error.ll
+++ b/llvm/test/Assembler/inline-asm-constraint-error.ll
@@ -8,6 +8,11 @@
; RUN: not llvm-as < %t/incorrect-arg-num.ll 2>&1 | FileCheck %s --check-prefix=CHECK-INCORRECT-ARG-NUM
; RUN: not llvm-as < %t/label-after-clobber.ll 2>&1 | FileCheck %s --check-prefix=CHECK-LABEL-AFTER-CLOBBER
; RUN: not llvm-as < %t/output-after-label.ll 2>&1 | FileCheck %s --check-prefix=CHECK-OUTPUT-AFTER-LABEL
+; RUN: not llvm-as < %t/at-bad.ll 2>&1 | FileCheck %s --check-prefix=CHECK-AT-BAD
+; RUN: not llvm-as < %t/at-eof.ll 2>&1 | FileCheck %s --check-prefix=CHECK-AT-EOF
+; RUN: not llvm-as < %t/at-zero.ll 2>&1 | FileCheck %s --check-prefix=CHECK-AT-ZERO
+; RUN: not llvm-as < %t/at-short.ll 2>&1 | FileCheck %s --check-prefix=CHECK-AT-SHORT
+; RUN: not llvm-as < %t/caret-short.ll 2>&1 | FileCheck %s --check-prefix=CHECK-CARET-SHORT
;--- parse-fail.ll
; CHECK-PARSE-FAIL: failed to parse constraints
@@ -80,3 +85,41 @@ define void @foo() {
2:
ret void
}
+
+;--- at-bad.ll
+; CHECK-AT-BAD: failed to parse constraints
+define void @foo() {
+ ; '@' must be followed by a digit giving the number of constraint letters.
+ call void asm sideeffect "", "=@ccz"()
+ ret void
+}
+
+;--- at-eof.ll
+; CHECK-AT-EOF: failed to parse constraints
+define void @foo() {
+ call void asm sideeffect "", "=@"()
+ ret void
+}
+
+;--- at-zero.ll
+; CHECK-AT-ZERO: failed to parse constraints
+define void @foo() {
+ call void asm sideeffect "", "=@0abc"()
+ ret void
+}
+
+;--- at-short.ll
+; CHECK-AT-SHORT: failed to parse constraints
+define void @foo() {
+ ; Not enough letters for the declared count.
+ call void asm sideeffect "", "=@3ab"()
+ ret void
+}
+
+;--- caret-short.ll
+; CHECK-CARET-SHORT: failed to parse constraints
+define void @foo() {
+ ; '^' must be followed by exactly two constraint letters.
+ call void asm sideeffect "", "=^x"()
+ ret void
+}
More information about the llvm-commits
mailing list