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

STL Hardening #5274

Merged
merged 42 commits into from
Feb 21, 2025
Merged
Show file tree
Hide file tree
Changes from 35 commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
7d01c7c
Exclude valarray's 28 binary ops, no test impact.
StephanTLavavej Jan 27, 2025
96471c5
Exclude condition_variable::wait_until, no test impact.
StephanTLavavej Jan 27, 2025
809bbee
Exclude basic_string::resize_and_overwrite, no test impact.
StephanTLavavej Jan 27, 2025
bd4e2ba
Exclude basic_string_view's ctor, update test coverage.
StephanTLavavej Jan 27, 2025
1f933a7
Exclude span::size_bytes, update test coverage.
StephanTLavavej Jan 27, 2025
a96d50b
Exclude most of `<mdspan>`, update test coverage.
StephanTLavavej Jan 28, 2025
4da1340
Exclude `<generator>`, update test coverage.
StephanTLavavej Jan 27, 2025
1acddc8
Exclude iota_view, update test coverage.
StephanTLavavej Jan 27, 2025
818163a
Exclude repeat_view, update test coverage.
StephanTLavavej Jan 27, 2025
03d1405
Exclude filter_view, update test coverage.
StephanTLavavej Jan 27, 2025
7d52a23
Exclude take_view, update test coverage.
StephanTLavavej Jan 27, 2025
6c79b36
Exclude take_while_view, update test coverage.
StephanTLavavej Jan 27, 2025
ad023f9
Exclude drop_view, update test coverage.
StephanTLavavej Jan 27, 2025
4a87616
Exclude drop_while_view, update test coverage.
StephanTLavavej Jan 27, 2025
9ef4d62
Exclude views::counted, update test coverage.
StephanTLavavej Jan 27, 2025
65d99ec
Exclude chunk_view, update test coverage.
StephanTLavavej Jan 27, 2025
311d174
Exclude slide_view, update test coverage.
StephanTLavavej Jan 27, 2025
40ea373
Exclude chunk_by_view, update test coverage.
StephanTLavavej Jan 27, 2025
705b096
Exclude stride_view, update test coverage.
StephanTLavavej Jan 27, 2025
e21a1ae
Exclude cartesian_product_view, update test coverage.
StephanTLavavej Jan 27, 2025
19e8406
Add `_MSVC_STL_HARDENING` control macros, initially off-by-default.
StephanTLavavej Jan 27, 2025
777f8ee
Harden array.
StephanTLavavej Jan 29, 2025
8b7ba64
Harden deque, overhaul pop_front/pop_back.
StephanTLavavej Jan 29, 2025
f1d8fe7
Harden forward_list, add pop_front.
StephanTLavavej Jan 29, 2025
c9ceb7e
Harden list.
StephanTLavavej Jan 29, 2025
d5a39a1
Harden vector, add vector<bool>::pop_back.
StephanTLavavej Jan 29, 2025
2c2a79e
Harden basic_string, add pop_back.
StephanTLavavej Jan 29, 2025
c65c68b
Harden basic_string_view.
StephanTLavavej Jan 29, 2025
0a799fb
Harden span.
StephanTLavavej Jan 30, 2025
78e097b
Harden mdspan.
StephanTLavavej Jan 30, 2025
9275943
Harden expected.
StephanTLavavej Jan 30, 2025
95355d4
Harden optional.
StephanTLavavej Jan 30, 2025
0b6c641
Harden valarray.
StephanTLavavej Jan 30, 2025
274a0bd
Harden ranges::view_interface.
StephanTLavavej Jan 30, 2025
e26df58
Harden bitset, overhauling operator[].
StephanTLavavej Jan 30, 2025
77b6fc5
Update test coverage for CDL removal.
StephanTLavavej Feb 5, 2025
9c8a7b1
Remove CDL's default definition and emit an error if users define it.
StephanTLavavej Feb 1, 2025
33c69b1
Add test coverage: GH_005090_stl_hardening
StephanTLavavej Feb 2, 2025
fae0a97
Enhancement: Move span::size_bytes() debug checks into span's ctors.
StephanTLavavej Feb 6, 2025
199fffd
Enhancement: Overhaul the STL's "doom function".
StephanTLavavej Feb 6, 2025
cc35a7b
Code review feedback: Improve comments and debug messages.
StephanTLavavej Feb 13, 2025
175f14d
Pre-emptively resolve conflict with GH 5274 by marking bitset.members…
StephanTLavavej Feb 19, 2025
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
16 changes: 10 additions & 6 deletions stl/inc/__msvc_string_view.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1379,7 +1379,7 @@ class basic_string_view { // wrapper for any kind of contiguous character buffer
constexpr basic_string_view(
_In_reads_(_Count) const const_pointer _Cts, const size_type _Count) noexcept // strengthened
: _Mydata(_Cts), _Mysize(_Count) {
#if _CONTAINER_DEBUG_LEVEL > 0
#if _ITERATOR_DEBUG_LEVEL != 0
_STL_VERIFY(_Count == 0 || _Cts, "non-zero size null string_view");
#endif
}
Expand Down Expand Up @@ -1474,7 +1474,7 @@ class basic_string_view { // wrapper for any kind of contiguous character buffer
}

_NODISCARD constexpr const_reference operator[](const size_type _Off) const noexcept /* strengthened */ {
#if _CONTAINER_DEBUG_LEVEL > 0
#if _MSVC_STL_HARDENING_BASIC_STRING_VIEW || _ITERATOR_DEBUG_LEVEL != 0
_STL_VERIFY(_Off < _Mysize, "string_view subscript out of range");
#endif

Expand All @@ -1489,31 +1489,35 @@ class basic_string_view { // wrapper for any kind of contiguous character buffer
}

_NODISCARD constexpr const_reference front() const noexcept /* strengthened */ {
#if _CONTAINER_DEBUG_LEVEL > 0
#if _MSVC_STL_HARDENING_BASIC_STRING_VIEW || _ITERATOR_DEBUG_LEVEL != 0
_STL_VERIFY(_Mysize != 0, "front() called on empty string_view");
#endif

return _Mydata[0];
}

_NODISCARD constexpr const_reference back() const noexcept /* strengthened */ {
#if _CONTAINER_DEBUG_LEVEL > 0
#if _MSVC_STL_HARDENING_BASIC_STRING_VIEW || _ITERATOR_DEBUG_LEVEL != 0
_STL_VERIFY(_Mysize != 0, "back() called on empty string_view");
#endif

return _Mydata[_Mysize - 1];
}

constexpr void remove_prefix(const size_type _Count) noexcept /* strengthened */ {
#if _CONTAINER_DEBUG_LEVEL > 0
#if _MSVC_STL_HARDENING_BASIC_STRING_VIEW || _ITERATOR_DEBUG_LEVEL != 0
_STL_VERIFY(_Mysize >= _Count, "cannot remove_prefix() larger than string_view size");
#endif

_Mydata += _Count;
_Mysize -= _Count;
}

constexpr void remove_suffix(const size_type _Count) noexcept /* strengthened */ {
#if _CONTAINER_DEBUG_LEVEL > 0
#if _MSVC_STL_HARDENING_BASIC_STRING_VIEW || _ITERATOR_DEBUG_LEVEL != 0
_STL_VERIFY(_Mysize >= _Count, "cannot remove_suffix() larger than string_view size");
#endif

_Mysize -= _Count;
}

Expand Down
16 changes: 8 additions & 8 deletions stl/inc/array
Original file line number Diff line number Diff line change
Expand Up @@ -531,7 +531,7 @@ public:
}

_NODISCARD _CONSTEXPR17 reference operator[](_In_range_(<, _Size) size_type _Pos) noexcept /* strengthened */ {
#if _CONTAINER_DEBUG_LEVEL > 0
#if _MSVC_STL_HARDENING_ARRAY || _ITERATOR_DEBUG_LEVEL != 0
_STL_VERIFY(_Pos < _Size, "array subscript out of range");
#endif

Expand All @@ -540,7 +540,7 @@ public:

_NODISCARD constexpr const_reference operator[](_In_range_(<, _Size) size_type _Pos) const noexcept
/* strengthened */ {
#if _CONTAINER_DEBUG_LEVEL > 0
#if _MSVC_STL_HARDENING_ARRAY || _ITERATOR_DEBUG_LEVEL != 0
_STL_VERIFY(_Pos < _Size, "array subscript out of range");
#endif

Expand Down Expand Up @@ -707,47 +707,47 @@ public:
}

_NODISCARD reference operator[](size_type) noexcept /* strengthened */ {
#if _CONTAINER_DEBUG_LEVEL > 0
#if _MSVC_STL_HARDENING_ARRAY || _ITERATOR_DEBUG_LEVEL != 0
_STL_REPORT_ERROR("array<T, 0> subscript is invalid");
#endif

return *data();
}

_NODISCARD const_reference operator[](size_type) const noexcept /* strengthened */ {
#if _CONTAINER_DEBUG_LEVEL > 0
#if _MSVC_STL_HARDENING_ARRAY || _ITERATOR_DEBUG_LEVEL != 0
_STL_REPORT_ERROR("array<T, 0> subscript is invalid");
#endif

return *data();
}

_NODISCARD reference front() noexcept /* strengthened */ {
#if _CONTAINER_DEBUG_LEVEL > 0
#if _MSVC_STL_HARDENING_ARRAY || _ITERATOR_DEBUG_LEVEL != 0
_STL_REPORT_ERROR("array<T, 0>::front() is invalid");
#endif

return *data();
}

_NODISCARD const_reference front() const noexcept /* strengthened */ {
#if _CONTAINER_DEBUG_LEVEL > 0
#if _MSVC_STL_HARDENING_ARRAY || _ITERATOR_DEBUG_LEVEL != 0
_STL_REPORT_ERROR("array<T, 0>::front() is invalid");
#endif

return *data();
}

_NODISCARD reference back() noexcept /* strengthened */ {
#if _CONTAINER_DEBUG_LEVEL > 0
#if _MSVC_STL_HARDENING_ARRAY || _ITERATOR_DEBUG_LEVEL != 0
_STL_REPORT_ERROR("array<T, 0>::back() is invalid");
#endif

return *data();
}

_NODISCARD const_reference back() const noexcept /* strengthened */ {
#if _CONTAINER_DEBUG_LEVEL > 0
#if _MSVC_STL_HARDENING_ARRAY || _ITERATOR_DEBUG_LEVEL != 0
_STL_REPORT_ERROR("array<T, 0>::back() is invalid");
#endif

Expand Down
18 changes: 8 additions & 10 deletions stl/inc/bitset
Original file line number Diff line number Diff line change
Expand Up @@ -116,14 +116,6 @@ public:
};

private:
static constexpr void _Validate(const size_t _Pos) noexcept { // verify that _Pos is within bounds
#if _ITERATOR_DEBUG_LEVEL == 0
(void) _Pos;
#else // ^^^ _ITERATOR_DEBUG_LEVEL == 0 / _ITERATOR_DEBUG_LEVEL != 0 vvv
_STL_VERIFY(_Pos < _Bits, "bitset subscript out of range");
#endif // ^^^ _ITERATOR_DEBUG_LEVEL != 0 ^^^
}

constexpr bool _Subscript(size_t _Pos) const noexcept {
return (_Array[_Pos / _Bitsperword] & (_Ty{1} << _Pos % _Bitsperword)) != 0;
}
Expand All @@ -133,12 +125,18 @@ private:

public:
_NODISCARD constexpr bool operator[](const size_t _Pos) const noexcept /* strengthened */ {
_Validate(_Pos);
#if _MSVC_STL_HARDENING_BITSET || _ITERATOR_DEBUG_LEVEL != 0
_STL_VERIFY(_Pos < _Bits, "bitset subscript out of range");
#endif

return _Subscript(_Pos);
}

_NODISCARD _CONSTEXPR23 reference operator[](const size_t _Pos) noexcept /* strengthened */ {
_Validate(_Pos);
#if _MSVC_STL_HARDENING_BITSET || _ITERATOR_DEBUG_LEVEL != 0
_STL_VERIFY(_Pos < _Bits, "bitset subscript out of range");
#endif

return reference(*this, _Pos);
}

Expand Down
51 changes: 19 additions & 32 deletions stl/inc/deque
Original file line number Diff line number Diff line change
Expand Up @@ -1063,15 +1063,15 @@ public:
}

_NODISCARD const_reference operator[](size_type _Pos) const noexcept /* strengthened */ {
#if _CONTAINER_DEBUG_LEVEL > 0
#if _MSVC_STL_HARDENING_DEQUE || _ITERATOR_DEBUG_LEVEL != 0
_STL_VERIFY(_Pos < _Mysize(), "deque subscript out of range");
#endif

return _Subscript(_Pos);
}

_NODISCARD reference operator[](size_type _Pos) noexcept /* strengthened */ {
#if _CONTAINER_DEBUG_LEVEL > 0
#if _MSVC_STL_HARDENING_DEQUE || _ITERATOR_DEBUG_LEVEL != 0
_STL_VERIFY(_Pos < _Mysize(), "deque subscript out of range");
#endif

Expand All @@ -1095,31 +1095,31 @@ public:
}

_NODISCARD reference front() noexcept /* strengthened */ {
#if _CONTAINER_DEBUG_LEVEL > 0
#if _MSVC_STL_HARDENING_DEQUE || _ITERATOR_DEBUG_LEVEL != 0
_STL_VERIFY(!empty(), "front() called on empty deque");
#endif

return _Subscript(0);
}

_NODISCARD const_reference front() const noexcept /* strengthened */ {
#if _CONTAINER_DEBUG_LEVEL > 0
#if _MSVC_STL_HARDENING_DEQUE || _ITERATOR_DEBUG_LEVEL != 0
_STL_VERIFY(!empty(), "front() called on empty deque");
#endif

return _Subscript(0);
}

_NODISCARD reference back() noexcept /* strengthened */ {
#if _CONTAINER_DEBUG_LEVEL > 0
#if _MSVC_STL_HARDENING_DEQUE || _ITERATOR_DEBUG_LEVEL != 0
_STL_VERIFY(!empty(), "back() called on empty deque");
#endif

return _Subscript(_Mysize() - 1);
}

_NODISCARD const_reference back() const noexcept /* strengthened */ {
#if _CONTAINER_DEBUG_LEVEL > 0
#if _MSVC_STL_HARDENING_DEQUE || _ITERATOR_DEBUG_LEVEL != 0
_STL_VERIFY(!empty(), "back() called on empty deque");
#endif

Expand Down Expand Up @@ -1473,47 +1473,34 @@ private:

public:
void pop_front() noexcept /* strengthened */ {
#if _MSVC_STL_HARDENING_DEQUE || _ITERATOR_DEBUG_LEVEL != 0
_STL_VERIFY(!empty(), "pop_front() called on empty deque");
#endif

#if _ITERATOR_DEBUG_LEVEL == 2
if (empty()) {
_STL_REPORT_ERROR("pop_front() called on empty deque");
} else { // something to erase, do it
_Orphan_off(_Myoff());
_Alty_traits::destroy(_Getal(), _Get_data()._Address_subscript(_Myoff()));
if (--_Mysize() == 0) {
_Myoff() = 0;
} else {
++_Myoff();
}
}
#else // ^^^ _ITERATOR_DEBUG_LEVEL == 2 / _ITERATOR_DEBUG_LEVEL < 2 vvv
_Orphan_off(_Myoff());
#endif
_Alty_traits::destroy(_Getal(), _Get_data()._Address_subscript(_Myoff()));
if (--_Mysize() == 0) {
_Myoff() = 0;
} else {
++_Myoff();
}
#endif // ^^^ _ITERATOR_DEBUG_LEVEL < 2 ^^^
}

void pop_back() noexcept /* strengthened */ {
#if _ITERATOR_DEBUG_LEVEL == 2
if (empty()) {
_STL_REPORT_ERROR("pop_back() called on empty deque");
} else { // something to erase, do it
size_type _Newoff = _Myoff() + _Mysize() - 1;
_Orphan_off(_Newoff);
_Alty_traits::destroy(_Getal(), _Get_data()._Address_subscript(_Newoff));
if (--_Mysize() == 0) {
_Myoff() = 0;
}
}
#else // ^^^ _ITERATOR_DEBUG_LEVEL == 2 / _ITERATOR_DEBUG_LEVEL < 2 vvv
#if _MSVC_STL_HARDENING_DEQUE || _ITERATOR_DEBUG_LEVEL != 0
_STL_VERIFY(!empty(), "pop_back() called on empty deque");
#endif

size_type _Newoff = _Myoff() + _Mysize() - 1;
#if _ITERATOR_DEBUG_LEVEL == 2
_Orphan_off(_Newoff);
#endif
_Alty_traits::destroy(_Getal(), _Get_data()._Address_subscript(_Newoff));
if (--_Mysize() == 0) {
_Myoff() = 0;
}
#endif // ^^^ _ITERATOR_DEBUG_LEVEL < 2 ^^^
}

iterator erase(const_iterator _Where) noexcept(is_nothrow_move_assignable_v<value_type>) /* strengthened */ {
Expand Down
Loading