From a381a3759fbd66030065fc9949fa2cf4c2c1fd58 Mon Sep 17 00:00:00 2001 From: Werner Henze <34543625+beinhaerter@users.noreply.github.com> Date: Wed, 18 Jan 2023 22:33:20 +0100 Subject: [PATCH] 1075 Wrong Expects in gsl::at? (#1076) https://github.com/microsoft/GSL/issues/1075 - Add `static_assert` because we only support C style array `at` for up to half of the address space. - Add `std::` before `size_t`. - tests: - Add `#include ` - Implement `span_tests` `interop_with_gsl_at` like `at_tests` `std_span` --- include/gsl/util | 6 ++++-- tests/at_tests.cpp | 1 + tests/span_ext_tests.cpp | 33 ++++++++++++++++++++++++++------- 3 files changed, 31 insertions(+), 9 deletions(-) diff --git a/include/gsl/util b/include/gsl/util index 75c78ad..1b0bacf 100644 --- a/include/gsl/util +++ b/include/gsl/util @@ -21,6 +21,7 @@ #include #include // for ptrdiff_t, size_t +#include // for numeric_limits #include // for initializer_list #include // for is_signed, integral_constant #include // for exchange, forward @@ -110,6 +111,7 @@ GSL_SUPPRESS(bounds.2) // NO-FORMAT: attribute // clang-format on constexpr T& at(T (&arr)[N], const index i) { + static_assert(N <= static_cast(std::numeric_limits::max()), "We only support arrays up to PTRDIFF_MAX bytes."); Expects(i >= 0 && i < narrow_cast(N)); return arr[narrow_cast(i)]; } @@ -137,11 +139,11 @@ GSL_SUPPRESS(bounds.1) // NO-FORMAT: attribute } #if defined(__cpp_lib_span) && __cpp_lib_span >= 202002L -template +template constexpr auto at(std::span sp, const index i) -> decltype(sp[sp.size()]) { Expects(i >= 0 && i < narrow_cast(sp.size())); - return sp[gsl::narrow_cast(i)]; + return sp[gsl::narrow_cast(i)]; } #endif // __cpp_lib_span >= 202002L } // namespace gsl diff --git a/tests/at_tests.cpp b/tests/at_tests.cpp index 93e6b7b..42b2241 100644 --- a/tests/at_tests.cpp +++ b/tests/at_tests.cpp @@ -20,6 +20,7 @@ #include // for array #include // for size_t +#include // for terminate #include // for initializer_list #include // for vector #if defined(__cplusplus) && __cplusplus >= 202002L diff --git a/tests/span_ext_tests.cpp b/tests/span_ext_tests.cpp index 3d35f8f..dfd2725 100644 --- a/tests/span_ext_tests.cpp +++ b/tests/span_ext_tests.cpp @@ -19,9 +19,10 @@ #include // for span and span_ext #include // for narrow_cast, at -#include // for array -#include // for cerr -#include // for vector +#include // for array +#include // for terminate +#include // for cerr +#include // for vector using namespace std; using namespace gsl; @@ -193,10 +194,28 @@ TEST(span_ext_test, make_span_from_container_constructor) TEST(span_test, interop_with_gsl_at) { - int arr[5] = {1, 2, 3, 4, 5}; - gsl::span s{arr}; - EXPECT_TRUE(at(s, 0) == 1); - EXPECT_TRUE(at(s, 1) == 2); + std::vector vec{1, 2, 3, 4, 5}; + gsl::span sp{vec}; + + std::vector cvec{1, 2, 3, 4, 5}; + gsl::span csp{cvec}; + + for (gsl::index i = 0; i < gsl::narrow_cast(vec.size()); ++i) + { + EXPECT_TRUE(&gsl::at(sp, i) == &vec[gsl::narrow_cast(i)]); + EXPECT_TRUE(&gsl::at(csp, i) == &cvec[gsl::narrow_cast(i)]); + } + + const auto terminateHandler = std::set_terminate([] { + std::cerr << "Expected Death. interop_with_gsl_at"; + std::abort(); + }); + const auto expected = GetExpectedDeathString(terminateHandler); + + EXPECT_DEATH(gsl::at(sp, -1), expected); + EXPECT_DEATH(gsl::at(sp, gsl::narrow_cast(sp.size())), expected); + EXPECT_DEATH(gsl::at(csp, -1), expected); + EXPECT_DEATH(gsl::at(csp, gsl::narrow_cast(sp.size())), expected); } TEST(span_ext_test, iterator_free_functions)