diff options
-rw-r--r-- | BUILD.gn | 1 | ||||
-rw-r--r-- | core/fxcrt/pdfium_span_unittest.cpp | 30 | ||||
-rw-r--r-- | core/fxcrt/unowned_ptr.h | 15 | ||||
-rw-r--r-- | third_party/base/span.h | 13 |
4 files changed, 56 insertions, 3 deletions
@@ -2905,6 +2905,7 @@ test("pdfium_unittests") { "core/fxcrt/fx_system_unittest.cpp", "core/fxcrt/maybe_owned_unittest.cpp", "core/fxcrt/observable_unittest.cpp", + "core/fxcrt/pdfium_span_unittest.cpp", "core/fxcrt/retain_ptr_unittest.cpp", "core/fxcrt/shared_copy_on_write_unittest.cpp", "core/fxcrt/string_pool_template_unittest.cpp", diff --git a/core/fxcrt/pdfium_span_unittest.cpp b/core/fxcrt/pdfium_span_unittest.cpp new file mode 100644 index 0000000000..177bc4097e --- /dev/null +++ b/core/fxcrt/pdfium_span_unittest.cpp @@ -0,0 +1,30 @@ +// Copyright 2018 PDFium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "testing/gtest/include/gtest/gtest.h" +#include "third_party/base/span.h" +#include "third_party/base/stl_util.h" + +// Tests PDFium-modifications to base::span. The name of this file is +// chosen to avoid collisions with base's span_unittest.cc + +TEST(PdfiumSpan, EmptySpan) { + int stuff[] = {1, 2, 3}; + pdfium::span<int> stuff_span(stuff); + pdfium::span<int> empty_first_span = stuff_span.first(0); + pdfium::span<int> empty_last_span = stuff_span.last(0); + pdfium::span<int> empty_sub_span1 = stuff_span.subspan(0, 0); + pdfium::span<int> empty_sub_span2 = stuff_span.subspan(3, 0); + EXPECT_TRUE(empty_first_span.empty()); + EXPECT_TRUE(empty_last_span.empty()); + EXPECT_TRUE(empty_sub_span1.empty()); + EXPECT_TRUE(empty_sub_span2.empty()); +} + +TEST(PdfiumSpan, EmptySpanDeath) { + int stuff[] = {1, 2, 3}; + pdfium::span<int> stuff_span(stuff); + pdfium::span<int> empty_span = stuff_span.last(0); + EXPECT_DEATH(empty_span[0] += 1, ".*"); +} diff --git a/core/fxcrt/unowned_ptr.h b/core/fxcrt/unowned_ptr.h index 0e3bf9e09b..0a44f9db52 100644 --- a/core/fxcrt/unowned_ptr.h +++ b/core/fxcrt/unowned_ptr.h @@ -35,6 +35,13 @@ // other heap object. Use pdfium::span<> for the cases where indexing // into an unowned array is desired, which performs the same checks. +namespace pdfium { + +template <typename T> +class span; + +} // namespace pdfium + namespace fxcrt { template <class T> @@ -95,6 +102,8 @@ class UnownedPtr { T* operator->() const { return m_pObj; } private: + friend class pdfium::span<T>; + inline void ProbeForLowSeverityLifetimeIssue() { #if defined(MEMORY_TOOL_REPLACES_ALLOCATOR) if (m_pObj) @@ -102,6 +111,12 @@ class UnownedPtr { #endif } + inline void ReleaseBadPointer() { +#if defined(MEMORY_TOOL_REPLACES_ALLOCATOR) + m_pObj = nullptr; +#endif + } + T* m_pObj = nullptr; }; diff --git a/third_party/base/span.h b/third_party/base/span.h index 034c6a35e7..0fb627ba8c 100644 --- a/third_party/base/span.h +++ b/third_party/base/span.h @@ -195,6 +195,7 @@ class span { // [span.cons], span constructors, copy, assignment, and destructor constexpr span() noexcept : data_(nullptr), size_(0) {} constexpr span(T* data, size_t size) noexcept : data_(data), size_(size) {} + // TODO(dcheng): Implement construction from a |begin| and |end| pointer. template <size_t N> constexpr span(T (&array)[N]) noexcept : span(array, N) {} @@ -215,12 +216,18 @@ class span { template <typename U, typename = internal::EnableIfLegalSpanConversion<U, T>> constexpr span(const span<U>& other) : span(other.data(), other.size()) {} span& operator=(const span& other) noexcept = default; - ~span() noexcept = default; + ~span() noexcept { + if (!size_) { + // Empty spans might point to byte N+1 of a N-byte object, legal for + // C pointers but not UnownedPtrs. + data_.ReleaseBadPointer(); + } + } // [span.sub], span subviews const span first(size_t count) const { CHECK(count <= size_); - return span(data_, count); + return span(data_.Get(), count); } const span last(size_t count) const { @@ -240,7 +247,7 @@ class span { constexpr bool empty() const noexcept { return size_ == 0; } // [span.elem], span element access - const T& operator[](size_t index) const noexcept { + T& operator[](size_t index) const noexcept { CHECK(index < size_); return data_.Get()[index]; } |