From cba44c45fc5fb624a96af60b34b4d8838f414b19 Mon Sep 17 00:00:00 2001 From: "Markus F.X.J. Oberhumer" Date: Sat, 11 May 2024 17:37:15 +0200 Subject: [PATCH] src: introduce ptr_get_address() --- src/check/dt_check.cpp | 8 ++++++++ src/check/dt_cxxlib.cpp | 1 + src/compress/compress_lzma.cpp | 6 ++---- src/conf.h | 2 ++ src/util/membuffer.cpp | 8 ++++---- src/util/util.cpp | 16 ++++++++-------- src/util/util.h | 16 ++++++++++------ src/util/xspan.cpp | 5 +++-- 8 files changed, 38 insertions(+), 24 deletions(-) diff --git a/src/check/dt_check.cpp b/src/check/dt_check.cpp index 8965751c..a1ec68ac 100644 --- a/src/check/dt_check.cpp +++ b/src/check/dt_check.cpp @@ -498,8 +498,16 @@ void upx_compiler_sanity_check(void) noexcept { CheckIntegral::check(); CheckIntegral::check(); CheckIntegral::check(); + CheckIntegral::check(); CheckIntegral::check(); + COMPILE_TIME_ASSERT(ptrdiff_t(0) - 1 < 0); + COMPILE_TIME_ASSERT(intptr_t(0) - 1 < 0); + COMPILE_TIME_ASSERT(size_t(0) - 1 > 0); + COMPILE_TIME_ASSERT(uintptr_t(0) - 1 > 0); + COMPILE_TIME_ASSERT(upx_ptraddr_t(0) - 1 > 0); + COMPILE_TIME_ASSERT(upx_uintptr_t(0) - 1 > 0); + COMPILE_TIME_ASSERT(sizeof(upx_charptr_unit_type) == 1) COMPILE_TIME_ASSERT_ALIGNED1(upx_charptr_unit_type) COMPILE_TIME_ASSERT(sizeof(*((charptr) nullptr)) == 1) diff --git a/src/check/dt_cxxlib.cpp b/src/check/dt_cxxlib.cpp index 872acf0c..0a700ee8 100644 --- a/src/check/dt_cxxlib.cpp +++ b/src/check/dt_cxxlib.cpp @@ -54,6 +54,7 @@ ACC_COMPILE_TIME_ASSERT_HEADER((!upx::is_same_any_v) ) ACC_COMPILE_TIME_ASSERT_HEADER((upx::is_same_any_v) ) ACC_COMPILE_TIME_ASSERT_HEADER( (upx::is_same_any_v) ) +// TODO later: CHERI ACC_COMPILE_TIME_ASSERT_HEADER( (upx::is_same_any_v) ) diff --git a/src/compress/compress_lzma.cpp b/src/compress/compress_lzma.cpp index 06acd937..bd8686e1 100644 --- a/src/compress/compress_lzma.cpp +++ b/src/compress/compress_lzma.cpp @@ -30,11 +30,9 @@ #if (ACC_CC_CLANG) #pragma clang diagnostic ignored "-Wshadow" -#endif -#if (ACC_CC_GNUC >= 0x040200) +#elif (ACC_CC_GNUC >= 0x040200) #pragma GCC diagnostic ignored "-Wshadow" -#endif -#if (ACC_CC_MSC) +#elif (ACC_CC_MSC) #pragma warning(disable : 4456) // -Wno-shadow #endif diff --git a/src/conf.h b/src/conf.h index fbc24484..8c3606a5 100644 --- a/src/conf.h +++ b/src/conf.h @@ -144,6 +144,8 @@ typedef acc_uint32_t upx_uint32_t; typedef acc_int64_t upx_int64_t; typedef acc_uint64_t upx_uint64_t; typedef acc_uintptr_t upx_uintptr_t; +// see CHERI ptraddr_t / vaddr_t +typedef upx_uintptr_t upx_ptraddr_t; // UPX convention: use "byte" when dealing with data; use "char/uchar" when dealing // with strings; use "upx_uint8_t" when dealing with small integers diff --git a/src/util/membuffer.cpp b/src/util/membuffer.cpp index c0cdbb2f..ecfcfc47 100644 --- a/src/util/membuffer.cpp +++ b/src/util/membuffer.cpp @@ -73,7 +73,7 @@ static forceinline constexpr bool use_simple_mcheck() noexcept { return true; } // **************************************************************************/ -MemBuffer::MemBuffer(upx_uint64_t bytes) : MemBufferBase() { +MemBuffer::MemBuffer(upx_uint64_t bytes) may_throw : MemBufferBase() { static_assert(element_size == 1); alloc(bytes); debug_set(debug.last_return_address_alloc, upx_return_address()); @@ -148,11 +148,11 @@ void MemBuffer::fill(unsigned off, unsigned len, int value) { **************************************************************************/ // for use_simple_mcheck() -#define PTR_BITS32(p) ((unsigned) ((upx_uintptr_t) (p) &0xffffffff)) +#define PTR_BITS32(p) ((unsigned) (ptr_get_address(p) & 0xffffffff)) #define MAGIC1(p) ((PTR_BITS32(p) ^ 0xfefdbeeb) | 1) #define MAGIC2(p) ((PTR_BITS32(p) ^ 0xfefdbeeb ^ 0x88224411) | 1) -void MemBuffer::checkState() const { +void MemBuffer::checkState() const may_throw { if (!ptr) throwInternalError("block not allocated"); assert(size_in_bytes > 0); @@ -167,7 +167,7 @@ void MemBuffer::checkState() const { } } -void MemBuffer::alloc(upx_uint64_t bytes) { +void MemBuffer::alloc(upx_uint64_t bytes) may_throw { // INFO: we don't automatically free a used buffer assert(ptr == nullptr); assert(size_in_bytes == 0); diff --git a/src/util/util.cpp b/src/util/util.cpp index b5fb46ae..70f44dc3 100644 --- a/src/util/util.cpp +++ b/src/util/util.cpp @@ -144,11 +144,11 @@ TEST_CASE("ptr_diff") { } // check that 2 buffers do not overlap; will throw on error -void uintptr_check_no_overlap(upx_uintptr_t a, size_t a_size, upx_uintptr_t b, size_t b_size) { +void ptraddr_check_no_overlap(upx_ptraddr_t a, size_t a_size, upx_ptraddr_t b, size_t b_size) { if very_unlikely (a == 0 || b == 0) throwCantPack("ptr_check_no_overlap-nullptr"); - upx_uintptr_t a_end = a + mem_size(1, a_size); - upx_uintptr_t b_end = b + mem_size(1, b_size); + upx_ptraddr_t a_end = a + mem_size(1, a_size); + upx_ptraddr_t b_end = b + mem_size(1, b_size); if very_unlikely (a_end < a || b_end < b) // wrap-around throwCantPack("ptr_check_no_overlap-overflow"); // simple, but a little bit mind bending: @@ -159,13 +159,13 @@ void uintptr_check_no_overlap(upx_uintptr_t a, size_t a_size, upx_uintptr_t b, s } // check that 3 buffers do not overlap; will throw on error -void uintptr_check_no_overlap(upx_uintptr_t a, size_t a_size, upx_uintptr_t b, size_t b_size, - upx_uintptr_t c, size_t c_size) { +void ptraddr_check_no_overlap(upx_ptraddr_t a, size_t a_size, upx_ptraddr_t b, size_t b_size, + upx_ptraddr_t c, size_t c_size) { if very_unlikely (a == 0 || b == 0 || c == 0) throwCantPack("ptr_check_no_overlap-nullptr"); - upx_uintptr_t a_end = a + mem_size(1, a_size); - upx_uintptr_t b_end = b + mem_size(1, b_size); - upx_uintptr_t c_end = c + mem_size(1, c_size); + upx_ptraddr_t a_end = a + mem_size(1, a_size); + upx_ptraddr_t b_end = b + mem_size(1, b_size); + upx_ptraddr_t c_end = c + mem_size(1, c_size); if very_unlikely (a_end < a || b_end < b || c_end < c) // wrap-around throwCantPack("ptr_check_no_overlap-overflow"); if very_unlikely (a < b_end && b < a_end) diff --git a/src/util/util.h b/src/util/util.h index 5c34a1ec..2319472e 100644 --- a/src/util/util.h +++ b/src/util/util.h @@ -93,6 +93,10 @@ T *NewArray(upx_uint64_t n) may_throw { // ptr util **************************************************************************/ +// also see CHERI cheri_address_get() +forceinline upx_ptraddr_t ptr_get_address(const void *p) { return (upx_uintptr_t) p; } +forceinline upx_ptraddr_t ptr_get_address(upx_uintptr_t p) { return p; } + // ptrdiff_t with nullptr checks and asserted size; will throw on failure // NOTE: returns size_in_bytes, not number of elements! int ptr_diff_bytes(const void *a, const void *b) may_throw; @@ -112,19 +116,19 @@ ptr_udiff(const T *a, const U *b) may_throw { } // check that buffers do not overlap; will throw on error -noinline void uintptr_check_no_overlap(upx_uintptr_t a, size_t a_size, upx_uintptr_t b, +noinline void ptraddr_check_no_overlap(upx_ptraddr_t a, size_t a_size, upx_ptraddr_t b, size_t b_size) may_throw; -noinline void uintptr_check_no_overlap(upx_uintptr_t a, size_t a_size, upx_uintptr_t b, - size_t b_size, upx_uintptr_t c, size_t c_size) may_throw; +noinline void ptraddr_check_no_overlap(upx_ptraddr_t a, size_t a_size, upx_ptraddr_t b, + size_t b_size, upx_ptraddr_t c, size_t c_size) may_throw; forceinline void ptr_check_no_overlap(const void *a, size_t a_size, const void *b, size_t b_size) may_throw { - uintptr_check_no_overlap((upx_uintptr_t) a, a_size, (upx_uintptr_t) b, b_size); + ptraddr_check_no_overlap(ptr_get_address(a), a_size, ptr_get_address(b), b_size); } forceinline void ptr_check_no_overlap(const void *a, size_t a_size, const void *b, size_t b_size, const void *c, size_t c_size) may_throw { - uintptr_check_no_overlap((upx_uintptr_t) a, a_size, (upx_uintptr_t) b, b_size, - (upx_uintptr_t) c, c_size); + ptraddr_check_no_overlap(ptr_get_address(a), a_size, ptr_get_address(b), b_size, + ptr_get_address(c), c_size); } // invalidate and poison a pointer: point to a non-null invalid address diff --git a/src/util/xspan.cpp b/src/util/xspan.cpp index ed4b021a..3807f984 100644 --- a/src/util/xspan.cpp +++ b/src/util/xspan.cpp @@ -76,9 +76,10 @@ void xspan_check_range(const void *ptr, const void *base, ptrdiff_t size_in_byte xspan_fail_range_nullptr(); if very_unlikely (base == nullptr) xspan_fail_range_nullbase(); -#if defined(__SANITIZE_ADDRESS__) +#if defined(__SANITIZE_ADDRESS__) || 1 // info: pointers are out of range deliberately during internal doctest checks; see dt_xspan.cpp - const acc_intptr_t off = (acc_uintptr_t) ptr - (acc_uintptr_t) base; + ACC_COMPILE_TIME_ASSERT(sizeof(intptr_t) == sizeof(upx_ptraddr_t)) + const intptr_t off = ptr_get_address(ptr) - ptr_get_address(base); #else const ptrdiff_t off = (const charptr) ptr - (const charptr) base; #endif