Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Re-enable ASAN string annotations #3164

Merged
merged 33 commits into from
Dec 15, 2022
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
b1cfcde
initial attempt
strega-nil Oct 19, 2022
34bacc1
moar tests
strega-nil Oct 19, 2022
d51e580
CRs, plus some more minor work
strega-nil Oct 20, 2022
c62e749
minor code quality
strega-nil Oct 20, 2022
997f9b7
fix vector
strega-nil Oct 21, 2022
f108c24
fix stuff with testing
strega-nil Oct 24, 2022
86642d0
fixey fixey format
strega-nil Oct 24, 2022
277e68b
casey crs
strega-nil Oct 25, 2022
b76170a
fix comment
strega-nil Oct 25, 2022
99ea61a
moar fixin
strega-nil Oct 26, 2022
65dbe64
[ci skip] [wip] re-enable tests
strega-nil Oct 27, 2022
d869441
ooh, tests are passing!
strega-nil Nov 1, 2022
90ed742
oh okay, so you need to align both first and end
strega-nil Nov 1, 2022
7f52caa
CRs, plus fix vector test
strega-nil Nov 1, 2022
8afead5
add test for DevCom-10109507
strega-nil Nov 1, 2022
888cc8b
please tell me i actually fixed the tests this time
strega-nil Nov 1, 2022
dfaa6b1
ooh we can actually DO MORE
strega-nil Nov 1, 2022
42ef1a5
blampley blample more example
strega-nil Nov 2, 2022
9f503ca
remove noexcept from asan function
strega-nil Nov 2, 2022
f80f166
Amy CRs; force strings to be aligned on 4
strega-nil Nov 4, 2022
1641a6e
I dunno why this wasn't formatted
strega-nil Nov 4, 2022
f7cdbfb
Merge remote-tracking branch 'origin/main' into strega-nil/anno-asan01
strega-nil Nov 4, 2022
f12db09
Stephan CRs
strega-nil Nov 4, 2022
840cae1
misc cleanups
strega-nil Nov 4, 2022
6e37b5c
fix tests
strega-nil Nov 8, 2022
74f8320
forgot to format as I was copying back and forth
strega-nil Nov 8, 2022
cc418a3
zack's CRs
strega-nil Nov 8, 2022
f6984d8
xstring: remove memcpies in `_INSERT_STRING_ANNOTATION` mode
strega-nil Nov 14, 2022
13b122f
Merge remote-tracking branch 'origin/main' into strega-nil/anno-asan01
strega-nil Nov 21, 2022
ace0d8b
ughghghughuhughg
strega-nil Nov 21, 2022
b413060
Merge remote-tracking branch 'origin/main' into strega-nil/anno-asan01
strega-nil Dec 7, 2022
1f55a10
remove SBO annotations
strega-nil Dec 7, 2022
e38dd35
minor CRs
strega-nil Dec 13, 2022
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
47 changes: 11 additions & 36 deletions stl/inc/vector
Original file line number Diff line number Diff line change
Expand Up @@ -539,29 +539,6 @@ private:
_Apply_annotation(_My_data._Myfirst, _My_data._Myend, _My_data._Mylast, _My_data._Mylast + _Count);
}

_NODISCARD static const void* _Get_aligned_first(const void* _First, const void* _End) noexcept {
const auto _CFirst = reinterpret_cast<const char*>(_First);
const auto _CEnd = reinterpret_cast<const char*>(_End);
const size_t _Capacity = static_cast<size_t>(_CEnd - _CFirst);

if (_Capacity >= _Asan_granularity) {
// We are guaranteed to have sufficient space to find an aligned address.
return reinterpret_cast<const void*>(
(reinterpret_cast<uintptr_t>(_CFirst) + (_Asan_granularity - 1)) & ~(_Asan_granularity - 1));
}

uintptr_t _Alignment_offset = reinterpret_cast<uintptr_t>(_CFirst) & (_Asan_granularity - 1);
if (_Alignment_offset != 0) {
_Alignment_offset = _Asan_granularity - _Alignment_offset;
}

if (_Capacity > _Alignment_offset) {
return _CFirst + _Alignment_offset;
}

return nullptr;
}

static _CONSTEXPR20 void _Apply_annotation(
pointer _First_, pointer _End_, pointer _Old_last_, pointer _New_last_) noexcept {
_STL_INTERNAL_CHECK(_First_ != nullptr);
Expand All @@ -579,24 +556,22 @@ private:
return;
}

