Skip to content

Commit f4dd1bc

Browse files
authored
[AMDGPU] Fix leak and self-assignment in copy assignment operator (#107847)
A static analyzer identified that this operator was unsafe in the case of self-assignment. In the placement new statement, StringValue's copy constructor was being implicitly called, which received a reference to "itself". In fact, it was being passed an old StringValue at the same address - one whose lifetime had already ended. The copy constructor was thus copying fields from a dead object. We need to be careful when switching active union members, and calling the destructor on the old StringValue will avoid memory leaks which I believe the old code exhibited.
1 parent a4b0153 commit f4dd1bc

File tree

1 file changed

+14
-8
lines changed

1 file changed

+14
-8
lines changed

llvm/lib/Target/AMDGPU/SIMachineFunctionInfo.h

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -100,19 +100,25 @@ struct SIArgument {
100100
SIArgument() : IsRegister(false), StackOffset(0) {}
101101
SIArgument(const SIArgument &Other) {
102102
IsRegister = Other.IsRegister;
103-
if (IsRegister) {
104-
::new ((void *)std::addressof(RegisterName))
105-
StringValue(Other.RegisterName);
106-
} else
103+
if (IsRegister)
104+
new (&RegisterName) StringValue(Other.RegisterName);
105+
else
107106
StackOffset = Other.StackOffset;
108107
Mask = Other.Mask;
109108
}
110109
SIArgument &operator=(const SIArgument &Other) {
110+
// Default-construct or destruct the old RegisterName in case of switching
111+
// union members
112+
if (IsRegister != Other.IsRegister) {
113+
if (Other.IsRegister)
114+
new (&RegisterName) StringValue();
115+
else
116+
RegisterName.~StringValue();
117+
}
111118
IsRegister = Other.IsRegister;
112-
if (IsRegister) {
113-
::new ((void *)std::addressof(RegisterName))
114-
StringValue(Other.RegisterName);
115-
} else
119+
if (IsRegister)
120+
RegisterName = Other.RegisterName;
121+
else
116122
StackOffset = Other.StackOffset;
117123
Mask = Other.Mask;
118124
return *this;

0 commit comments

Comments
 (0)