-
Notifications
You must be signed in to change notification settings - Fork 13.6k
[IR] Fix assertion error in User new/delete edge case #129914
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[IR] Fix assertion error in User new/delete edge case #129914
Conversation
@llvm/pr-subscribers-llvm-ir Author: Marc Auberer (marcauberer) ChangesFixes #129900 If Full diff: https://github.com/llvm/llvm-project/pull/129914.diff 1 Files Affected:
diff --git a/llvm/lib/IR/User.cpp b/llvm/lib/IR/User.cpp
index b0aa785deb9af..ab44cb4b8a3f7 100644
--- a/llvm/lib/IR/User.cpp
+++ b/llvm/lib/IR/User.cpp
@@ -146,6 +146,9 @@ void *User::allocateFixedOperandUser(size_t Size, unsigned Us,
Use *Start = reinterpret_cast<Use *>(Storage + DescBytesToAllocate);
Use *End = Start + Us;
User *Obj = reinterpret_cast<User *>(End);
+ Obj->NumUserOperands = Us;
+ Obj->HasHungOffUses = false;
+ Obj->HasDescriptor = DescBytes != 0;
for (; Start != End; Start++)
new (Start) Use(Obj);
@@ -172,6 +175,9 @@ void *User::operator new(size_t Size, HungOffOperandsAllocMarker) {
void *Storage = ::operator new(Size + sizeof(Use *));
Use **HungOffOperandList = static_cast<Use **>(Storage);
User *Obj = reinterpret_cast<User *>(HungOffOperandList + 1);
+ Obj->NumUserOperands = 0;
+ Obj->HasHungOffUses = true;
+ Obj->HasDescriptor = false;
*HungOffOperandList = nullptr;
return Obj;
}
|
@nikic Could you trigger a compile time tracker run for this change? |
Compile-time: https://llvm-compile-time-tracker.com/compare.php?from=a614f2b489caa19001b2f44784514a6226f79cb7&to=e2454c7cb4245fceb05435cdcf775d4b1a47fc24&stat=instructions:u Impact is very small if there is any. |
Cool, thanks! |
/cherry-pick 8d38906 |
/pull-request #130580 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wouldn't the proper way to fix this be to change the operator delete overloads that take an alloc marker to actually use it?
llvm-project/llvm/include/llvm/IR/User.h
Lines 147 to 183 in 2e6402c
/// Placement delete - required by std, called if the ctor throws. | |
void operator delete(void *Usr, HungOffOperandsAllocMarker) { | |
// Note: If a subclass manipulates the information which is required to | |
// calculate the Usr memory pointer, e.g. NumUserOperands, the operator | |
// delete of that subclass has to restore the changed information to the | |
// original value, since the dtor of that class is not called if the ctor | |
// fails. | |
User::operator delete(Usr); | |
#ifndef LLVM_ENABLE_EXCEPTIONS | |
llvm_unreachable("Constructor throws?"); | |
#endif | |
} | |
/// Placement delete - required by std, called if the ctor throws. | |
void operator delete(void *Usr, IntrusiveOperandsAllocMarker) { | |
// Note: If a subclass manipulates the information which is required to calculate the | |
// Usr memory pointer, e.g. NumUserOperands, the operator delete of that subclass has | |
// to restore the changed information to the original value, since the dtor of that class | |
// is not called if the ctor fails. | |
User::operator delete(Usr); | |
#ifndef LLVM_ENABLE_EXCEPTIONS | |
llvm_unreachable("Constructor throws?"); | |
#endif | |
} | |
/// Placement delete - required by std, called if the ctor throws. | |
void operator delete(void *Usr, IntrusiveOperandsAndDescriptorAllocMarker) { | |
// Note: If a subclass manipulates the information which is required to calculate the | |
// Usr memory pointer, e.g. NumUserOperands, the operator delete of that subclass has | |
// to restore the changed information to the original value, since the dtor of that class | |
// is not called if the ctor fails. | |
User::operator delete(Usr); | |
#ifndef LLVM_ENABLE_EXCEPTIONS | |
llvm_unreachable("Constructor throws?"); | |
#endif | |
} |
@nikic Probably you are right, I am not particularly familiar in this corner ;) |
No need to revert, it's fine to apply it on top. |
Fixes llvm#129900 If `operator delete` was called after an unsuccessful constructor call after `operator new`, we ran into undefined behaviour. This was discovered by our malfunction tests while preparing an upgrade to LLVM 20, that explicitly check for such kind of bugs. (cherry picked from commit 8d38906)
Fixes #129900
If
operator delete
was called after an unsuccessful constructor call afteroperator new
, we ran into undefined behaviour.This was discovered by our malfunction tests while preparing an upgrade to LLVM 20, that explicitly check for such kind of bugs.