mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 15:57:45 +00:00
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:
parent
aa2e19e58f
commit
587d4663a3
3 changed files with 59 additions and 0 deletions
|
@ -99,6 +99,8 @@ constexpr T ceil_div(T a, U b)
|
||||||
template<typename T, typename U>
|
template<typename T, typename U>
|
||||||
inline void swap(T& a, U& b)
|
inline void swap(T& a, U& b)
|
||||||
{
|
{
|
||||||
|
if (&a == &b)
|
||||||
|
return;
|
||||||
U tmp = move((U&)a);
|
U tmp = move((U&)a);
|
||||||
a = (T &&) move(b);
|
a = (T &&) move(b);
|
||||||
b = move(tmp);
|
b = move(tmp);
|
||||||
|
|
|
@ -51,6 +51,7 @@ set(AK_TEST_SOURCES
|
||||||
TestSourceLocation.cpp
|
TestSourceLocation.cpp
|
||||||
TestSpan.cpp
|
TestSpan.cpp
|
||||||
TestStack.cpp
|
TestStack.cpp
|
||||||
|
TestStdLibExtras.cpp
|
||||||
TestString.cpp
|
TestString.cpp
|
||||||
TestStringUtils.cpp
|
TestStringUtils.cpp
|
||||||
TestStringView.cpp
|
TestStringView.cpp
|
||||||
|
|
56
Tests/AK/TestStdLibExtras.cpp
Normal file
56
Tests/AK/TestStdLibExtras.cpp
Normal 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>());
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue