[Mlir-commits] [mlir] [mlir][NVVM] Reject malformed target chip names (PR #220873)
Mehdi Amini
llvmlistbot at llvm.org
Mon Sep 7 15:30:19 PDT 2026
https://github.com/joker-eph updated https://github.com/llvm/llvm-project/pull/220873
>From 4fcf451312e524bdd559da4571afa1acc8303eb8 Mon Sep 17 00:00:00 2001
From: Mehdi Amini <joker.eph at gmail.com>
Date: Wed, 2 Sep 2026 14:58:42 -0700
Subject: [PATCH] [mlir][NVVM] Reject malformed target chip names
Parse the complete sm_<version>[a|f] grammar before using the SM version.
This prevents a failed integer conversion from leaving the version
uninitialized and also rejects overflowing encodings.
Valgrind did not observe the uninitialized read in the optimized pre-fix
binary; the arbitrary value reached the existing diagnostic:
error: unexpected error: Minimum NVVM target SM version is sm_20
==534292== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
Found by Coverity.
Assisted-by: Codex
---
.../Dialect/LLVMIR/NVVMRequiresSMTraits.h | 32 ++++++++++++++-----
mlir/lib/Dialect/LLVMIR/IR/NVVMDialect.cpp | 11 +++++--
.../Dialect/LLVMIR/nvvm-target-invalid.mlir | 8 +++++
3 files changed, 40 insertions(+), 11 deletions(-)
diff --git a/mlir/include/mlir/Dialect/LLVMIR/NVVMRequiresSMTraits.h b/mlir/include/mlir/Dialect/LLVMIR/NVVMRequiresSMTraits.h
index fa7eb4194dfac..d60b7c8bb6867 100644
--- a/mlir/include/mlir/Dialect/LLVMIR/NVVMRequiresSMTraits.h
+++ b/mlir/include/mlir/Dialect/LLVMIR/NVVMRequiresSMTraits.h
@@ -15,7 +15,10 @@
#include "mlir/IR/OpDefinition.h"
#include "mlir/IR/StorageUniquerSupport.h"
-#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringRef.h"
+
+#include <limits>
+#include <optional>
namespace mlir {
@@ -23,6 +26,7 @@ namespace NVVM {
// Struct to store and check compatibility of SM versions.
struct NVVMCheckSMVersion {
+ static constexpr llvm::StringLiteral kStreamingMultiprocessorPrefix = "sm_";
static constexpr char kArchAcceleratedSuffix = 'a';
static constexpr char kFamilySpecificSuffix = 'f';
@@ -62,16 +66,28 @@ struct NVVMCheckSMVersion {
// Parses an SM version string and returns an equivalent full SM version
// integer.
- static unsigned getTargetFullSmVersionFromStr(StringRef smVersionString) {
- bool isAA = smVersionString.back() == kArchAcceleratedSuffix;
- bool isFS = smVersionString.back() == kFamilySpecificSuffix;
+ static std::optional<unsigned>
+ getTargetFullSmVersionFromStr(StringRef smVersionString) {
+ if (!smVersionString.consume_front(kStreamingMultiprocessorPrefix))
+ return std::nullopt;
+
+ unsigned suffix = 0;
+ if (!smVersionString.empty()) {
+ if (smVersionString.back() == kArchAcceleratedSuffix)
+ suffix = 3;
+ else if (smVersionString.back() == kFamilySpecificSuffix)
+ suffix = 2;
+ if (suffix)
+ smVersionString = smVersionString.drop_back();
+ }
unsigned smVersion;
- smVersionString.drop_front(3)
- .take_while([](char c) { return llvm::isDigit(c); })
- .getAsInteger(10, smVersion);
+ if (smVersionString.empty() ||
+ smVersionString.getAsInteger(10, smVersion) ||
+ smVersion > (std::numeric_limits<unsigned>::max() - suffix) / 10)
+ return std::nullopt;
- return smVersion * 10 + (isAA ? 3 : 0) + (isFS ? 2 : 0);
+ return smVersion * 10 + suffix;
}
static bool isMinimumSMVersion(unsigned fullSmVersion) {
diff --git a/mlir/lib/Dialect/LLVMIR/IR/NVVMDialect.cpp b/mlir/lib/Dialect/LLVMIR/IR/NVVMDialect.cpp
index c6ed0a840a1b0..b8c4868206761 100644
--- a/mlir/lib/Dialect/LLVMIR/IR/NVVMDialect.cpp
+++ b/mlir/lib/Dialect/LLVMIR/IR/NVVMDialect.cpp
@@ -7148,9 +7148,14 @@ LogicalResult NVVMTargetAttr::verifyTarget(Operation *gpuModule) {
"NVVM target attribute must be attached to a GPU module");
}
- const unsigned targetFullSmVersion =
+ std::optional<unsigned> targetFullSmVersion =
NVVMCheckSMVersion::getTargetFullSmVersionFromStr(getChip());
- if (!NVVMCheckSMVersion::isMinimumSMVersion(targetFullSmVersion)) {
+ if (!targetFullSmVersion)
+ return emitError(gpuModule->getLoc())
+ << "invalid NVVM target chip \"" << getChip()
+ << "\", expected sm_<version>[a|f]";
+
+ if (!NVVMCheckSMVersion::isMinimumSMVersion(*targetFullSmVersion)) {
return emitError(gpuModule->getLoc(),
"Minimum NVVM target SM version is sm_20");
}
@@ -7160,7 +7165,7 @@ LogicalResult NVVMTargetAttr::verifyTarget(Operation *gpuModule) {
if (auto reqOp = llvm::dyn_cast<NVVM::RequiresSMInterface>(op)) {
const NVVMCheckSMVersion requirement =
reqOp.getRequiredMinSMVersion();
- if (!requirement.isCompatibleWith(targetFullSmVersion)) {
+ if (!requirement.isCompatibleWith(*targetFullSmVersion)) {
op->emitOpError() << "is not supported on " << getChip();
return WalkResult::interrupt();
}
diff --git a/mlir/test/Dialect/LLVMIR/nvvm-target-invalid.mlir b/mlir/test/Dialect/LLVMIR/nvvm-target-invalid.mlir
index 0f20e66dd2019..992b17564d35e 100644
--- a/mlir/test/Dialect/LLVMIR/nvvm-target-invalid.mlir
+++ b/mlir/test/Dialect/LLVMIR/nvvm-target-invalid.mlir
@@ -17,3 +17,11 @@ module attributes {gpu.container_module} {
gpu.module @nvvm_target_invalid_opt_level [#nvvm.target<chip = "sm_90", O = 4>] {
}
}
+
+// -----
+
+module attributes {gpu.container_module} {
+ // expected-error @+1 {{invalid NVVM target chip "not-an-sm"}}
+ gpu.module @nvvm_target_invalid_chip [#nvvm.target<chip = "not-an-sm">] {
+ }
+}
More information about the Mlir-commits
mailing list