[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