From 665296f7cf1e1aa3e0b23efb4edb723735e6ebd2 Mon Sep 17 00:00:00 2001 From: "Markus F.X.J. Oberhumer" Date: Tue, 22 Nov 2022 21:21:26 +0100 Subject: [PATCH] src/util: minor xspan improvements --- src/util/xspan.cpp | 82 +++++++++++++++++++++++++++--------- src/util/xspan_impl.h | 2 + src/util/xspan_impl_common.h | 10 ++--- 3 files changed, 69 insertions(+), 25 deletions(-) diff --git a/src/util/xspan.cpp b/src/util/xspan.cpp index 6b7ad1e3..11755884 100644 --- a/src/util/xspan.cpp +++ b/src/util/xspan.cpp @@ -32,12 +32,17 @@ SPAN_NAMESPACE_BEGIN unsigned long long span_check_stats_check_range = 0; +// HINT: set env-var "UPX_DEBUG_DOCTEST_DISABLE=1" for improved debugging experience __acc_noinline void span_fail_nullptr() { throwCantUnpack("span unexpected NULL pointer; take care!"); } +__acc_noinline void span_fail_nullbase() { + throwCantUnpack("span unexpected NULL base; take care!"); +} __acc_noinline void span_fail_not_same_base() { throwInternalError("span unexpected base pointer; take care!"); } + __acc_noinline void span_fail_range_nullptr() { throwCantUnpack("span_check_range: unexpected NULL pointer; take care!"); } @@ -474,26 +479,63 @@ TEST_CASE("Span") { assert(ss_with_base.raw_base() == base_buf); CHECK_THROWS(ss_with_base = my_null); // nullptr assignment #if SPAN_CONFIG_ENABLE_SPAN_CONVERSION - typedef PtrOrSpanOrNull Span0; - Span0 s0_no_base(nullptr); - Span0 s0_with_base(nullptr, 4, base_buf); - CHECK_THROWS(ss_with_base = s0_no_base); // nullptr assignment - CHECK_THROWS(ss_with_base = s0_with_base); // nullptr assignment - typedef PtrOrSpanOrNull SpanP; - SpanP sp_1(base_buf + 1, 3, base_buf); - SpanP sp_2(base_buf + 2, 2, base_buf); - // SpanP sp_4(base_buf + 4, 0, base_buf); - SpanP sp_x(base_buf + 1, 3, base_buf + 1); - assert(ss_with_base.raw_base() == base_buf); -#if 0 - ss_with_base = sp_1; - assert(ss_with_base.raw_ptr() == base_buf + 1); - CHECK(*ss_with_base == 1); - ss_with_base = sp_2; - assert(ss_with_base.raw_ptr() == base_buf + 2); - CHECK_THROWS(ss_with_base = sp_x); // not same base - assert(ss_with_base.raw_base() == base_buf); -#endif + { + typedef PtrOrSpanOrNull Span0; + // v0 nullptr, b0 base, b1 base + 1 + const Span0 v0_v0(nullptr); + const Span0 v0_b0(nullptr, 4, base_buf); + const Span0 v0_b1(nullptr, 3, base_buf + 1); + const Span0 b0_v0(base_buf); + const Span0 b0_b0(base_buf, 4, base_buf); + CHECK_THROWS(SPAN_0_MAKE(char, base_buf, 3, base_buf + 1)); // b0_b1 + const Span0 b1_v0(base_buf + 1); + const Span0 b1_b0(base_buf + 1, 4, base_buf); + const Span0 b1_b1(base_buf + 1, 3, base_buf + 1); + CHECK_THROWS(ss_with_base = v0_v0); // nullptr assignment + CHECK_THROWS(ss_with_base = v0_b0); // nullptr assignment + CHECK_THROWS(ss_with_base = v0_b1); // nullptr assignment + CHECK_NOTHROW(ss_with_base = b0_v0); + CHECK_NOTHROW(ss_with_base = b0_b0); + CHECK_NOTHROW(ss_with_base = b1_v0); + CHECK_NOTHROW(ss_with_base = b1_b0); + CHECK_THROWS(ss_with_base = b1_b1); // different base + CHECK_THROWS(SPAN_S_MAKE(char, v0_v0)); + CHECK_THROWS(SPAN_S_MAKE(char, v0_b0)); + CHECK_THROWS(SPAN_S_MAKE(char, v0_b1)); + CHECK_THROWS(SPAN_S_MAKE(char, b0_v0)); + CHECK_NOTHROW(SPAN_S_MAKE(char, b0_b0)); + CHECK_THROWS(SPAN_S_MAKE(char, b1_v0)); + CHECK_NOTHROW(SPAN_S_MAKE(char, b1_b0)); + CHECK_NOTHROW(SPAN_S_MAKE(char, b1_b1)); + // + CHECK((SPAN_S_MAKE(char, b0_b0).raw_base() == base_buf)); + CHECK((SPAN_S_MAKE(char, b1_b0).raw_base() == base_buf)); + CHECK((SPAN_S_MAKE(char, b1_b1).raw_base() == base_buf + 1)); + } + { + typedef PtrOrSpan SpanP; + // v0 nullptr, b0 base, b1 base + 1 + const SpanP b0_v0(base_buf); + const SpanP b0_b0(base_buf, 4, base_buf); + CHECK_THROWS(SPAN_P_MAKE(char, base_buf, 3, base_buf + 1)); // b0_b1 + const SpanP b1_v0(base_buf + 1); + const SpanP b1_b0(base_buf + 1, 4, base_buf); + const SpanP b1_b1(base_buf + 1, 3, base_buf + 1); + CHECK_NOTHROW(ss_with_base = b0_v0); + CHECK_NOTHROW(ss_with_base = b0_b0); + CHECK_NOTHROW(ss_with_base = b1_v0); + CHECK_NOTHROW(ss_with_base = b1_b0); + CHECK_THROWS(ss_with_base = b1_b1); // different base + CHECK_THROWS(SPAN_S_MAKE(char, b0_v0)); + CHECK_NOTHROW(SPAN_S_MAKE(char, b0_b0)); + CHECK_THROWS(SPAN_S_MAKE(char, b1_v0)); + CHECK_NOTHROW(SPAN_S_MAKE(char, b1_b0)); + CHECK_NOTHROW(SPAN_S_MAKE(char, b1_b1)); + // + CHECK((SPAN_S_MAKE(char, b0_b0).raw_base() == base_buf)); + CHECK((SPAN_S_MAKE(char, b1_b0).raw_base() == base_buf)); + CHECK((SPAN_S_MAKE(char, b1_b1).raw_base() == base_buf + 1)); + } #endif } diff --git a/src/util/xspan_impl.h b/src/util/xspan_impl.h index df24f2bd..50832256 100644 --- a/src/util/xspan_impl.h +++ b/src/util/xspan_impl.h @@ -41,7 +41,9 @@ SPAN_NAMESPACE_BEGIN +// HINT: set env-var "UPX_DEBUG_DOCTEST_DISABLE=1" for improved debugging experience __acc_noinline void span_fail_nullptr(); +__acc_noinline void span_fail_nullbase(); __acc_noinline void span_fail_not_same_base(); __acc_noinline void span_fail_range_nullptr(); __acc_noinline void span_fail_range_nullbase(); diff --git a/src/util/xspan_impl_common.h b/src/util/xspan_impl_common.h index 792a6252..41e851d7 100644 --- a/src/util/xspan_impl_common.h +++ b/src/util/xspan_impl_common.h @@ -78,7 +78,7 @@ static __acc_forceinline pointer makePtr(pointer p) { } static __acc_forceinline pointer makeBase(pointer b) { if __acc_cte (configRequireBase && b == nullptr) - span_fail_nullptr(); + span_fail_nullbase(); return b; } // inverse logic for ensuring valid pointers from existing objets @@ -89,8 +89,8 @@ __acc_forceinline pointer ensurePtr() const { } __acc_forceinline pointer ensureBase() const { if __acc_cte (!configRequireBase && base == nullptr) - span_fail_nullptr(); - return ptr; + span_fail_nullbase(); + return base; } public: @@ -161,13 +161,12 @@ CSelf(std::nullptr_t, size_type, std::nullptr_t) SPAN_DELETED_FUNCTION; CSelf(const void *, size_type, std::nullptr_t) SPAN_DELETED_FUNCTION; // unchecked constructor -private: +protected: enum ModeUnchecked { Unchecked }; CSelf(ModeUnchecked, pointer p, size_type bytes, pointer b) : ptr(p), base(b), size_in_bytes(bytes) { assertInvariants(); } -#if 0 // unchecked assignment Self &assign(ModeUnchecked, pointer p, size_type bytes, pointer b) { ptr = p; @@ -176,6 +175,7 @@ Self &assign(ModeUnchecked, pointer p, size_type bytes, pointer b) { assertInvariants(); return *this; } +#if 0 Self &assign(ModeUnchecked, const Self &other) { ptr = other.ptr; base = other.base;