Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 54 additions & 1 deletion stl/inc/__msvc_sanitizer_annotate_container.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,13 @@ _STL_DISABLE_CLANG_WARNINGS
// (this will be auto-defined on unsupported platforms)
// + _DISABLE_STRING_ANNOTATION: same, but for only `basic_string`
// + _DISABLE_VECTOR_ANNOTATION: same, but for only `vector`
// + _DISABLE_OPTIONAL_ANNOTATION: same, but for only `optional`
// - _ENABLE_STL_ANNOTATION_ON_UNSUPPORTED_PLATFORMS: Don't auto-disable ASan annotations
// - _ANNOTATE_STL: Even when ASan annotations are disabled, insert the code for annotating into the STL anyways;
// this is useful when building static libraries which may be linked against both ASan and non-ASan binaries.
// + _ANNOTATE_STRING: same, but only for `basic_string`
// + _ANNOTATE_VECTOR: same, but only for `vector`
// + _ANNOTATE_OPTIONAL: same, but only for `optional`

#if !defined(_DISABLE_STL_ANNOTATION) && !defined(_ENABLE_STL_ANNOTATION_ON_UNSUPPORTED_PLATFORMS)

Expand All @@ -46,6 +48,9 @@ _STL_DISABLE_CLANG_WARNINGS
#ifndef _DISABLE_VECTOR_ANNOTATION
#define _DISABLE_VECTOR_ANNOTATION
#endif // ^^^ !defined(_DISABLE_VECTOR_ANNOTATION) ^^^
#ifndef _DISABLE_OPTIONAL_ANNOTATION
#define _DISABLE_OPTIONAL_ANNOTATION
#endif // ^^^ !defined(_DISABLE_OPTIONAL_ANNOTATION) ^^^

#endif // ^^^ defined(_DISABLE_STL_ANNOTATION) ^^^

Expand All @@ -59,6 +64,10 @@ _STL_DISABLE_CLANG_WARNINGS
#define _ANNOTATE_VECTOR
#endif // ^^^ !defined(_ANNOTATE_VECTOR) ^^^

#ifndef _ANNOTATE_OPTIONAL
#define _ANNOTATE_OPTIONAL
#endif // ^^^ !defined(_ANNOTATE_OPTIONAL) ^^^

#endif // ^^^ defined(_ANNOTATE_STL) ^^^

#ifdef __SANITIZE_ADDRESS__
Expand All @@ -67,6 +76,8 @@ _STL_DISABLE_CLANG_WARNINGS
#define _INSERT_STRING_ANNOTATION
#define _ACTIVATE_VECTOR_ANNOTATION
#define _INSERT_VECTOR_ANNOTATION
#define _ACTIVATE_OPTIONAL_ANNOTATION
#define _INSERT_OPTIONAL_ANNOTATION

#elif defined(__clang__) // ^^^ defined(__SANITIZE_ADDRESS__) / defined(__clang__) vvv

Expand All @@ -75,6 +86,8 @@ _STL_DISABLE_CLANG_WARNINGS
#define _INSERT_STRING_ANNOTATION
#define _ACTIVATE_VECTOR_ANNOTATION
#define _INSERT_VECTOR_ANNOTATION
#define _ACTIVATE_OPTIONAL_ANNOTATION
#define _INSERT_OPTIONAL_ANNOTATION
#pragma comment(linker, "/INFERASANLIBS")
#endif // __has_feature(address_sanitizer)

Expand All @@ -89,13 +102,20 @@ _STL_DISABLE_CLANG_WARNINGS
#undef _ACTIVATE_VECTOR_ANNOTATION
#undef _INSERT_VECTOR_ANNOTATION
#endif // ^^^ defined(_DISABLE_VECTOR_ANNOTATION) ^^^
#ifdef _DISABLE_OPTIONAL_ANNOTATION
#undef _ACTIVATE_OPTIONAL_ANNOTATION
#undef _INSERT_OPTIONAL_ANNOTATION
#endif // ^^^ defined(_DISABLE_OPTIONAL_ANNOTATION) ^^^

