[llvm] [IR] Add assertions for unchecked getAsInteger() calls in atrib merging (PR #194713)
JP Hafer via llvm-commits
llvm-commits at lists.llvm.org
Tue Apr 28 13:03:03 PDT 2026
https://github.com/jph-13 created https://github.com/llvm/llvm-project/pull/194713
Several functions that merge or update string-valued function attributes (stack-probe-size, min-legal-vector-width) called
StringRef::getAsInteger() without checking the return value.
On parse failure, getAsInteger() leaves the output variable untouched, so these functions would silently operate on uninitialized values. While valid IR should never produce non-numeric strings for these attributes, the missing checks make it harder to diagnose corrupted IR or front-end bugs.
Add [[maybe_unused]] bool + assert to all five unchecked call sites across adjustCallerStackProbeSize, adjustMinLegalVectorWidth, and updateMinLegalVectorWidthAttr. Add death tests covering all three functions.
>From 949cf05ac3447135b5cd96c6b1c7363ec1de350c Mon Sep 17 00:00:00 2001
From: Jason Hafer <jhafer at mathworks.com>
Date: Tue, 28 Apr 2026 15:52:53 -0400
Subject: [PATCH] [IR] Add assertions for unchecked getAsInteger() calls in
attribute merging
Several functions that merge or update string-valued function attributes
(stack-probe-size, min-legal-vector-width) called
StringRef::getAsInteger() without checking the return value.
On parse failure, getAsInteger() leaves the output variable untouched,
so these functions would silently operate on uninitialized values.
While valid IR should never produce non-numeric strings for these
attributes, the missing checks make it harder to diagnose corrupted IR
or front-end bugs.
Add [[maybe_unused]] bool + assert to all five unchecked call sites
across adjustCallerStackProbeSize, adjustMinLegalVectorWidth, and
updateMinLegalVectorWidthAttr. Add death tests covering all three
functions.
---
llvm/lib/IR/Attributes.cpp | 20 ++++++++---
llvm/unittests/IR/AttributesTest.cpp | 50 ++++++++++++++++++++++++++++
2 files changed, 65 insertions(+), 5 deletions(-)
diff --git a/llvm/lib/IR/Attributes.cpp b/llvm/lib/IR/Attributes.cpp
index 4087b25951a1c..44962488b4a67 100644
--- a/llvm/lib/IR/Attributes.cpp
+++ b/llvm/lib/IR/Attributes.cpp
@@ -2687,8 +2687,12 @@ adjustCallerStackProbeSize(Function &Caller, const Function &Callee) {
Attribute CallerAttr = Caller.getFnAttribute("stack-probe-size");
if (CallerAttr.isValid()) {
uint64_t CallerStackProbeSize, CalleeStackProbeSize;
- CallerAttr.getValueAsString().getAsInteger(0, CallerStackProbeSize);
- CalleeAttr.getValueAsString().getAsInteger(0, CalleeStackProbeSize);
+ [[maybe_unused]] bool ErrCaller =
+ CallerAttr.getValueAsString().getAsInteger(0, CallerStackProbeSize);
+ assert(!ErrCaller && "Invalid stack-probe-size attribute value");
+ [[maybe_unused]] bool ErrCallee =
+ CalleeAttr.getValueAsString().getAsInteger(0, CalleeStackProbeSize);
+ assert(!ErrCallee && "Invalid stack-probe-size attribute value");
if (CallerStackProbeSize > CalleeStackProbeSize) {
Caller.addFnAttr(CalleeAttr);
@@ -2715,8 +2719,12 @@ adjustMinLegalVectorWidth(Function &Caller, const Function &Callee) {
Attribute CalleeAttr = Callee.getFnAttribute("min-legal-vector-width");
if (CalleeAttr.isValid()) {
uint64_t CallerVectorWidth, CalleeVectorWidth;
- CallerAttr.getValueAsString().getAsInteger(0, CallerVectorWidth);
- CalleeAttr.getValueAsString().getAsInteger(0, CalleeVectorWidth);
+ [[maybe_unused]] bool ErrCaller =
+ CallerAttr.getValueAsString().getAsInteger(0, CallerVectorWidth);
+ assert(!ErrCaller && "Invalid min-legal-vector-width attribute value");
+ [[maybe_unused]] bool ErrCallee =
+ CalleeAttr.getValueAsString().getAsInteger(0, CalleeVectorWidth);
+ assert(!ErrCallee && "Invalid min-legal-vector-width attribute value");
if (CallerVectorWidth < CalleeVectorWidth)
Caller.addFnAttr(CalleeAttr);
} else {
@@ -2813,7 +2821,9 @@ void AttributeFuncs::updateMinLegalVectorWidthAttr(Function &Fn,
Attribute Attr = Fn.getFnAttribute("min-legal-vector-width");
if (Attr.isValid()) {
uint64_t OldWidth;
- Attr.getValueAsString().getAsInteger(0, OldWidth);
+ [[maybe_unused]] bool Err =
+ Attr.getValueAsString().getAsInteger(0, OldWidth);
+ assert(!Err && "Invalid min-legal-vector-width attribute value");
if (Width > OldWidth)
Fn.addFnAttr("min-legal-vector-width", llvm::utostr(Width));
}
diff --git a/llvm/unittests/IR/AttributesTest.cpp b/llvm/unittests/IR/AttributesTest.cpp
index 5e795ef771713..bd40a678d4396 100644
--- a/llvm/unittests/IR/AttributesTest.cpp
+++ b/llvm/unittests/IR/AttributesTest.cpp
@@ -818,4 +818,54 @@ TEST(Attributes, ListIntersect) {
ASSERT_TRUE(Res->hasParamAttr(3, Attribute::ByVal));
}
+#ifdef GTEST_HAS_DEATH_TEST
+#ifndef NDEBUG
+
+TEST(Attributes, MergeInvalidStackProbeSize) {
+ LLVMContext C;
+ Module M("test", C);
+ FunctionType *FTy = FunctionType::get(Type::getVoidTy(C), false);
+ Function *Caller =
+ Function::Create(FTy, Function::ExternalLinkage, "caller", M);
+ Function *Callee =
+ Function::Create(FTy, Function::ExternalLinkage, "callee", M);
+
+ Caller->addFnAttr("stack-probe-size", "not-a-number");
+ Callee->addFnAttr("stack-probe-size", "4096");
+
+ EXPECT_DEATH(AttributeFuncs::mergeAttributesForInlining(*Caller, *Callee),
+ "Invalid stack-probe-size attribute value");
+}
+
+TEST(Attributes, MergeInvalidMinLegalVectorWidth) {
+ LLVMContext C;
+ Module M("test", C);
+ FunctionType *FTy = FunctionType::get(Type::getVoidTy(C), false);
+ Function *Caller =
+ Function::Create(FTy, Function::ExternalLinkage, "caller", M);
+ Function *Callee =
+ Function::Create(FTy, Function::ExternalLinkage, "callee", M);
+
+ Caller->addFnAttr("min-legal-vector-width", "512");
+ Callee->addFnAttr("min-legal-vector-width", "garbage");
+
+ EXPECT_DEATH(AttributeFuncs::mergeAttributesForInlining(*Caller, *Callee),
+ "Invalid min-legal-vector-width attribute value");
+}
+
+TEST(Attributes, UpdateInvalidMinLegalVectorWidth) {
+ LLVMContext C;
+ Module M("test", C);
+ FunctionType *FTy = FunctionType::get(Type::getVoidTy(C), false);
+ Function *Fn = Function::Create(FTy, Function::ExternalLinkage, "fn", M);
+
+ Fn->addFnAttr("min-legal-vector-width", "bad");
+
+ EXPECT_DEATH(AttributeFuncs::updateMinLegalVectorWidthAttr(*Fn, 256),
+ "Invalid min-legal-vector-width attribute value");
+}
+
+#endif // NDEBUG
+#endif // GTEST_HAS_DEATH_TEST
+
} // end anonymous namespace
More information about the llvm-commits
mailing list