Skip to content

Commit d655c17

Browse files
ASan should detect writing to a basic_string's reserved but uninitialized memory (#5252)
Co-authored-by: David Justo <[email protected]> Co-authored-by: Stephan T. Lavavej <[email protected]>
1 parent 2446dba commit d655c17

File tree

2 files changed

+36
-11
lines changed

2 files changed

+36
-11
lines changed

stl/inc/xstring

+8
Original file line numberDiff line numberDiff line change
@@ -2418,6 +2418,10 @@ public:
24182418
[](_Elem* const _New_ptr, const _Elem* const _Old_ptr, const size_type _Old_size)
24192419
_STATIC_CALL_OPERATOR { _Traits::copy(_New_ptr, _Old_ptr, _Old_size + 1); });
24202420

2421+
// `_Reallocate_grow_by` calls `_ASAN_STRING_CREATE` assuming that the string
2422+
// has size (initialized memory) equal to its new capacity (allocated memory).
2423+
// This is not true for the `reserve` method, so we modify the ASan annotation.
2424+
_ASAN_STRING_MODIFY(*this, _Mypair._Myval2._Mysize, _Old_size);
24212425
_Mypair._Myval2._Mysize = _Old_size;
24222426
}
24232427

@@ -2442,6 +2446,10 @@ public:
24422446
[](_Elem* const _New_ptr, const _Elem* const _Old_ptr, const size_type _Old_size)
24432447
_STATIC_CALL_OPERATOR { _Traits::copy(_New_ptr, _Old_ptr, _Old_size + 1); });
24442448

2449+
// `_Reallocate_grow_by` calls `_ASAN_STRING_CREATE` assuming that the string
2450+
// has size (initialized memory) equal to its new capacity (allocated memory).
2451+
// This is not true for the `reserve` method, so we modify the ASan annotation.
2452+
_ASAN_STRING_MODIFY(*this, _Mypair._Myval2._Mysize, _Old_size);
24452453
_Mypair._Myval2._Mysize = _Old_size;
24462454
return;
24472455
}

tests/std/tests/GH_002030_asan_annotate_string/test.cpp

+28-11
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
#include <new>
2121
#include <sstream>
2222
#include <string>
23+
24+
#include <test_death.hpp>
2325
#if _HAS_CXX17
2426
#include <string_view>
2527
#endif // _HAS_CXX17
@@ -1917,17 +1919,32 @@ void test_gh_3955() {
19171919
assert(s == t);
19181920
}
19191921

1920-
int main() {
1921-
run_allocator_matrix<char>();
1922+
void test_gh_5251() {
1923+
// GH-5251 <string>: ASan annotations do not prevent writing to allocated
1924+
// but uninitialized basic_string memory
1925+
string myString;
1926+
myString.reserve(100);
1927+
char* myData = &myString[0];
1928+
myData[50] = 'A'; // ASan should fire!
1929+
}
1930+
1931+
int main(int argc, char* argv[]) {
1932+
std_testing::death_test_executive exec([] {
1933+
run_allocator_matrix<char>();
19221934
#ifdef __cpp_char8_t
1923-
run_allocator_matrix<char8_t>();
1935+
run_allocator_matrix<char8_t>();
19241936
#endif // __cpp_char8_t
1925-
run_allocator_matrix<char16_t>();
1926-
run_allocator_matrix<char32_t>();
1927-
run_allocator_matrix<wchar_t>();
1928-
1929-
test_DevCom_10116361();
1930-
test_DevCom_10109507();
1931-
test_gh_3883();
1932-
test_gh_3955();
1937+
run_allocator_matrix<char16_t>();
1938+
run_allocator_matrix<char32_t>();
1939+
run_allocator_matrix<wchar_t>();
1940+
1941+
test_DevCom_10116361();
1942+
test_DevCom_10109507();
1943+
test_gh_3883();
1944+
test_gh_3955();
1945+
});
1946+
#ifdef __SANITIZE_ADDRESS__
1947+
exec.add_death_tests({test_gh_5251});
1948+
#endif // ASan instrumentation enabled
1949+
return exec.run(argc, argv);
19331950
}

0 commit comments

Comments
 (0)