#ifdef _ANNOTATE_STRING
#define _INSERT_STRING_ANNOTATION
#endif // ^^^ defined(_ANNOTATE_STRING) ^^^
#ifdef _ANNOTATE_VECTOR
#define _INSERT_VECTOR_ANNOTATION
#endif // ^^^ defined(_ANNOTATE_VECTOR) ^^^
#ifdef _ANNOTATE_OPTIONAL
#define _INSERT_OPTIONAL_ANNOTATION
#endif // ^^^ defined(_ANNOTATE_OPTIONAL) ^^^


#ifndef _INSERT_STRING_ANNOTATION
Expand All @@ -104,6 +124,9 @@ _STL_DISABLE_CLANG_WARNINGS
#ifndef _INSERT_VECTOR_ANNOTATION
#pragma detect_mismatch("annotate_vector", "0")
#endif // ^^^ !defined(_INSERT_VECTOR_ANNOTATION) ^^^
#ifndef _INSERT_OPTIONAL_ANNOTATION
#pragma detect_mismatch("annotate_optional", "0")
#endif // ^^^ !defined(_INSERT_OPTIONAL_ANNOTATION) ^^^

#ifdef _ACTIVATE_STRING_ANNOTATION
#pragma comment(lib, "stl_asan")
Expand All @@ -113,9 +136,14 @@ _STL_DISABLE_CLANG_WARNINGS
#pragma comment(lib, "stl_asan")
#pragma detect_mismatch("annotate_vector", "1")
#endif // ^^^ defined(_ACTIVATE_VECTOR_ANNOTATION) ^^^
#ifdef _ACTIVATE_OPTIONAL_ANNOTATION
#pragma comment(lib, "stl_asan")
#pragma detect_mismatch("annotate_optional", "1")
#endif // ^^^ defined(_ACTIVATE_OPTIONAL_ANNOTATION) ^^^

#undef _ACTIVATE_STRING_ANNOTATION
#undef _ACTIVATE_VECTOR_ANNOTATION
#undef _ACTIVATE_OPTIONAL_ANNOTATION

extern "C" {
#ifdef _INSERT_VECTOR_ANNOTATION
Expand All @@ -125,16 +153,27 @@ extern const bool _Asan_vector_should_annotate;
#ifdef _INSERT_STRING_ANNOTATION
extern const bool _Asan_string_should_annotate;
#endif

#ifdef _INSERT_OPTIONAL_ANNOTATION
extern const bool _Asan_optional_should_annotate;
#endif
} // extern "C"

#if defined(_INSERT_VECTOR_ANNOTATION) || defined(_INSERT_STRING_ANNOTATION)
#if defined(_INSERT_VECTOR_ANNOTATION) || defined(_INSERT_STRING_ANNOTATION) || defined(_INSERT_OPTIONAL_ANNOTATION)
extern "C" {
void __cdecl __asan_poison_memory_region(void const volatile* _Addr, size_t _Size);
void __cdecl __asan_unpoison_memory_region(void const volatile* _Addr, size_t _Size);

// This must match ASan's primary declaration, which isn't marked `noexcept`.
void __cdecl __sanitizer_annotate_contiguous_container(
const void* _First, const void* _End, const void* _Old_last, const void* _New_last);
} // extern "C"

