Skip to content

[libc++][hardening] Use static_assert for __(static_)bounded_iter #115304

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

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
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
7 changes: 5 additions & 2 deletions libcxx/include/__iterator/bounded_iter.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,11 @@ _LIBCPP_BEGIN_NAMESPACE_STD
// pointer, it is undefined at the language level (see [expr.add]). If
// bounded iterators exhibited this undefined behavior, we risk compiler
// optimizations deleting non-redundant bounds checks.
template <class _Iterator, class = __enable_if_t< __libcpp_is_contiguous_iterator<_Iterator>::value > >
template <class _Iterator>
struct __bounded_iter {
static_assert(__libcpp_is_contiguous_iterator<_Iterator>::value,
"Only contiguous iterators can be adapted by __bounded_iter.");

using value_type = typename iterator_traits<_Iterator>::value_type;
using difference_type = typename iterator_traits<_Iterator>::difference_type;
using pointer = typename iterator_traits<_Iterator>::pointer;
Expand Down Expand Up @@ -247,7 +250,7 @@ struct __bounded_iter {
private:
template <class>
friend struct pointer_traits;
template <class, class>
template <class>
friend struct __bounded_iter;
_Iterator __current_; // current iterator
_Iterator __begin_, __end_; // valid range represented as [begin, end]
Expand Down
5 changes: 4 additions & 1 deletion libcxx/include/__iterator/static_bounded_iter.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,11 @@ struct __static_bounded_iter_storage<_Iterator, 0> {
// it can be computed from the start of the range.
//
// The operations on which this iterator wrapper traps are the same as `__bounded_iter`.
template <class _Iterator, size_t _Size, class = __enable_if_t<__libcpp_is_contiguous_iterator<_Iterator>::value> >
template <class _Iterator, size_t _Size>
struct __static_bounded_iter {
static_assert(__libcpp_is_contiguous_iterator<_Iterator>::value,
"Only contiguous iterators can be adapted by __static_bounded_iter.");

using value_type = typename iterator_traits<_Iterator>::value_type;
using difference_type = typename iterator_traits<_Iterator>::difference_type;
using pointer = typename iterator_traits<_Iterator>::pointer;
Expand Down
25 changes: 25 additions & 0 deletions libcxx/test/libcxx/iterators/contiguous_iterators.verify.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
//===----------------------------------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//

// <iterator>

// __bounded_iter<_Iter>

// Verify that __bounded_iter does not accept non-contiguous iterators as determined by __libcpp_is_contiguous_iterator.
// static_assert should be used, see https://github.com/llvm/llvm-project/issues/115002.
// __wrap_iter cannot be so handled because it may directly wrap user-defined fancy pointers in libc++'s vector.

#include <deque>
#include <vector>
#include <array>

// expected-error-re@*:* {{static assertion failed due to requirement {{.*}}Only contiguous iterators can be adapted by __bounded_iter.}}
std::__bounded_iter<std::deque<int>::iterator> bounded_iter;
// expected-error-re@*:* {{static assertion failed due to requirement {{.*}}Only contiguous iterators can be adapted by __static_bounded_iter.}}
std::__static_bounded_iter<std::deque<int>::iterator, 42> statically_bounded_iter;
Loading