AK: Return early from swap() when swapping the same object

When swapping the same object, we could end up with a double-free error.
This was found while quick-sorting a Vector of Variants holding complex
types, reproduced by the new swap_same_complex_object test case.
This commit is contained in:
Timothy Flynn 2021-08-28 11:19:21 -04:00 committed by Linus Groh
parent aa2e19e58f
commit 587d4663a3
Notes: sideshowbarker 2024-07-18 05:04:51 +09:00
3 changed files with 59 additions and 0 deletions

View file

@ -99,6 +99,8 @@ constexpr T ceil_div(T a, U b)
template<typename T, typename U>
inline void swap(T& a, U& b)
{
if (&a == &b)
return;
U tmp = move((U&)a);
a = (T &&) move(b);
b = move(tmp);

View file

@ -51,6 +51,7 @@ set(AK_TEST_SOURCES
TestSourceLocation.cpp
TestSpan.cpp
TestStack.cpp
TestStdLibExtras.cpp
TestString.cpp
TestStringUtils.cpp
TestStringView.cpp

View file

@ -0,0 +1,56 @@
/*
* Copyright (c) 2021, Tim Flynn <trflynn89@pm.me>
*
* SPDX-License-Identifier: BSD-2-Clause
*/
#include <LibTest/TestSuite.h>
#include <AK/Optional.h>
#include <AK/StdLibExtras.h>
#include <AK/StringView.h>
#include <AK/Variant.h>
#include <AK/Vector.h>
TEST_CASE(swap)
{
int i = 4;
int j = 6;
swap(i, j);
EXPECT_EQ(i, 6);
EXPECT_EQ(j, 4);
}
TEST_CASE(swap_same_value)
{
int i = 4;
swap(i, i);
EXPECT_EQ(i, 4);
}
TEST_CASE(swap_same_complex_object)
{
struct Type1 {
StringView foo;
};
struct Type2 {
Optional<Type1> foo;
Vector<Type1> bar;
};
Variant<Type1, Type2> value1 { Type1 { "hello"sv } };
Variant<Type1, Type2> value2 { Type2 { {}, { { "goodbye"sv } } } };
swap(value1, value2);
EXPECT(value1.has<Type2>());
EXPECT(value2.has<Type1>());
swap(value1, value1);
EXPECT(value1.has<Type2>());
EXPECT(value2.has<Type1>());
}