From 5cf1610cfe10ca083dd9eaf14cf9a12f2cb63692 Mon Sep 17 00:00:00 2001 From: "Jordan Maples [MSFT]" <49793787+JordanMaples@users.noreply.github.com> Date: Wed, 5 Feb 2020 12:58:49 -0800 Subject: [PATCH] prevent overflow in size_bytes. fix compilation issue for clang 3.6 and 3.7 --- include/gsl/span | 20 ++++++++++++-------- tests/span_tests.cpp | 29 ++++++++++++++++++++++++++++- 2 files changed, 40 insertions(+), 9 deletions(-) diff --git a/include/gsl/span b/include/gsl/span index 548587b..fbb3758 100644 --- a/include/gsl/span +++ b/include/gsl/span @@ -163,7 +163,7 @@ namespace details constexpr span_iterator operator++(int) noexcept { - auto ret{*this}; + span_iterator ret = {*this}; ++*this; return ret; } @@ -178,7 +178,7 @@ namespace details constexpr span_iterator operator--(int) noexcept { - auto ret{*this}; + span_iterator ret = {*this}; --*this; return ret; } @@ -194,7 +194,7 @@ namespace details constexpr span_iterator operator+(const difference_type n) const noexcept { - auto ret{*this}; + span_iterator ret = {*this}; return ret += n; } @@ -215,7 +215,7 @@ namespace details constexpr span_iterator operator-(const difference_type n) const noexcept { - auto ret{*this}; + span_iterator ret = {*this}; return ret -= n; } @@ -238,7 +238,8 @@ namespace details std::enable_if_t, value_type>::value, int> = 0> constexpr bool operator==(const span_iterator& rhs) const noexcept { - return begin_ == rhs.begin_ && end_ == rhs.end_ && current_ == rhs.current_; + Expects(begin_ == rhs.begin_ && end_ == rhs.end_); + return current_ == rhs.current_; } template < @@ -452,7 +453,7 @@ public: std::is_convertible::value && std::is_convertible().data())>::value>> - constexpr span(Container& cont) noexcept : span(cont.data(), narrow(cont.size())) + constexpr span(Container& cont) noexcept : span(cont.data(), cont.size()) {} template ().data())>::value>> constexpr span(const Container& cont) noexcept - : span(cont.data(), narrow(cont.size())) + : span(cont.data(), cont.size()) {} constexpr span(const span& other) noexcept = default; @@ -526,10 +527,13 @@ public: // [span.obs], span observers constexpr size_type size() const noexcept { return storage_.size(); } + constexpr size_type size_bytes() const noexcept { - return size() * narrow_cast(sizeof(element_type)); + Expects(size() < dynamic_extent / sizeof(element_type)); + return size() * sizeof(element_type); } + constexpr bool empty() const noexcept { return size() == 0; } // [span.elem], span element access diff --git a/tests/span_tests.cpp b/tests/span_tests.cpp index ce10325..c078f3a 100644 --- a/tests/span_tests.cpp +++ b/tests/span_tests.cpp @@ -1090,6 +1090,23 @@ TEST(span_test, from_array_constructor) } } + TEST(span_test, incomparable_iterators) + { + std::set_terminate([] { + std::cerr << "Expected Death. incomparable_iterators"; + std::abort(); + }); + + int a[] = {1, 2, 3, 4}; + int b[] = {1, 2, 3, 4}; + { + span s = a; + span s2 = b; + EXPECT_DEATH(s.begin() == s2.begin(), deathstring); + EXPECT_DEATH(s.begin() <= s2.begin(), deathstring); + } + } + TEST(span_test, begin_end) { std::set_terminate([] { @@ -1425,8 +1442,12 @@ TEST(span_test, from_array_constructor) TEST(span_test, as_bytes) { - int a[] = {1, 2, 3, 4}; + std::set_terminate([] { + std::cerr << "Expected Death. as_bytes"; + std::abort(); + }); + int a[] = {1, 2, 3, 4}; { const span s = a; EXPECT_TRUE(s.size() == 4); @@ -1451,6 +1472,12 @@ TEST(span_test, from_array_constructor) EXPECT_TRUE(static_cast(bs.data()) == static_cast(s.data())); EXPECT_TRUE(bs.size() == s.size_bytes()); } + + int b[5] = {1, 2, 3, 4, 5}; + { + span sp(begin(b), static_cast(-2)); + EXPECT_DEATH((void) sp.size_bytes(), deathstring); + } } TEST(span_test, as_writeable_bytes)