[libcxx-commits] [libcxx] [libc++][hardening] Check bounds on arithmetic in __bounded_iter (PR #78876)
Konstantin Varlamov via libcxx-commits
libcxx-commits at lists.llvm.org
Wed Feb 14 00:06:38 PST 2024
================
@@ -0,0 +1,176 @@
+//===----------------------------------------------------------------------===//
+//
+// 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
+//
+//===----------------------------------------------------------------------===//
+// UNSUPPORTED: c++03, c++11, c++14, c++17
+
+// Make sure that std::span's iterators check for OOB accesses when the debug mode is enabled.
+
+// REQUIRES: has-unix-headers, libcpp-has-abi-bounded-iterators
+// UNSUPPORTED: libcpp-hardening-mode=none
+
+#include <span>
+
+#include "check_assertion.h"
+
+struct Foo {
+ int x;
+};
+
+template <typename Iter>
+void test_iterator(Iter begin, Iter end, bool reverse) {
+ std::ptrdiff_t distance = std::distance(begin, end);
+
+ // Dereferencing an iterator at the end.
+ {
+ TEST_LIBCPP_ASSERT_FAILURE(
+ *end,
+ reverse ? "__bounded_iter::operator--: Attempt to rewind an iterator past the start"
+ : "__bounded_iter::operator*: Attempt to dereference an iterator at the end");
+#if _LIBCPP_STD_VER >= 20
+ // In C++20 mode, std::reverse_iterator implements operator->, but not operator*, with
+ // std::prev instead of operator--. std::prev ultimately calls operator+
+ TEST_LIBCPP_ASSERT_FAILURE(
+ end->x,
+ reverse ? "__bounded_iter::operator+=: Attempt to rewind an iterator past the start"
+ : "__bounded_iter::operator->: Attempt to dereference an iterator at the end");
+#else
+ TEST_LIBCPP_ASSERT_FAILURE(
+ end->x,
+ reverse ? "__bounded_iter::operator--: Attempt to rewind an iterator past the start"
+ : "__bounded_iter::operator->: Attempt to dereference an iterator at the end");
+#endif
+ }
+
+ // Incrementing an iterator past the end.
+ {
+ [[maybe_unused]] const char* msg =
+ reverse ? "__bounded_iter::operator--: Attempt to rewind an iterator past the start"
+ : "__bounded_iter::operator++: Attempt to advance an iterator past the end";
+ auto it = end;
+ TEST_LIBCPP_ASSERT_FAILURE(it++, msg);
+ it = end;
----------------
var-const wrote:
Nit: I don't think resetting `it` is necessary -- `TEST_LIBCPP_ASSERT_FAILURE` forks the process, so I think everything that happens in the given expression doesn't affect the current process. Or to go to the other extreme, this could rather be:
```cpp
{
auto it = end;
TEST_LIBCPP_ASSERT_FAILURE(it++, msg);
}
{
auto it = end;
TEST_LIBCPP_ASSERT_FAILURE(++i, msg);
}
```
https://github.com/llvm/llvm-project/pull/78876
More information about the libcxx-commits
mailing list