diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index c8a2a81f..b19228cd 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -349,8 +349,11 @@ jobs: - { name: arm64ec-win64-vs2022, os: windows-2022, vsversion: 2022, vsarch: amd64_arm64, cl_machine_flags: -arm64EC, link_machine_flags: '/machine:arm64ec' } # { name: arm64x-win64-vs2022, os: windows-2022, vsversion: 2022, vsarch: amd64_arm64, cl_machine_flags: -arm64EC, link_machine_flags: '/machine:arm64x' } - { name: i386-win32-vs2019, os: windows-2019, vsversion: 2019, vsarch: amd64_x86 } - # TODO later: as of 2024-06-07 i386-win32-vs2022 stopped working: "upx_ucl_init() failed"; - # examine why; flaky?? + # TODO: as of 2024-06-07 i386-win32-vs2022 stopped working: "upx_ucl_init() failed" + # working: MSVC 19.39.33523 for x86 + # broken: MSVC 19.40.33811 for x86 + # caused by runner-images update 20240603.1: + # https://github.com/actions/runner-images/blob/win22/20240603.1/images/windows/Windows2022-Readme.md?plain=1#L470-L480 # { name: i386-win32-vs2022, os: windows-2022, vsversion: 2022, vsarch: amd64_x86 } steps: - run: git config --global core.autocrlf false diff --git a/CMakeLists.txt b/CMakeLists.txt index b53c47a4..730bde73 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -495,6 +495,7 @@ upx_cmake_include_hook(8_summary) upx_print_var(CMAKE_VERSION UPX_CONFIG_CMAKE_MINIMUM_REQUIRED_VERSION CMAKE_GENERATOR) if(NOT UPX_CONFIG_CMAKE_DISABLE_PRINT_INFO) + # print detailed info include("${CMAKE_CURRENT_SOURCE_DIR}/misc/cmake/print_info.cmake") endif() upx_print_var(CMAKE_INSTALL_PREFIX CMAKE_CONFIGURATION_TYPES CMAKE_TRY_COMPILE_CONFIGURATION CMAKE_BUILD_TYPE) diff --git a/Makefile b/Makefile index d04d0282..54b64298 100644 --- a/Makefile +++ b/Makefile @@ -9,7 +9,7 @@ # mkdir -p build/release # cd build/release # cmake ../.. # run config -# make -j # and run build +# make -j4 # and run build CMAKE = cmake UPX_CMAKE_BUILD_FLAGS += --parallel diff --git a/misc/cmake/print_info.cmake b/misc/cmake/print_info.cmake index 58e63f0a..cf3c709a 100644 --- a/misc/cmake/print_info.cmake +++ b/misc/cmake/print_info.cmake @@ -21,7 +21,7 @@ upx_print_var(CMAKE_HOST_SYSTEM_NAME CMAKE_HOST_SYSTEM_VERSION CMAKE_HOST_SYSTEM upx_print_var(CMAKE_SYSTEM_NAME CMAKE_SYSTEM_VERSION CMAKE_SYSTEM_PROCESSOR) upx_print_var(CMAKE_ANDROID_NDK CMAKE_ANDROID_NDK_VERSION CMAKE_ANDROID_STANDALONE_TOOLCHAIN) upx_print_var(CMAKE_APPLE_SILICON_PROCESSOR CMAKE_OSX_DEPLOYMENT_TARGET CMAKE_OSX_SYSROOT) -upx_print_Var(CMAKE_CROSSCOMPILING CMAKE_CROSSCOMPILING_EMULATOR) +upx_print_var(CMAKE_CROSSCOMPILING CMAKE_CROSSCOMPILING_EMULATOR) # binutils upx_print_var(CMAKE_AR CMAKE_RANLIB) diff --git a/misc/make/Makefile-extra.mk b/misc/make/Makefile-extra.mk index 958fc522..2de824d3 100644 --- a/misc/make/Makefile-extra.mk +++ b/misc/make/Makefile-extra.mk @@ -59,6 +59,12 @@ build/extra/clang-m64/release: PHONY; $(call run_config_and_build,$@,Release) build/extra/clang-m64/%: export CC = clang -m64 build/extra/clang-m64/%: export CXX = clang++ -m64 +# force building with clang/clang++ -flto=auto +build/extra/clang-lto-auto/debug: PHONY; $(call run_config_and_build,$@,Debug) +build/extra/clang-lto-auto/release: PHONY; $(call run_config_and_build,$@,Release) +build/extra/clang-lto-auto/%: export CC = clang -flto=auto +build/extra/clang-lto-auto/%: export CXX = clang++ -flto=auto + # force building with clang/clang++ -static build/extra/clang-static/debug: PHONY; $(call run_config_and_build,$@,Debug) build/extra/clang-static/release: PHONY; $(call run_config_and_build,$@,Release) @@ -77,7 +83,7 @@ build/extra/clang-static-lto/release: PHONY; $(call run_config_and_build,$@,Rele build/extra/clang-static-lto/%: export CC = clang -static -flto build/extra/clang-static-lto/%: export CXX = clang++ -static -flto -# force building with clang/clang++ C17/C++20 +# force building with clang/clang++ C++20 (and C17) build/extra/clang-std-cxx20/debug: PHONY; $(call run_config_and_build,$@,Debug) build/extra/clang-std-cxx20/release: PHONY; $(call run_config_and_build,$@,Release) build/extra/clang-std-cxx20/%: export CC = clang -std=gnu17 @@ -85,7 +91,7 @@ build/extra/clang-std-cxx20/%: export CXX = clang++ -std=gnu++20 build/extra/clang-std-cxx20/%: export UPX_CONFIG_DISABLE_C_STANDARD=ON build/extra/clang-std-cxx20/%: export UPX_CONFIG_DISABLE_CXX_STANDARD=ON -# force building with clang/clang++ C23/C++23 +# force building with clang/clang++ C++23 (and C23) build/extra/clang-std-cxx23/debug: PHONY; $(call run_config_and_build,$@,Debug) build/extra/clang-std-cxx23/release: PHONY; $(call run_config_and_build,$@,Release) build/extra/clang-std-cxx23/%: export CC = clang -std=gnu2x @@ -117,6 +123,12 @@ build/extra/gcc-m64/release: PHONY; $(call run_config_and_build,$@,Release) build/extra/gcc-m64/%: export CC = gcc -m64 build/extra/gcc-m64/%: export CXX = g++ -m64 +# force building with gcc/g++ -flto=auto +build/extra/gcc-lto-auto/debug: PHONY; $(call run_config_and_build,$@,Debug) +build/extra/gcc-lto-auto/release: PHONY; $(call run_config_and_build,$@,Release) +build/extra/gcc-lto-auto/%: export CC = gcc -flto=auto +build/extra/gcc-lto-auto/%: export CXX = g++ -flto=auto + # force building with gcc/g++ -static build/extra/gcc-static/debug: PHONY; $(call run_config_and_build,$@,Debug) build/extra/gcc-static/release: PHONY; $(call run_config_and_build,$@,Release) @@ -135,7 +147,7 @@ build/extra/gcc-static-lto/release: PHONY; $(call run_config_and_build,$@,Releas build/extra/gcc-static-lto/%: export CC = gcc -static -flto build/extra/gcc-static-lto/%: export CXX = g++ -static -flto -# force building with gcc/g++ C17/C++20 +# force building with gcc/g++ C++20 (and C17) build/extra/gcc-std-cxx20/debug: PHONY; $(call run_config_and_build,$@,Debug) build/extra/gcc-std-cxx20/release: PHONY; $(call run_config_and_build,$@,Release) build/extra/gcc-std-cxx20/%: export CC = gcc -std=gnu17 @@ -143,7 +155,7 @@ build/extra/gcc-std-cxx20/%: export CXX = g++ -std=gnu++20 build/extra/gcc-std-cxx20/%: export UPX_CONFIG_DISABLE_C_STANDARD=ON build/extra/gcc-std-cxx20/%: export UPX_CONFIG_DISABLE_CXX_STANDARD=ON -# force building with gcc/g++ C23/C++23 +# force building with gcc/g++ C++23 (and C23) build/extra/gcc-std-cxx23/debug: PHONY; $(call run_config_and_build,$@,Debug) build/extra/gcc-std-cxx23/release: PHONY; $(call run_config_and_build,$@,Release) build/extra/gcc-std-cxx23/%: export CC = gcc -std=gnu2x @@ -151,6 +163,14 @@ build/extra/gcc-std-cxx23/%: export CXX = g++ -std=gnu++2b build/extra/gcc-std-cxx23/%: export UPX_CONFIG_DISABLE_C_STANDARD=ON build/extra/gcc-std-cxx23/%: export UPX_CONFIG_DISABLE_CXX_STANDARD=ON +# force building with gcc/g++ C++26 (EXPERIMENTAL; need gcc-14) +build/extra/gcc-std-cxx26/debug: PHONY; $(call run_config_and_build,$@,Debug) +build/extra/gcc-std-cxx26/release: PHONY; $(call run_config_and_build,$@,Release) +build/extra/gcc-std-cxx26/%: export CC = gcc -std=gnu23 +build/extra/gcc-std-cxx26/%: export CXX = g++ -std=gnu++26 +build/extra/gcc-std-cxx26/%: export UPX_CONFIG_DISABLE_C_STANDARD=ON +build/extra/gcc-std-cxx26/%: export UPX_CONFIG_DISABLE_CXX_STANDARD=ON + # cross compiler: Linux glibc aarch64-linux-gnu (arm64) build/extra/cross-linux-gnu-aarch64/debug: PHONY; $(call run_config_and_build,$@,Debug) build/extra/cross-linux-gnu-aarch64/release: PHONY; $(call run_config_and_build,$@,Release) diff --git a/misc/podman/rebuild-stubs/Dockerfile b/misc/podman/rebuild-stubs/Dockerfile index b75d194e..dfe67697 100644 --- a/misc/podman/rebuild-stubs/Dockerfile +++ b/misc/podman/rebuild-stubs/Dockerfile @@ -14,10 +14,10 @@ RUN dpkg --add-architecture i386 \ # the following packages are not required for rebuilding the stubs, but # they do make the image *much* more convenient and also allow building # the full UPX binary inside the container via CMake: - 7zip bfs btop bubblewrap busybox bzip2 bzip3 cabextract ccache chrpath cmake cpio \ - dash diffstat direnv elfutils execstack fd-find file fish fzf \ + 7zip bat bfs btop bubblewrap busybox bzip2 bzip3 cabextract ccache chrpath cmake cpio \ + dash diffstat direnv elfutils execstack eza fd-find file fish fzf \ g++ gawk gdb gojq ht htop hyperfine jq ksh \ - libzstd-dev lsd lsb-release lz4 lzip lzop minify mksh moreutils musl neovim ninja-build \ + libzstd-dev lsb-release lsd lz4 lzip lzop minify mksh moreutils musl neovim ninja-build \ p7zip parallel patch patchelf patchutils pax-utils proot \ python3 python3-pyasn1 python3-pycryptodome python3-pycurl python3-tomli python3-tomli-w \ python3-yaml python3-zstd \ diff --git a/misc/podman/rebuild-stubs/packages.txt b/misc/podman/rebuild-stubs/packages.txt index 002e0f0e..45419618 100644 --- a/misc/podman/rebuild-stubs/packages.txt +++ b/misc/podman/rebuild-stubs/packages.txt @@ -8,6 +8,7 @@ ii base-files 13ubuntu10 amd64 ii base-passwd 3.6.3build1 amd64 Debian base system master password and group files ii bash 5.2.21-2ubuntu4 amd64 GNU Bourne Again SHell ii bash-completion 1:2.11-8 all programmable completion for the bash shell +ii bat 0.24.0-1build1 amd64 cat(1) clone with syntax highlighting and git integration ii bfs 3.1.2-1build1 amd64 Breadth-first version of find(1) ii binutils 2.42-4ubuntu2 amd64 GNU assembler, linker and binary utilities ii binutils-common:amd64 2.42-4ubuntu2 amd64 Common files for the GNU assembler, linker and binary utilities @@ -42,6 +43,7 @@ ii dpkg 1.22.6ubuntu6 amd64 ii e2fsprogs 1.47.0-2.4~exp1ubuntu4 amd64 ext2/ext3/ext4 file system utilities ii elfutils 0.190-1.1build4 amd64 collection of utilities to handle ELF objects ii execstack 0.0.20131005-1.1ubuntu1 amd64 ELF GNU_STACK program header editing utility +ii eza 0.18.2-1 amd64 Modern replacement for ls ii fd-find 9.0.0-1 amd64 Simple, fast and user-friendly alternative to find ii file 1:5.45-3build1 amd64 Recognize the type of data in a file using "magic" numbers ii findutils 4.9.0-5build1 amd64 utilities for finding files--find, xargs @@ -368,7 +370,7 @@ ii zstd 1.5.5+dfsg2-2build1 amd64 ||/ Name Version Architecture Description Packages sorted by Installed-Size: - 978188 ===== TOTAL (362 packages) + 984549 ===== TOTAL (364 packages) 76943 valgrind amd64 72249 gcc-13-x86-64-linux-gnu amd64 37841 g++-13-x86-64-linux-gnu amd64 @@ -414,6 +416,7 @@ Packages sorted by Installed-Size: 6433 libx32stdc++-13-dev amd64 6237 dpkg amd64 6158 7zip amd64 + 5219 bat amd64 5210 ripgrep amd64 5169 libpython3.12-minimal amd64 4879 libhwasan0 amd64 @@ -484,6 +487,7 @@ Packages sorted by Installed-Size: 1237 libgit2-1.7 amd64 1186 libmpfr6 amd64 1145 libpam-modules amd64 + 1142 eza amd64 1136 zoxide amd64 1025 libsystemd0 amd64 1014 libkrb5-3 amd64 diff --git a/src/bele.h b/src/bele.h index 4b7a8656..27cdba16 100644 --- a/src/bele.h +++ b/src/bele.h @@ -480,12 +480,9 @@ inline bele_constexpr upx_int64_t get_le64_signed(const XE64 *p) noexcept { /************************************************************************* // classes for portable unaligned access // -// Important: these classes must be PODs (Plain Old Data), i.e. no +// Note: these classes must be PODs (Plain Old Data), i.e. no // constructor, no destructor, no virtual functions and no default -// assignment operator, and all fields must be public(!). -// -// [Actually we _can_ use a safe non-POD subset, but for this we need -// to have gcc bug 17519 fixed - see http://gcc.gnu.org/PR17519 ] +// assignment operator, and all fields must be public **************************************************************************/ struct alignas(1) BE16 final { diff --git a/src/conf.h b/src/conf.h index ce25ec3a..6f00efdb 100644 --- a/src/conf.h +++ b/src/conf.h @@ -52,8 +52,8 @@ static_assert(sizeof(short) == 2); static_assert(sizeof(int) == 4); static_assert(sizeof(long long) == 8); // check sane compiler mandatory flags -static_assert(-1 == ~0); // two's complement - see http://wg21.link/P0907R4 -static_assert(0u - 1 == ~0u); // two's complement - see http://wg21.link/P0907R4 +static_assert(-1 == ~0); // two's complement - see https://wg21.link/P0907R4 +static_assert(0u - 1 == ~0u); // two's complement - see https://wg21.link/P0907R4 static_assert((1u << 31) << 1 == 0); static_assert(((int) (1u << 31)) >> 31 == -1); // arithmetic right shift static_assert((-1) >> 31 == -1); // arithmetic right shift @@ -468,13 +468,12 @@ noreturn void throwAssertFailed(const char *expr, const char *file, int line, co // C++ support library #include "util/cxxlib.h" using upx::tribool; -#define usizeof(expr) (upx::UnsignedSizeOf::value) - -#define ALIGN_DOWN(a, b) upx::align_down((a), (b)) -#define ALIGN_UP(a, b) upx::align_up((a), (b)) -#define ALIGN_GAP(a, b) upx::align_gap((a), (b)) -#define UPX_MAX(a, b) upx::max((a), (b)) -#define UPX_MIN(a, b) upx::min((a), (b)) +#define usizeof(expr) (upx::UnsignedSizeOf::value) +#define ALIGN_DOWN(a, b) (upx::align_down((a), (b))) +#define ALIGN_UP(a, b) (upx::align_up((a), (b))) +#define ALIGN_GAP(a, b) (upx::align_gap((a), (b))) +#define UPX_MAX(a, b) (upx::max((a), (b))) +#define UPX_MIN(a, b) (upx::min((a), (b))) /************************************************************************* // constants diff --git a/src/linker.cpp b/src/linker.cpp index 4206d6e5..11d9165b 100644 --- a/src/linker.cpp +++ b/src/linker.cpp @@ -227,7 +227,7 @@ void ElfLinker::preprocessSymbols(char *start, char const *end) { else if (sscanf(start, "%x%*8c %1023s %*x %1023s", &offset, section, symbol) == 3) #else // work around broken scanf() implementations - // http://bugs.winehq.org/show_bug.cgi?id=10401 (fixed in Wine 0.9.58) + // https://bugs.winehq.org/show_bug.cgi?id=10401 (fixed in Wine 0.9.58) else if (sscanf(start, "%x%*c%*c%*c%*c%*c%*c%*c%*c %1023s %*x %1023s", &offset, section, symbol) == 3) #endif diff --git a/src/packer.cpp b/src/packer.cpp index ecfa2c76..1d45fb14 100644 --- a/src/packer.cpp +++ b/src/packer.cpp @@ -39,7 +39,7 @@ PackerBase::PackerBase(InputFile *f) : fi(f), file_size(f != nullptr ? f->st_size() : 0), file_size_i32(file_size) { ph.reset(); - mem_size_assert(1, file_size_u); + mem_size_assert(1, file_size_u); // limited by UPX_RSIZE_MAX assert_noexcept(file_size_i32 == file_size); assert_noexcept(file_size_u32 == file_size_u); } diff --git a/src/packer.h b/src/packer.h index 395491dd..6d921542 100644 --- a/src/packer.h +++ b/src/packer.h @@ -82,7 +82,7 @@ public: protected: InputFile *const fi; // reference - // multiple names for "file_size" to avoid casts + // multiple names for "file_size" to avoid casts; limited by UPX_RSIZE_MAX union { // unnamed union const upx_int64_t file_size; // must get set by constructor const upx_uint64_t file_size_u; @@ -275,6 +275,7 @@ protected: template static inline constexpr bool is_te64_type = upx::is_same_any_v; + template using enable_if_te16 = std::enable_if_t, T>; template diff --git a/src/util/raw_bytes.h b/src/util/raw_bytes.h index 12f9352a..05239503 100644 --- a/src/util/raw_bytes.h +++ b/src/util/raw_bytes.h @@ -37,7 +37,7 @@ template inline typename std::enable_if::value && !upx::is_bounded_array::value, T>::type - raw_bytes(T ptr, size_t size_in_bytes) { + raw_bytes(T ptr, size_t size_in_bytes) may_throw { if (size_in_bytes > 0) { if very_unlikely (ptr == nullptr) throwCantPack("raw_bytes unexpected NULL ptr"); @@ -53,7 +53,7 @@ template inline typename std::enable_if::value && !upx::is_bounded_array::value && !std::is_void::type>::value, T>::type -raw_index_bytes(T ptr, size_t index, size_t size_in_bytes) { +raw_index_bytes(T ptr, size_t index, size_t size_in_bytes) may_throw { typedef typename std::remove_pointer::type element_type; if very_unlikely (ptr == nullptr) throwCantPack("raw_index_bytes unexpected NULL ptr"); @@ -66,7 +66,7 @@ raw_index_bytes(T ptr, size_t index, size_t size_in_bytes) { // same for bounded arrays template -inline T *raw_bytes(T (&array)[N], size_t size_in_bytes) { +inline T *raw_bytes(T (&array)[N], size_t size_in_bytes) may_throw { typedef T element_type; if very_unlikely (size_in_bytes > mem_size(sizeof(element_type), N)) throwCantPack("raw_bytes out of range"); @@ -74,7 +74,7 @@ inline T *raw_bytes(T (&array)[N], size_t size_in_bytes) { } template -inline T *raw_index_bytes(T (&array)[N], size_t index, size_t size_in_bytes) { +inline T *raw_index_bytes(T (&array)[N], size_t index, size_t size_in_bytes) may_throw { typedef T element_type; return raw_bytes(array, mem_size(sizeof(element_type), index, size_in_bytes)) + index; } diff --git a/src/util/snprintf.h b/src/util/snprintf.h index d0b5248f..9877a763 100644 --- a/src/util/snprintf.h +++ b/src/util/snprintf.h @@ -31,25 +31,25 @@ // UPX version of string functions, with assertions and sane limits **************************************************************************/ +upx_rsize_t upx_safe_strlen(const char *) may_throw; + // info: snprintf() returns length and NOT size, but max_size is indeed size (incl NUL) -int upx_safe_vsnprintf(char *str, upx_rsize_t max_size, const char *format, va_list ap); +int upx_safe_vsnprintf(char *str, upx_rsize_t max_size, const char *format, va_list ap) may_throw; int upx_safe_snprintf(char *str, upx_rsize_t max_size, const char *format, ...) - attribute_format(3, 4); + may_throw attribute_format(3, 4); // malloc's *ptr -int upx_safe_vasprintf(char **ptr, const char *format, va_list ap); -int upx_safe_asprintf(char **ptr, const char *format, ...) attribute_format(2, 3); +int upx_safe_vasprintf(char **ptr, const char *format, va_list ap) may_throw; +int upx_safe_asprintf(char **ptr, const char *format, ...) may_throw attribute_format(2, 3); // returns a malloc'd pointer -char *upx_safe_xprintf(const char *format, ...) attribute_format(1, 2); - -upx_rsize_t upx_safe_strlen(const char *); +char *upx_safe_xprintf(const char *format, ...) may_throw attribute_format(1, 2); // noexcept variants (these use "assert_noexcept") +upx_rsize_t upx_safe_strlen_noexcept(const char *) noexcept; int upx_safe_vsnprintf_noexcept(char *str, upx_rsize_t max_size, const char *format, va_list ap) noexcept; -upx_rsize_t upx_safe_strlen_noexcept(const char *) noexcept; // globally redirect some functions #undef strlen @@ -66,28 +66,32 @@ upx_rsize_t upx_safe_strlen_noexcept(const char *) noexcept; // some uchar string support functions to avoid casts **************************************************************************/ -forceinline uchar *strcpy(uchar *s1, const uchar *s2) { - return (uchar *) strcpy((char *) s1, (const char *) s2); -} - -forceinline int strcmp(const uchar *s1, const char *s2) { return strcmp((const char *) s1, s2); } -forceinline int strcmp(const char *s1, const uchar *s2) { return strcmp(s1, (const char *) s2); } -forceinline int strcmp(const uchar *s1, const uchar *s2) { - return strcmp((const char *) s1, (const char *) s2); -} - -forceinline int strcasecmp(const uchar *s1, const char *s2) { - return strcasecmp((const char *) s1, s2); -} -forceinline int strcasecmp(const char *s1, const uchar *s2) { - return strcasecmp(s1, (const char *) s2); -} -forceinline int strcasecmp(const uchar *s1, const uchar *s2) { - return strcasecmp((const char *) s1, (const char *) s2); -} - -forceinline upx_rsize_t upx_safe_strlen(const uchar *s) { +forceinline upx_rsize_t upx_safe_strlen(const uchar *s) may_throw { return upx_safe_strlen((const char *) s); } +forceinline uchar *strcpy(uchar *s1, const uchar *s2) noexcept { + return (uchar *) strcpy((char *) s1, (const char *) s2); +} + +forceinline int strcmp(const uchar *s1, const char *s2) noexcept { + return strcmp((const char *) s1, s2); +} +forceinline int strcmp(const char *s1, const uchar *s2) noexcept { + return strcmp(s1, (const char *) s2); +} +forceinline int strcmp(const uchar *s1, const uchar *s2) noexcept { + return strcmp((const char *) s1, (const char *) s2); +} + +forceinline int strcasecmp(const uchar *s1, const char *s2) noexcept { + return strcasecmp((const char *) s1, s2); +} +forceinline int strcasecmp(const char *s1, const uchar *s2) noexcept { + return strcasecmp(s1, (const char *) s2); +} +forceinline int strcasecmp(const uchar *s1, const uchar *s2) noexcept { + return strcasecmp((const char *) s1, (const char *) s2); +} + /* vim:set ts=4 sw=4 et: */