Skip to content

Commit 3f5c245

Browse files
committed
Basic: correct use-after-move on Windows
The order of evaluation for arguments is underspecified in the language specification. It is permissible to evluate right to left, resulting in the use after the move of the OwnedPtr. This happens in practice on Windows. Alter the construction to avoid this.
1 parent 468d9c3 commit 3f5c245

File tree

1 file changed

+10
-2
lines changed

1 file changed

+10
-2
lines changed

include/swift/Basic/OwnedString.h

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,8 +87,16 @@ class OwnedString {
8787
return makeUnowned(Str);
8888
} else {
8989
llvm::IntrusiveRefCntPtr<TextOwner> OwnedPtr(TextOwner::make(Str));
90-
return OwnedString(StringRef(OwnedPtr->getText(), Str.size()),
91-
std::move(OwnedPtr));
90+
// Allocate the StringRef on the stack first. This is to ensure that the
91+
// order of evaluation of the arguments is specified. The specification
92+
// does not specify the order of evaluation for the arguments. Itanium
93+
// chose to evaluate left to right, while Windows evaluates right to left.
94+
// As such, it is possible that the OwnedPtr has already been `std::move`d
95+
// by the time that the StringRef is attempted to be created. In such a
96+
// case, the offset of the field (+4) is used instead of the pointer to
97+
// the text, resulting in invalid memory references.
98+
StringRef S(OwnedPtr->getText(), Str.size());
99+
return OwnedString(S, std::move(OwnedPtr));
92100
}
93101
}
94102

0 commit comments

Comments
 (0)