From 98c00d0fcb2eddb3314c478848ab27ba34d9c933 Mon Sep 17 00:00:00 2001 From: "Markus F.X.J. Oberhumer" Date: Sat, 8 Nov 2025 09:05:25 +0100 Subject: [PATCH] CI updates --- .github/workflows/ci.yml | 3 +++ CMakeLists.txt | 2 +- misc/valgrind/musl.supp | 6 ++++++ src/check/dt_xspan.cpp | 6 ------ src/stub/Makefile | 14 +++++++------- src/util/util.cpp | 36 ++++++++++++++++++------------------ src/util/util.h | 4 ++-- src/util/xspan_impl.h | 12 ++++++------ src/util/xspan_impl_common.h | 15 ++++++++------- src/util/xspan_impl_ptr.h | 6 ++++++ 10 files changed, 57 insertions(+), 47 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3297e8a8..fad571c1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -609,6 +609,8 @@ jobs: - { zig_target: powerpc64-linux-musl, qemu: qemu-ppc64, zig_pic: -fPIE } - { zig_target: powerpc64le-linux-musl, qemu: qemu-ppc64le } - { zig_target: powerpc64le-linux-musl, qemu: qemu-ppc64le, zig_pic: -fPIE } + - { zig_target: riscv64-linux-musl, qemu: qemu-riscv64, tt: UPX-UNSUPPORTED } + - { zig_target: riscv64-linux-musl, qemu: qemu-riscv64, tt: UPX-UNSUPPORTED, zig_pic: -fPIE } - { zig_target: x86_64-linux-gnu.2.3.4, qemu: qemu-x86_64 } # can use QEMU because of gcompat - { zig_target: x86_64-linux-gnu.2.17, qemu: qemu-x86_64 } # can use QEMU because of gcompat - { zig_target: x86_64-linux-musl, qemu: qemu-x86_64 } @@ -652,6 +654,7 @@ jobs: # TODO FIXME: problem with self-packed upx and musl+gcompat: "Not a valid dynamic program" echo "UPX_CONFIG_DISABLE_RUN_PACKED_TEST=ON" >> $GITHUB_ENV fi + test -z "${{ matrix.tt }}" || echo "UPX_CONFIG_DISABLE_SELF_PACK_TEST=ON" >> $GITHUB_ENV # install zig; note that ~/.local/bin is included in the default $PATH on Ubuntu mkdir -p -v ~/.local/bin cd ~/.local/bin diff --git a/CMakeLists.txt b/CMakeLists.txt index 888124a8..3869d1ca 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -289,7 +289,7 @@ if(Threads_FOUND) if(NOT result) # failed; under MinGW be sure to use the posix-threads and NOT the win32-threads version if(UPX_CONFIG_REQUIRE_THREADS OR (UPX_CONFIG_EXPECT_THREADS AND NOT UPX_CONFIG_DISABLE_THREADS)) - message(WARNING "Threads FAILED ${f}: ${output}") # output from try_compile + message(WARNING "Threads FAILED ${f}: ${output}") # output from try_compile() endif() set(Threads_FOUND OFF) break() diff --git a/misc/valgrind/musl.supp b/misc/valgrind/musl.supp index d85db386..3ee8788f 100644 --- a/misc/valgrind/musl.supp +++ b/misc/valgrind/musl.supp @@ -9,6 +9,12 @@ Memcheck:Cond fun:enframe } +{ + musl-malloc-get_nominal_size + Memcheck:Cond + fun:get_nominal_size + fun:__libc_free +} # these are only needed for older musl versions diff --git a/src/check/dt_xspan.cpp b/src/check/dt_xspan.cpp index 9ffbdf25..c70c38b7 100644 --- a/src/check/dt_xspan.cpp +++ b/src/check/dt_xspan.cpp @@ -101,9 +101,6 @@ TEST_CASE("basic xspan usage") { CHECK(b0.raw_size_in_bytes() == 0u); CHECK(bp.raw_size_in_bytes() == 0u); #endif - CHECK(raw_bytes(b0, 999999) == buf); - CHECK(raw_bytes(bp, 999999) == buf); - CHECK(raw_bytes(c0, 4) == buf); CHECK(raw_index_bytes(c0, 1, 3) == buf + 1); CHECK(raw_bytes(cp, 4) == buf); @@ -180,9 +177,6 @@ TEST_CASE("basic xspan usage") { CHECK(b0.raw_size_in_bytes() == 0u); CHECK(bp.raw_size_in_bytes() == 0u); #endif - CHECK(raw_bytes(b0, 999999) == buf); - CHECK(raw_bytes(bp, 999999) == buf); - CHECK(raw_bytes(c0, 4) == buf); CHECK(raw_index_bytes(c0, 1, 3) == buf + 1); CHECK(raw_bytes(cp, 4) == buf); diff --git a/src/stub/Makefile b/src/stub/Makefile index 69847a11..32f6ad7f 100644 --- a/src/stub/Makefile +++ b/src/stub/Makefile @@ -167,7 +167,7 @@ all: $$(all.targets) @echo "timestamp" > $@ .DELETE_ON_ERROR: .upx-stubtools-stamp %/.tmp-stamp: - @mkdir -p $(dir $@) + @mkdir -p "$(dir $@)" @echo "timestamp" > $@ .PRECIOUS: %/.tmp-stamp .all-stamp: $$(STUBS) @@ -241,15 +241,15 @@ define tc endef # default tools -tc.default.bin2h = $(PYTHON3) $(top_srcdir)/src/stub/scripts/bin2h.py --ident=auto-stub +tc.default.bin2h = $(PYTHON3) "$(top_srcdir)/src/stub/scripts/bin2h.py" --ident=auto-stub ##tc.default.bin2h-c = $(call tc,bin2h) --compress=14,15,0 tc.default.bin2h-c = $(call tc,bin2h) --compress=0 -tc.default.brandelf = $(PYTHON3) $(top_srcdir)/src/stub/scripts/brandelf.py $(if $(tc_bfdname),--bfdname=$(tc_bfdname)) -tc.default.gpp_inc = $(PYTHON3) $(top_srcdir)/src/stub/scripts/gpp_inc.py -tc.default.gpp_mkdep = $(PYTHON3) $(top_srcdir)/src/stub/scripts/gpp_inc.py -o /dev/null +tc.default.brandelf = $(PYTHON3) "$(top_srcdir)/src/stub/scripts/brandelf.py" $(if $(tc_bfdname),--bfdname=$(tc_bfdname)) +tc.default.gpp_inc = $(PYTHON3) "$(top_srcdir)/src/stub/scripts/gpp_inc.py" +tc.default.gpp_mkdep = $(PYTHON3) "$(top_srcdir)/src/stub/scripts/gpp_inc.py" -o /dev/null tc.default.pp-as = i386-linux-gcc-3.4.6 -E -nostdinc -x assembler-with-cpp -Wall tc.default.sstrip = sstrip-20060518 -tc.default.xstrip = $(PYTHON3) $(top_srcdir)/src/stub/scripts/xstrip.py +tc.default.xstrip = $(PYTHON3) "$(top_srcdir)/src/stub/scripts/xstrip.py" # default multiarch-binutils tc.default.m-ar = multiarch-ar-2.17 @@ -319,7 +319,7 @@ endef define tc.default.f-embed_objinfo_without_xstrip_keep_dot_text chmod a-x $1 - $(call tc,objcopy) -R .data -R .bss $1 + $(call tc,objcopy) -R .data -R .bss $1 $(call tc,objcopy) -R .comment -R .note -R .note.GNU-stack -R .reginfo $1 $(call tc,objcopy) --strip-unneeded --keep-symbol=_start --keep-symbol=upx_so_main $1 # diff --git a/src/util/util.cpp b/src/util/util.cpp index a2215082..9da675cd 100644 --- a/src/util/util.cpp +++ b/src/util/util.cpp @@ -260,11 +260,11 @@ const char *upx_getenv(const char *envvar) noexcept { } // random value from libc; quality is not important for UPX -int upx_rand(void) noexcept { +int upx_rand() noexcept { return ::rand(); // NOLINT(clang-analyzer-security.insecureAPI.rand) } -void upx_rand_init(void) noexcept { +void upx_rand_init() noexcept { unsigned seed = 0; seed ^= UPX_VERSION_HEX; #if (!HAVE_GETTIMEOFDAY || (ACC_OS_DOS32 && defined(__DJGPP__))) && !defined(__wasi__) @@ -420,6 +420,22 @@ void upx_std_stable_sort(void *array, size_t n, upx_compare_func_t compare) { #endif } +#if UPX_CONFIG_USE_STABLE_SORT +// instantiate function templates for all element sizes we need; efficient +// run-time, but code size bloat (about 4KiB code size for each function +// with my current libstdc++); not really needed as libc qsort() is +// good enough for our use cases +template void upx_std_stable_sort<1>(void *, size_t, upx_compare_func_t); +template void upx_std_stable_sort<2>(void *, size_t, upx_compare_func_t); +template void upx_std_stable_sort<4>(void *, size_t, upx_compare_func_t); +template void upx_std_stable_sort<5>(void *, size_t, upx_compare_func_t); +template void upx_std_stable_sort<8>(void *, size_t, upx_compare_func_t); +template void upx_std_stable_sort<16>(void *, size_t, upx_compare_func_t); +template void upx_std_stable_sort<32>(void *, size_t, upx_compare_func_t); +template void upx_std_stable_sort<56>(void *, size_t, upx_compare_func_t); +template void upx_std_stable_sort<72>(void *, size_t, upx_compare_func_t); +#endif // UPX_CONFIG_USE_STABLE_SORT + TEST_CASE("upx_memswap") { auto check4 = [](int off1, int off2, int len, int a, int b, int c, int d) { byte p[4] = {0, 1, 2, 3}; @@ -473,22 +489,6 @@ TEST_CASE("upx_memswap") { } } -#if UPX_CONFIG_USE_STABLE_SORT -// instantiate function templates for all element sizes we need; efficient -// run-time, but code size bloat (about 4KiB code size for each function -// with my current libstdc++); not really needed as libc qsort() is -// good enough for our use cases -template void upx_std_stable_sort<1>(void *, size_t, upx_compare_func_t); -template void upx_std_stable_sort<2>(void *, size_t, upx_compare_func_t); -template void upx_std_stable_sort<4>(void *, size_t, upx_compare_func_t); -template void upx_std_stable_sort<5>(void *, size_t, upx_compare_func_t); -template void upx_std_stable_sort<8>(void *, size_t, upx_compare_func_t); -template void upx_std_stable_sort<16>(void *, size_t, upx_compare_func_t); -template void upx_std_stable_sort<32>(void *, size_t, upx_compare_func_t); -template void upx_std_stable_sort<56>(void *, size_t, upx_compare_func_t); -template void upx_std_stable_sort<72>(void *, size_t, upx_compare_func_t); -#endif // UPX_CONFIG_USE_STABLE_SORT - #if !defined(DOCTEST_CONFIG_DISABLE) && DEBUG #if __cplusplus >= 202002L // use C++20 std::next_permutation() to test all permutations namespace { diff --git a/src/util/util.h b/src/util/util.h index 3e048432..a9d7422a 100644 --- a/src/util/util.h +++ b/src/util/util.h @@ -181,8 +181,8 @@ noinline const char *upx_getenv(const char *envvar) noexcept; noinline void upx_memswap(void *a, void *b, size_t bytes) noexcept; -noinline void upx_rand_init(void) noexcept; -noinline int upx_rand(void) noexcept; +noinline void upx_rand_init() noexcept; +noinline int upx_rand() noexcept; typedef int(__acc_cdecl_qsort *upx_compare_func_t)(const void *, const void *); typedef void (*upx_sort_func_t)(void *array, size_t n, size_t element_size, upx_compare_func_t); diff --git a/src/util/xspan_impl.h b/src/util/xspan_impl.h index bd92aa1f..da76d37a 100644 --- a/src/util/xspan_impl.h +++ b/src/util/xspan_impl.h @@ -43,12 +43,12 @@ XSPAN_NAMESPACE_BEGIN // HINT: set env-var "UPX_DEBUG_DOCTEST_DISABLE=1" for improved debugging experience -noreturn void xspan_fail_nullptr(void) may_throw; -noreturn void xspan_fail_nullbase(void) may_throw; -noreturn void xspan_fail_not_same_base(void) may_throw; -noreturn void xspan_fail_range_nullptr(void) may_throw; -noreturn void xspan_fail_range_nullbase(void) may_throw; -noreturn void xspan_fail_range_range(void) may_throw; +noreturn void xspan_fail_nullptr() may_throw; +noreturn void xspan_fail_nullbase() may_throw; +noreturn void xspan_fail_not_same_base() may_throw; +noreturn void xspan_fail_range_nullptr() may_throw; +noreturn void xspan_fail_range_nullbase() may_throw; +noreturn void xspan_fail_range_range() may_throw; void xspan_check_range(const void *ptr, const void *base, ptrdiff_t size_in_bytes) may_throw; // help constructor to distinguish between number of elements and bytes diff --git a/src/util/xspan_impl_common.h b/src/util/xspan_impl_common.h index 78d3a2d6..3b517522 100644 --- a/src/util/xspan_impl_common.h +++ b/src/util/xspan_impl_common.h @@ -34,11 +34,6 @@ class CSelf { #endif public: - typedef T element_type; - typedef typename std::add_lvalue_reference::type reference; - typedef typename std::add_pointer::type pointer; - typedef size_t size_type; - // befriend all template friend struct PtrOrSpan; @@ -47,6 +42,11 @@ public: template friend struct Span; + typedef T element_type; + typedef typename std::add_lvalue_reference::type reference; + typedef typename std::add_pointer::type pointer; + typedef size_t size_type; + #if XSPAN_CONFIG_ENABLE_IMPLICIT_CONVERSION public: operator pointer() const noexcept { return ptr; } @@ -449,9 +449,10 @@ public: // raw access if (bytes > 0) { if __acc_cte (!configRequirePtr && ptr == nullptr) xspan_fail_nullptr(); - if __acc_cte (configRequireBase || base != nullptr) { + if __acc_cte (configRequireBase || base != nullptr) xspan_check_range(ptr, base, size_in_bytes - bytes); - } + if very_unlikely (__acc_cte(VALGRIND_CHECK_MEM_IS_ADDRESSABLE(ptr, bytes) != 0)) + throwCantPack("raw_bytes valgrind-check-mem"); } return ptr; } diff --git a/src/util/xspan_impl_ptr.h b/src/util/xspan_impl_ptr.h index 8583e11d..4e29c325 100644 --- a/src/util/xspan_impl_ptr.h +++ b/src/util/xspan_impl_ptr.h @@ -201,6 +201,10 @@ private: static forceinline pointer check_deref(pointer p, ptrdiff_t n) noexcept { return p + n; } static forceinline pointer check_add(pointer p, ptrdiff_t n) noexcept { return p + n; } + // disable taking the address => force passing by reference + // [I'm not too sure about this design decision, but we can always allow it if needed] + Self *operator&() const XSPAN_DELETED_FUNCTION; + public: // raw access pointer raw_ptr() const noexcept { return ptr; } @@ -209,6 +213,8 @@ public: // raw access if (bytes > 0) { if very_unlikely (ptr == nullptr) xspan_fail_nullptr(); + if very_unlikely (__acc_cte(VALGRIND_CHECK_MEM_IS_ADDRESSABLE(ptr, bytes) != 0)) + throwCantPack("raw_bytes valgrind-check-mem"); } return ptr; }