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

<format>: Detect some invalid contiguous ranges in range_formatter #5187

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
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
6 changes: 4 additions & 2 deletions stl/inc/format
Original file line number Diff line number Diff line change
Expand Up @@ -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_t>(_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.");
frederick-vs-ja marked this conversation as resolved.
Show resolved Hide resolved
}
#endif // _CONTAINER_DEBUG_LEVEL > 0

formatter<basic_string_view<_CharT>, _CharT> _String_view_formatter;
if (_Debug) {
Expand Down
1 change: 1 addition & 0 deletions tests/std/test.lst
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Copyright (c) Microsoft Corporation.
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

RUNALL_INCLUDE ..\usual_latest_matrix.lst
111 changes: 111 additions & 0 deletions tests/std/tests/P2286R8_text_formatting_range_string_death/test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
// Copyright (c) Microsoft Corporation.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception

#define _CONTAINER_DEBUG_LEVEL 1

#include <cstddef>
#include <cstdint>
#include <format>
#include <ranges>

#include <range_algorithm_support.hpp>
#include <test_death.hpp>

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<ptrdiff_t>(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<ptrdiff_t>(offset_);
}

const char& operator[](difference_type n) const noexcept {
return base_[static_cast<ptrdiff_t>(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_;
frederick-vs-ja marked this conversation as resolved.
Show resolved Hide resolved
}

friend auto operator<=>(const based_huge_iterator&, const based_huge_iterator&) = default;
};

struct based_huge_view : ranges::view_interface<based_huge_view> {
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<based_huge_view>);

void test_case_invalid_range_size() {
based_huge_view v{.base_ = "", .size_ = SIZE_MAX};
frederick-vs-ja marked this conversation as resolved.
Show resolved Hide resolved
(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);
}