diff --git a/stl/inc/format b/stl/inc/format index 6026f34202d..53b960dbdd6 100644 --- a/stl/inc/format +++ b/stl/inc/format @@ -3288,9 +3288,11 @@ void _Range_formatter_format_as_string(_Range&& _Rng, _FormatContext& _Ctx, cons if constexpr (_RANGES contiguous_range<_Range>) { const auto _Size = _STD _To_unsigned_like(_RANGES distance(_Rng)); - if (!_STD in_range(_Size)) [[unlikely]] { - _Throw_format_error("Formatted range is too long."); +#ifdef _DEBUG + if constexpr (sizeof(_Size) > sizeof(size_t)) { + _STL_VERIFY(_Size <= size_t{PTRDIFF_MAX}, "contiguous range has impossible size."); } +#endif // defined(_DEBUG) formatter, _CharT> _String_view_formatter; if (_Debug) { diff --git a/tests/std/test.lst b/tests/std/test.lst index 4e38b8fb265..7093936102a 100644 --- a/tests/std/test.lst +++ b/tests/std/test.lst @@ -638,6 +638,7 @@ tests\P2286R8_text_formatting_range_map tests\P2286R8_text_formatting_range_sequence tests\P2286R8_text_formatting_range_set tests\P2286R8_text_formatting_range_string +tests\P2286R8_text_formatting_range_string_death tests\P2286R8_text_formatting_tuple tests\P2286R8_text_formatting_tuple_disambiguation tests\P2286R8_text_formatting_vector_bool_reference diff --git a/tests/std/tests/P2286R8_text_formatting_range_string_death/env.lst b/tests/std/tests/P2286R8_text_formatting_range_string_death/env.lst new file mode 100644 index 00000000000..642f530ffad --- /dev/null +++ b/tests/std/tests/P2286R8_text_formatting_range_string_death/env.lst @@ -0,0 +1,4 @@ +# Copyright (c) Microsoft Corporation. +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +RUNALL_INCLUDE ..\usual_latest_matrix.lst diff --git a/tests/std/tests/P2286R8_text_formatting_range_string_death/test.cpp b/tests/std/tests/P2286R8_text_formatting_range_string_death/test.cpp new file mode 100644 index 00000000000..bee4f6bc5a6 --- /dev/null +++ b/tests/std/tests/P2286R8_text_formatting_range_string_death/test.cpp @@ -0,0 +1,113 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include +#include +#include +#include +#include + +#include +#include + +using namespace std; + +struct based_huge_iterator { + const char* base_; + _Signed128 offset_; + + using iterator_category = contiguous_iterator_tag; + using difference_type = _Signed128; + using value_type = char; + + const char& operator*() const noexcept { + return base_[static_cast(offset_)]; + } + + based_huge_iterator& operator++() noexcept { + ++offset_; + return *this; + } + based_huge_iterator operator++(int) noexcept { + auto old = *this; + ++*this; + return old; + } + + based_huge_iterator& operator--() noexcept { + --offset_; + return *this; + } + based_huge_iterator operator--(int) noexcept { + auto old = *this; + --*this; + return old; + } + + based_huge_iterator& operator+=(difference_type n) noexcept { + offset_ += n; + return *this; + } + + based_huge_iterator& operator-=(difference_type n) noexcept { + offset_ -= n; + return *this; + } + + const char* operator->() const noexcept { + return base_ + static_cast(offset_); + } + + const char& operator[](difference_type n) const noexcept { + return base_[static_cast(offset_ + n)]; + } + + friend based_huge_iterator operator+(based_huge_iterator i, difference_type n) noexcept { + return {i.base_, i.offset_ + n}; + } + friend based_huge_iterator operator+(difference_type n, based_huge_iterator i) noexcept { + return {i.base_, i.offset_ + n}; + } + + friend based_huge_iterator operator-(based_huge_iterator i, difference_type n) noexcept { + return {i.base_, i.offset_ - n}; + } + friend difference_type operator-(based_huge_iterator i, based_huge_iterator j) noexcept { + assert(i.base_ == j.base_); + return i.offset_ - j.offset_; + } + + friend auto operator<=>(const based_huge_iterator&, const based_huge_iterator&) = default; +}; + +struct based_huge_view : ranges::view_interface { + const char* base_; + _Signed128 size_; + + based_huge_iterator begin() const noexcept { + return {base_, 0}; + } + + based_huge_iterator end() const noexcept { + return {base_, size_}; + } +}; + +static_assert(ranges::contiguous_range); + +void test_case_invalid_range_size() { + based_huge_view v{.base_ = "", .size_ = static_cast(PTRDIFF_MAX) + 1}; + (void) format("{:s}", v); +} + +int main(int argc, char** argv) { + std_testing::death_test_executive exec; + +#ifdef _DEBUG + exec.add_death_tests({ + test_case_invalid_range_size, + }); +#endif // defined(_DEBUG) + + return exec.run(argc, argv); +}