From 6dc0e6ddd19ffce4a16163b43669f2f82a02687d Mon Sep 17 00:00:00 2001 From: "A. Jiang" Date: Thu, 12 Dec 2024 12:21:07 +0800 Subject: [PATCH 1/3] Detect some invalid contiguous ranges in `range_formatter` --- stl/inc/format | 6 +- tests/std/test.lst | 1 + .../env.lst | 4 + .../test.cpp | 111 ++++++++++++++++++ 4 files changed, 120 insertions(+), 2 deletions(-) create mode 100644 tests/std/tests/P2286R8_text_formatting_range_string_death/env.lst create mode 100644 tests/std/tests/P2286R8_text_formatting_range_string_death/test.cpp diff --git a/stl/inc/format b/stl/inc/format index 3e11d596dc5..8ec58d6f54d 100644 --- a/stl/inc/format +++ b/stl/inc/format @@ -3285,9 +3285,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."); +#if _CONTAINER_DEBUG_LEVEL > 0 + if constexpr (sizeof(_Size) > sizeof(size_t)) { + _STL_VERIFY(_Size <= SIZE_MAX, "The size of the formatted range is too large for a valid range."); } +#endif // _CONTAINER_DEBUG_LEVEL > 0 formatter, _CharT> _String_view_formatter; if (_Debug) { diff --git a/tests/std/test.lst b/tests/std/test.lst index 7b8847181e6..df09714c4b1 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..7e2297000fe --- /dev/null +++ b/tests/std/tests/P2286R8_text_formatting_range_string_death/test.cpp @@ -0,0 +1,111 @@ +// Copyright (c) Microsoft Corporation. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#define _CONTAINER_DEBUG_LEVEL 1 + +#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 { + 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_ = SIZE_MAX}; + (void) format("{:s}", v); +} + +int main(int argc, char** argv) { + std_testing::death_test_executive exec; + + exec.add_death_tests({ + test_case_invalid_range_size, + }); + + return exec.run(argc, argv); +} From a3bd42c045675913270808cc4dc65e92c248924a Mon Sep 17 00:00:00 2001 From: "A. Jiang" Date: Sun, 15 Dec 2024 23:59:49 +0800 Subject: [PATCH 2/3] Address review comments --- stl/inc/format | 6 +++--- .../P2286R8_text_formatting_range_string_death/test.cpp | 7 ++++--- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/stl/inc/format b/stl/inc/format index 8ec58d6f54d..4b688e4c8f3 100644 --- a/stl/inc/format +++ b/stl/inc/format @@ -3285,11 +3285,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 _CONTAINER_DEBUG_LEVEL > 0 +#ifdef _DEBUG if constexpr (sizeof(_Size) > sizeof(size_t)) { - _STL_VERIFY(_Size <= SIZE_MAX, "The size of the formatted range is too large for a valid range."); + _STL_VERIFY(_Size <= size_t{PTRDIFF_MAX}, "contiguous range has impossible size."); } -#endif // _CONTAINER_DEBUG_LEVEL > 0 +#endif // defined(_DEBUG) formatter, _CharT> _String_view_formatter; if (_Debug) { 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 index 7e2297000fe..6da1275550e 100644 --- a/tests/std/tests/P2286R8_text_formatting_range_string_death/test.cpp +++ b/tests/std/tests/P2286R8_text_formatting_range_string_death/test.cpp @@ -1,8 +1,6 @@ // Copyright (c) Microsoft Corporation. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -#define _CONTAINER_DEBUG_LEVEL 1 - #include #include #include @@ -74,6 +72,7 @@ struct based_huge_iterator { 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_; } @@ -96,16 +95,18 @@ struct based_huge_view : ranges::view_interface { static_assert(ranges::contiguous_range); void test_case_invalid_range_size() { - based_huge_view v{.base_ = "", .size_ = SIZE_MAX}; + 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); } From 2471e3e027da417f1752366444afe16c0d19172c Mon Sep 17 00:00:00 2001 From: "Stephan T. Lavavej" Date: Tue, 7 Jan 2025 12:53:24 -0800 Subject: [PATCH 3/3] Include ``. --- .../tests/P2286R8_text_formatting_range_string_death/test.cpp | 1 + 1 file changed, 1 insertion(+) 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 index 6da1275550e..bee4f6bc5a6 100644 --- a/tests/std/tests/P2286R8_text_formatting_range_string_death/test.cpp +++ b/tests/std/tests/P2286R8_text_formatting_range_string_death/test.cpp @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +#include #include #include #include