[llvm] [IR] Value::setNameImpl: fix use-after-free when new name aliases old storage (PR #173258)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Dec 22 05:14:24 PST 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-llvm-ir
Author: Wenju He (wenju-he)
<details>
<summary>Changes</summary>
When setName() is called with a StringRef derived from the current name, it results in a use-after-free error reported by AddressSanitizer. A newly added test ValueTest.setNameShrink demonstrates the issue. Fix by creating the new ValueName before removing/destroying the old one.
---
Full diff: https://github.com/llvm/llvm-project/pull/173258.diff
2 Files Affected:
- (modified) llvm/lib/IR/Value.cpp (+13-6)
- (modified) llvm/unittests/IR/ValueTest.cpp (+17)
``````````diff
diff --git a/llvm/lib/IR/Value.cpp b/llvm/lib/IR/Value.cpp
index b775cbb0c7920..a43d63077bf9f 100644
--- a/llvm/lib/IR/Value.cpp
+++ b/llvm/lib/IR/Value.cpp
@@ -356,21 +356,28 @@ void Value::setNameImpl(const Twine &NewName) {
if (getSymTab(this, ST))
return; // Cannot set a name on this value (e.g. constant).
+ ValueName *NewValueName = nullptr;
if (!ST) { // No symbol table to update? Just do the change.
+ if (!NameRef.empty()) {
+ // Create the new name.
+ MallocAllocator Allocator;
+ NewValueName = ValueName::create(NameRef, Allocator);
+ }
// NOTE: Could optimize for the case the name is shrinking to not deallocate
// then reallocated.
destroyValueName();
- if (!NameRef.empty()) {
- // Create the new name.
+ if (NewValueName) {
assert(NeedNewName);
- MallocAllocator Allocator;
- setValueName(ValueName::create(NameRef, Allocator));
+ setValueName(NewValueName);
getValueName()->setValue(this);
}
return;
}
+ if (!NameRef.empty())
+ NewValueName = ST->createValueName(NameRef, this);
+
// NOTE: Could optimize for the case the name is shrinking to not deallocate
// then reallocated.
if (hasName()) {
@@ -383,8 +390,8 @@ void Value::setNameImpl(const Twine &NewName) {
}
// Name is changing to something new.
- assert(NeedNewName);
- setValueName(ST->createValueName(NameRef, this));
+ assert(NeedNewName && NewValueName != nullptr);
+ setValueName(NewValueName);
}
void Value::setName(const Twine &NewName) {
diff --git a/llvm/unittests/IR/ValueTest.cpp b/llvm/unittests/IR/ValueTest.cpp
index 4d28fe019ecd2..e1df4c216089e 100644
--- a/llvm/unittests/IR/ValueTest.cpp
+++ b/llvm/unittests/IR/ValueTest.cpp
@@ -22,6 +22,23 @@ using namespace llvm;
namespace {
+TEST(ValueTest, setNameShrink) {
+ LLVMContext C;
+
+ const char *ModuleString = "define void @f1() {\n"
+ "bb0:\n"
+ " ret void\n"
+ "}\n";
+ SMDiagnostic Err;
+ std::unique_ptr<Module> M = parseAssemblyString(ModuleString, Err, C);
+
+ Function *F = M->getFunction("f1");
+ StringRef FName = F->getName();
+ FName = FName.drop_back();
+ F->setName(FName);
+ EXPECT_EQ(F->getName(), "f");
+}
+
TEST(ValueTest, UsedInBasicBlock) {
LLVMContext C;
``````````
</details>
https://github.com/llvm/llvm-project/pull/173258
More information about the llvm-commits
mailing list