#ifdef _M_ARM64EC
#pragma comment(linker, "/alternatename:#__asan_poison_memory_region=#__asan_poison_memory_region_default")
#pragma comment(linker, "/alternatename:__asan_poison_memory_region=__asan_poison_memory_region_default")
#pragma comment(linker, "/alternatename:#__asan_unpoison_memory_region=#__asan_unpoison_memory_region_default")
#pragma comment(linker, "/alternatename:__asan_unpoison_memory_region=__asan_unpoison_memory_region_default")
#pragma comment(linker, \
"/alternatename:#__sanitizer_annotate_contiguous_container=#__sanitizer_annotate_contiguous_container_default")
#pragma comment(linker, \
Expand All @@ -143,7 +182,13 @@ void __cdecl __sanitizer_annotate_contiguous_container(
#pragma comment(linker, "/alternatename:_Asan_vector_should_annotate=_Asan_vector_should_annotate_default")
#pragma comment(linker, "/alternatename:#_Asan_string_should_annotate=#_Asan_string_should_annotate_default")
#pragma comment(linker, "/alternatename:_Asan_string_should_annotate=_Asan_string_should_annotate_default")
#pragma comment(linker, "/alternatename:#_Asan_optional_should_annotate=#_Asan_optional_should_annotate_default")
#pragma comment(linker, "/alternatename:_Asan_optional_should_annotate=_Asan_optional_should_annotate_default")
#elif defined(_M_HYBRID)
#pragma comment(linker, "/alternatename:#__asan_poison_memory_region=#__asan_poison_memory_region_default")
#pragma comment(linker, "/alternatename:___asan_poison_memory_region=___asan_poison_memory_region_default")
#pragma comment(linker, "/alternatename:#__asan_unpoison_memory_region=#__asan_unpoison_memory_region_default")
#pragma comment(linker, "/alternatename:___asan_unpoison_memory_region=___asan_unpoison_memory_region_default")
#pragma comment(linker, \
"/alternatename:#__sanitizer_annotate_contiguous_container=#__sanitizer_annotate_contiguous_container_default")
#pragma comment(linker, \
Expand All @@ -152,16 +197,24 @@ void __cdecl __sanitizer_annotate_contiguous_container(
#pragma comment(linker, "/alternatename:__Asan_vector_should_annotate=__Asan_vector_should_annotate_default")
#pragma comment(linker, "/alternatename:#_Asan_string_should_annotate=#_Asan_string_should_annotate_default")
#pragma comment(linker, "/alternatename:__Asan_string_should_annotate=__Asan_string_should_annotate_default")
#pragma comment(linker, "/alternatename:#_Asan_optional_should_annotate=#_Asan_optional_should_annotate_default")
#pragma comment(linker, "/alternatename:__Asan_optional_should_annotate=__Asan_optional_should_annotate_default")
#elif defined(_M_IX86)
#pragma comment(linker, "/alternatename:___asan_poison_memory_region=___asan_poison_memory_region_default")
#pragma comment(linker, "/alternatename:___asan_unpoison_memory_region=___asan_unpoison_memory_region_default")
#pragma comment(linker, \
"/alternatename:___sanitizer_annotate_contiguous_container=___sanitizer_annotate_contiguous_container_default")
#pragma comment(linker, "/alternatename:__Asan_vector_should_annotate=__Asan_vector_should_annotate_default")
#pragma comment(linker, "/alternatename:__Asan_string_should_annotate=__Asan_string_should_annotate_default")
#pragma comment(linker, "/alternatename:__Asan_optional_should_annotate=__Asan_optional_should_annotate_default")
#elif defined(_M_X64) || defined(_M_ARM64)
#pragma comment(linker, "/alternatename:__asan_poison_memory_region=__asan_poison_memory_region_default")
#pragma comment(linker, "/alternatename:__asan_unpoison_memory_region=__asan_unpoison_memory_region_default")
#pragma comment(linker, \
"/alternatename:__sanitizer_annotate_contiguous_container=__sanitizer_annotate_contiguous_container_default")
#pragma comment(linker, "/alternatename:_Asan_vector_should_annotate=_Asan_vector_should_annotate_default")
#pragma comment(linker, "/alternatename:_Asan_string_should_annotate=_Asan_string_should_annotate_default")
#pragma comment(linker, "/alternatename:_Asan_optional_should_annotate=_Asan_optional_should_annotate_default")
#else // ^^^ known architecture / unknown architecture vvv
#error Unknown architecture
#endif // ^^^ unknown architecture ^^^
Expand Down
42 changes: 40 additions & 2 deletions stl/inc/optional
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ _EMIT_STL_WARNING(STL4038, "The contents of <optional> are available only with C
#if _HAS_CXX20
#include <compare>
#endif // _HAS_CXX20
#include <__msvc_sanitizer_annotate_container.hpp>
#include <exception>
#include <initializer_list>
#include <type_traits>
Expand Down Expand Up @@ -74,7 +75,13 @@ struct _Optional_destruct_base { // either contains a value of _Ty or is empty (
};
bool _Has_value;

constexpr _Optional_destruct_base() noexcept : _Dummy{}, _Has_value{false} {} // initialize an empty optional
constexpr _Optional_destruct_base() noexcept : _Dummy{}, _Has_value{false} { // initialize an empty optional
#ifdef _INSERT_OPTIONAL_ANNOTATION
if (!_STD _Is_constant_evaluated() && _Asan_optional_should_annotate) {
__asan_poison_memory_region(_STD addressof(_Value), sizeof(_Ty));
}
#endif
}

template <class... _Types>
constexpr explicit _Optional_destruct_base(in_place_t, _Types&&... _Args)
Expand All @@ -93,6 +100,11 @@ struct _Optional_destruct_base { // either contains a value of _Ty or is empty (

_CONSTEXPR20 void reset() noexcept {
_Has_value = false;
#ifdef _INSERT_OPTIONAL_ANNOTATION
if (!_STD _Is_constant_evaluated() && _Asan_optional_should_annotate) {
__asan_poison_memory_region(_STD addressof(_Value), sizeof(_Ty));
}
#endif
}
};

Expand All @@ -108,6 +120,12 @@ struct _Optional_destruct_base<_Ty, false> { // either contains a value of _Ty o
if (_Has_value) {
_Value.~_Ty();

#ifdef _INSERT_OPTIONAL_ANNOTATION
if (!_STD _Is_constant_evaluated() && _Asan_optional_should_annotate) {
__asan_poison_memory_region(_STD addressof(_Value), sizeof(_Ty));
}
#endif

#if _MSVC_STL_DESTRUCTOR_TOMBSTONES
// For the non-trivially destructible case, we can set the optional to be empty.
// We don't attempt to scribble over the bytes of the object's storage because that could be expensive
Expand All @@ -117,7 +135,13 @@ struct _Optional_destruct_base<_Ty, false> { // either contains a value of _Ty o
}
}

constexpr _Optional_destruct_base() noexcept : _Dummy{}, _Has_value{false} {} // initialize an empty optional
constexpr _Optional_destruct_base() noexcept : _Dummy{}, _Has_value{false} { // initialize an empty optional
#ifdef _INSERT_OPTIONAL_ANNOTATION
if (!_STD _Is_constant_evaluated() && _Asan_optional_should_annotate) {
__asan_poison_memory_region(_STD addressof(_Value), sizeof(_Ty));
}
#endif
}

template <class... _Types>
constexpr explicit _Optional_destruct_base(in_place_t, _Types&&... _Args)
Expand All @@ -139,6 +163,13 @@ struct _Optional_destruct_base<_Ty, false> { // either contains a value of _Ty o
_CONSTEXPR20 void reset() noexcept {
if (_Has_value) {
_Value.~_Ty();

#ifdef _INSERT_OPTIONAL_ANNOTATION
if (!_STD _Is_constant_evaluated() && _Asan_optional_should_annotate) {
__asan_poison_memory_region(_STD addressof(_Value), sizeof(_Ty));
}
#endif

_Has_value = false;
}
}
Expand All @@ -153,6 +184,13 @@ struct _Optional_construct_base : _Optional_destruct_base<_Ty> {
_CONSTEXPR20 _Ty& _Construct(_Types&&... _Args) noexcept(is_nothrow_constructible_v<_Ty, _Types...>) {
// transition from the empty to the value-containing state
_STL_INTERNAL_CHECK(!this->_Has_value);

#ifdef _INSERT_OPTIONAL_ANNOTATION
if (!_STD _Is_constant_evaluated() && _Asan_optional_should_annotate) {
__asan_unpoison_memory_region(_STD addressof(this->_Value), sizeof(_Ty));
}
#endif

_STD _Construct_in_place(this->_Value, _STD forward<_Types>(_Args)...);
this->_Has_value = true;
return this->_Value;
Expand Down
5 changes: 3 additions & 2 deletions stl/src/asan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@

namespace std {
extern "C" {
extern const bool _Asan_string_should_annotate = true;
extern const bool _Asan_vector_should_annotate = true;
extern const bool _Asan_string_should_annotate = true;
extern const bool _Asan_vector_should_annotate = true;
extern const bool _Asan_optional_should_annotate = true;
} // extern "C"
} // namespace std
8 changes: 6 additions & 2 deletions stl/src/asan_noop.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,12 @@
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

extern "C" {
extern const bool _Asan_string_should_annotate_default = false;
extern const bool _Asan_vector_should_annotate_default = false;
extern const bool _Asan_string_should_annotate_default = false;
extern const bool _Asan_vector_should_annotate_default = false;
extern const bool _Asan_optional_should_annotate_default = false;

void __cdecl __asan_poison_memory_region_default(void const volatile*, size_t) {}
void __cdecl __asan_unpoison_memory_region_default(void const volatile*, size_t) {}

void __cdecl __sanitizer_annotate_contiguous_container_default(
const void*, const void*, const void*, const void*) noexcept {}
Expand Down
1 change: 1 addition & 0 deletions tests/std/test.lst
Original file line number Diff line number Diff line change
Expand Up @@ -278,6 +278,7 @@ tests\GH_005553_regex_character_translation
tests\GH_005768_pow_accuracy
tests\GH_005800_stable_sort_large_alignment
tests\GH_005968_headers_provide_begin_end
tests\GH_005974_asan_annotate_optional
tests\LWG2381_num_get_floating_point
tests\LWG2510_tag_classes
tests\LWG2597_complex_branch_cut
Expand Down
52 changes: 52 additions & 0 deletions tests/std/tests/GH_005974_asan_annotate_optional/env.lst
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# Copyright (c) Microsoft Corporation.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

# This test matrix is the usual test matrix, with all currently unsupported options removed, crossed with the ASan flags.

# TRANSITION, google/sanitizers#328: clang-cl does not support /MDd or /MTd with ASan
RUNALL_INCLUDE ..\prefix.lst
RUNALL_CROSSLIST
PM_CL="/Zi /wd4611 /w14640 /Zc:threadSafeInit-" PM_LINK="/debug"
RUNALL_CROSSLIST
PM_CL="-fsanitize=address /BE /c /EHsc /MD /std:c++17"
PM_CL="-fsanitize=address /BE /c /EHsc /MDd /std:c++17 /permissive-"
PM_CL="-fsanitize=address /BE /c /EHsc /MT /std:c++20 /permissive-"
PM_CL="-fsanitize=address /BE /c /EHsc /MTd /std:c++latest /permissive-"
PM_CL="-fsanitize=address /EHsc /MD /std:c++17"
PM_CL="-fsanitize=address /EHsc /MD /std:c++20"
PM_CL="-fsanitize=address /EHsc /MD /std:c++latest /permissive- /Zc:char8_t- /Zc:preprocessor"
PM_CL="-fsanitize=address /EHsc /MD /std:c++latest /permissive- /Zc:noexceptTypes-"
PM_CL="-fsanitize=address /EHsc /MDd /std:c++17 /fp:except /Zc:preprocessor"
PM_CL="-fsanitize=address /EHsc /MDd /std:c++17 /permissive-"
PM_CL="-fsanitize=address /EHsc /MDd /std:c++20 /permissive-"
PM_CL="-fsanitize=address /EHsc /MDd /std:c++latest /permissive- /Zc:wchar_t-"
PM_CL="-fsanitize=address /EHsc /MDd /std:c++latest /permissive-"
PM_CL="-fsanitize=address /EHsc /MT /std:c++latest /permissive- /analyze:only /analyze:autolog-"
PM_CL="-fsanitize=address /EHsc /MT /std:c++latest /permissive-"
PM_CL="-fsanitize=address /EHsc /MTd /std:c++latest /permissive"
PM_CL="-fsanitize=address /EHsc /MTd /std:c++latest /permissive- /analyze:only /analyze:autolog-"
PM_CL="-fsanitize=address /EHsc /MTd /std:c++latest /permissive- /fp:strict"
PM_CL="-fsanitize=address /EHsc /MTd /std:c++latest /permissive-"
PM_CL="/D_ANNOTATE_OPTIONAL /BE /c /EHsc /MD /std:c++17"
PM_CL="/D_ANNOTATE_OPTIONAL /BE /c /EHsc /MDd /std:c++17 /permissive-"
PM_CL="/D_ANNOTATE_OPTIONAL /BE /c /EHsc /MT /std:c++20 /permissive-"
PM_CL="/D_ANNOTATE_OPTIONAL /BE /c /EHsc /MTd /std:c++latest /permissive-"
PM_CL="/D_ANNOTATE_OPTIONAL /EHsc /MD /std:c++17"
PM_CL="/D_ANNOTATE_OPTIONAL /EHsc /MD /std:c++20"
PM_CL="/D_ANNOTATE_OPTIONAL /EHsc /MD /std:c++latest /permissive- /Zc:char8_t- /Zc:preprocessor"
PM_CL="/D_ANNOTATE_OPTIONAL /EHsc /MD /std:c++latest /permissive- /Zc:noexceptTypes-"
PM_CL="/D_ANNOTATE_OPTIONAL /EHsc /MDd /std:c++17 /fp:except /Zc:preprocessor"
PM_CL="/D_ANNOTATE_OPTIONAL /EHsc /MDd /std:c++17 /permissive-"
PM_CL="/D_ANNOTATE_OPTIONAL /EHsc /MDd /std:c++20 /permissive-"
PM_CL="/D_ANNOTATE_OPTIONAL /EHsc /MDd /std:c++latest /permissive- /Zc:wchar_t-"
PM_CL="/D_ANNOTATE_OPTIONAL /EHsc /MDd /std:c++latest /permissive-"
PM_CL="/D_ANNOTATE_OPTIONAL /EHsc /MT /std:c++latest /permissive- /analyze:only /analyze:autolog-"
PM_CL="/D_ANNOTATE_OPTIONAL /EHsc /MT /std:c++latest /permissive-"
PM_CL="/D_ANNOTATE_OPTIONAL /EHsc /MTd /std:c++latest /permissive"
PM_CL="/D_ANNOTATE_OPTIONAL /EHsc /MTd /std:c++latest /permissive- /analyze:only /analyze:autolog-"
PM_CL="/D_ANNOTATE_OPTIONAL /EHsc /MTd /std:c++latest /permissive- /fp:strict"
PM_CL="/D_ANNOTATE_OPTIONAL /EHsc /MTd /std:c++latest /permissive-"
# TRANSITION, we don't use /ALTERNATENAME for Clang (see GH-5224) so we cannot test /D_ANNOTATE_OPTIONAL without -fsanitize=address
PM_COMPILER="clang-cl" PM_CL="-fsanitize=address -fno-ms-compatibility -fno-delayed-template-parsing -Wno-unqualified-std-cast-call /EHsc /MD /std:c++17"
PM_COMPILER="clang-cl" PM_CL="-fsanitize=address -fno-ms-compatibility -fno-delayed-template-parsing -Wno-unqualified-std-cast-call /EHsc /MT /std:c++20 /permissive-"
PM_COMPILER="clang-cl" PM_CL="-fsanitize=address -fno-ms-compatibility -fno-delayed-template-parsing -Wno-unqualified-std-cast-call /EHsc /MT /std:c++latest /permissive- /fp:strict"
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Copyright (c) Microsoft Corporation.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

## TRANSITION, VSO-1938218 ASAN is not yet supported on arm64
arm64
Loading