const auto _First = reinterpret_cast<const char*>(_Unfancy(_First_));
const auto _End = reinterpret_cast<const char*>(_Unfancy(_End_));
const auto _Old_last = reinterpret_cast<const char*>(_Unfancy(_Old_last_));
const auto _New_last = reinterpret_cast<const char*>(_Unfancy(_New_last_));
if constexpr (_Has_minimum_allocation_alignment<vector>) {
const void* const _First = _STD _Unfancy(_First_);
const void* const _End = _STD _Unfancy(_End_);
const void* const _Old_last = _STD _Unfancy(_Old_last_);
const void* const _New_last = _STD _Unfancy(_New_last_);
if constexpr ((_Container_allocation_minimum_alignment<vector>) > _Asan_granularity) {
strega-nil-ms marked this conversation as resolved.
Show resolved Hide resolved
strega-nil-ms marked this conversation as resolved.
Show resolved Hide resolved
strega-nil-ms marked this conversation as resolved.
Show resolved Hide resolved
__sanitizer_annotate_contiguous_container(_First, _End, _Old_last, _New_last);
} else {
const void* const _Aligned_first = _Get_aligned_first(_First, _End);
if (!_Aligned_first) {
// There is no aligned address within the underlying buffer; nothing to do.
const auto _Aligned = _STD _Get_asan_aligned_first_last(_First, _End);
if (!_Aligned._First) {
// The buffer does not cover at least a full shadow memory section; nothing to do.
return;
}

const void* const _Aligned_old_last = _Old_last < _Aligned_first ? _Aligned_first : _Old_last;
const void* const _Aligned_new_last = _New_last < _Aligned_first ? _Aligned_first : _New_last;
const void* const _Aligned_end = _End < _Aligned_first ? _Aligned_first : _End;
__sanitizer_annotate_contiguous_container(
_Aligned_first, _Aligned_end, _Aligned_old_last, _Aligned_new_last);
const void* const _Old_fixed = _Aligned._Clamp(_Old_last);
const void* const _New_fixed = _Aligned._Clamp(_New_last);
__sanitizer_annotate_contiguous_container(_Aligned._First, _Aligned._End, _Old_fixed, _New_fixed);
}
}

Expand Down
57 changes: 57 additions & 0 deletions stl/inc/xmemory
Original file line number Diff line number Diff line change
Expand Up @@ -776,6 +776,63 @@ _NODISCARD constexpr allocation_result<typename allocator_traits<_Alloc>::pointe
// The number of user bytes a single byte of ASAN shadow memory can track.
_INLINE_VAR constexpr size_t _Asan_granularity = 8;
strega-nil-ms marked this conversation as resolved.
Show resolved Hide resolved

struct _AsanAlignedPointers {
strega-nil-ms marked this conversation as resolved.
Show resolved Hide resolved
const void* _First;
const void* _End;

constexpr const void* _Clamp(const void* _Mid) const noexcept {
strega-nil-ms marked this conversation as resolved.
Show resolved Hide resolved
if (_Mid < _First) {
return _First;
} else if (_Mid > _End) {
return _End;
} else {
return _Mid;
}
}
};
// Returns {nullptr, nullptr} if [_First, _Last) does not cover a full ASAN shadow memory section.
// `__sanitizer_annotate_contiguous_container` _requires_
// its first pointer to be aligned to the beginning of an ASAN shadow memory section (a single 8-byte).
// When the `end` pointer is not on a boundary, it will also mark the remainder of the section.
// This means that if you have, for example:
// struct alignas(8) cat {
// int meow; // bytes [0, 4)
// char buffer[16]; // bytes [4, 20)
// int purr; // bytes [20, 24)
// };
// you cannot mark `buffer + [0, 4)`, since `buffer + 0` doesn't start a shadow memory section
// (i.e., it's not on an 8-byte boundary).
// Additionally, if you attempt to mark up to `buffer + 16` (the real end of buffer), it'll also mark `purr`.
// Thus, the only part you can _actually_ mark is the complete shadow memory section of `buffer + [4, 12)`
// (i.e., bytes [8, 16)).
_NODISCARD inline _AsanAlignedPointers _Get_asan_aligned_first_last(
const void* const _First, const void* const _Last) noexcept {
constexpr static uintptr_t _Mask = ~(_Asan_granularity - 1);

const auto _First_address = reinterpret_cast<uintptr_t>(_First);
const auto _Last_address = reinterpret_cast<uintptr_t>(_Last);

const uintptr_t _Aligned_first_address = (_First_address + _Asan_granularity - 1) & _Mask;
const uintptr_t _Aligned_last_address = _Last_address & _Mask;

if (_Aligned_first_address == _Aligned_last_address) {
strega-nil-ms marked this conversation as resolved.
Show resolved Hide resolved
return {nullptr, nullptr};
} else {
return {
reinterpret_cast<const void*>(_Aligned_first_address),
reinterpret_cast<const void*>(_Aligned_last_address),
};
}
}

template <class _Container, class = void>
_INLINE_VAR constexpr size_t _Container_allocation_minimum_alignment = alignof(typename _Container::value_type);

template <class _Container>
_INLINE_VAR constexpr size_t _Container_allocation_minimum_alignment<_Container,
void_t<decltype(_Container::allocator_type::_Minimum_allocation_alignment)>> =
strega-nil-ms marked this conversation as resolved.
Show resolved Hide resolved
(_STD max)(alignof(typename _Container::value_type), _Container::allocator_type::_Minimum_allocation_alignment);

_EXPORT_STD template <class _Ty>
class allocator {
public:
Expand Down
Loading