diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b78fd510..0abab908 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -377,8 +377,8 @@ jobs: - { zig_target: x86_64-macos.13-none } - { zig_target: x86_64-windows-gnu } env: - # 2023-04-17 - ZIG_DIST_VERSION: 0.11.0-dev.2624+bc804eb84 + # 2023-04-24 + ZIG_DIST_VERSION: 0.11.0-dev.2777+b95cdf0ae # for zig-cc wrapper scripts (see below): ZIG_CPPFLAGS: -DUPX_DOCTEST_CONFIG_MULTITHREADING ZIG_FLAGS: ${{ matrix.zig_flags }} diff --git a/src/check/dt_check.cpp b/src/check/dt_check.cpp index cf268f3c..a999cbee 100644 --- a/src/check/dt_check.cpp +++ b/src/check/dt_check.cpp @@ -165,6 +165,12 @@ template struct CheckIntegral { template static void checkU(void) { + U a = {}; + const U b = {}; + constexpr U c = {}; + UNUSED(a); + UNUSED(b); + UNUSED(c); #if __cplusplus < 202002L COMPILE_TIME_ASSERT(std::is_pod::value) // deprecated in C++20 #endif @@ -217,15 +223,18 @@ struct TestBELE { static noinline bool test(void) { CheckIntegral::check(); CheckAlignment::check(); + // array init + T array[2] = {}; + assert(array[0] == 0 && array[1] == 0); // arithmetic checks (modern compilers will optimize this away) - T allbits; - allbits = 0; + T allbits = {}; + assert(allbits == 0); allbits += 1; allbits -= 2; T v1; v1 = 1; - v1 *= 2; - v1 /= 1; + v1 *= 4; + v1 /= 2; v1 -= 1; T v2; v2 = 1; @@ -251,6 +260,8 @@ struct TestBELE { v2 &= v1; v2 /= v1; v2 *= v1; + v1 += v2; + v1 -= v2; assert(v1 == 1); assert(v2 == 0); if ((v1 ^ v2) != 1) diff --git a/src/conf.h b/src/conf.h index dd4f0c0a..711a3659 100644 --- a/src/conf.h +++ b/src/conf.h @@ -65,14 +65,8 @@ ACC_COMPILE_TIME_ASSERT_HEADER((char)(-1) == 255) // -funsigned-char // 51:32: error: zero as null pointer constant # pragma GCC diagnostic error "-Wzero-as-null-pointer-constant" #endif -#if (ACC_CC_MSC) -# pragma warning(error: 4127) -# pragma warning(error: 4146) -# pragma warning(error: 4319) -# pragma warning(error: 4805) -#endif -#endif // UPX_CONFIG_DISABLE_WSTRICT #endif // UPX_CONFIG_DISABLE_WERROR +#endif // UPX_CONFIG_DISABLE_WSTRICT // multithreading (UPX currently does not use multithreading) #if (WITH_THREADS) @@ -346,7 +340,7 @@ inline void NO_fprintf(FILE *, const char *, ...) {} # define upx_return_address() nullptr #endif -// TODO cleanup: we now require C++14, so remove all __packed_struct usage +// TODO cleanup: we now require C++17, so remove all __packed_struct usage #define __packed_struct(s) struct alignas(1) s { #define __packed_struct_end() }; diff --git a/src/except.h b/src/except.h index 5fc8cb2a..7713ba05 100644 --- a/src/except.h +++ b/src/except.h @@ -211,6 +211,7 @@ NORET void throwOutOfMemoryException(const char *msg = nullptr); NORET void throwIOException(const char *msg = nullptr, int e = 0); NORET void throwEOFException(const char *msg = nullptr, int e = 0); +// some C++ template wizardry is needed to overload throwCantPack() for varargs template void throwCantPack(const T *, ...) = delete; template <> diff --git a/src/main.cpp b/src/main.cpp index b0c99961..0a749df1 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -28,9 +28,8 @@ // main entry, mostly boring stuff; see work.cpp for actual action #include "conf.h" -#include "file.h" -#include "packer.h" -#include "p_elf.h" +#include "packer.h" // Packer::isValidCompressionMethod() +#include "p_elf.h" // ELFOSABI_xxx #include "compress/compress.h" // upx_ucl_init() /************************************************************************* diff --git a/src/packer.h b/src/packer.h index 0102df0c..9c36cda3 100644 --- a/src/packer.h +++ b/src/packer.h @@ -278,8 +278,16 @@ protected: unsigned image_size, int bits, bool bswap); // Target Endianness abstraction -#if 1 - // try to detect TE16 vs TE32 vs TE64 size mismatches; note that "byte" is explicitly allowed +#if 0 + // permissive version using "void *" + inline unsigned get_te16(const void *p) const noexcept { return bele->get16(p); } + inline unsigned get_te32(const void *p) const noexcept { return bele->get32(p); } + inline upx_uint64_t get_te64(const void *p) const noexcept { return bele->get64(p); } + inline void set_te16(void *p, unsigned v) noexcept { bele->set16(p, v); } + inline void set_te32(void *p, unsigned v) noexcept { bele->set32(p, v); } + inline void set_te64(void *p, upx_uint64_t v) noexcept { bele->set64(p, v); } +#else + // try to detect TE16 vs TE32 vs TE64 size mismatches; note that byte is explicitly allowed template static inline constexpr bool is_te16_type = is_same_any_v; template @@ -312,14 +320,6 @@ protected: inline void set_te64(T *p, upx_uint64_t v) noexcept { bele->set64(p, v); } -#else - // permissive version using "void *" - inline unsigned get_te16(const void *p) const noexcept { return bele->get16(p); } - inline unsigned get_te32(const void *p) const noexcept { return bele->get32(p); } - inline upx_uint64_t get_te64(const void *p) const noexcept { return bele->get64(p); } - inline void set_te16(void *p, unsigned v) noexcept { bele->set16(p, v); } - inline void set_te32(void *p, unsigned v) noexcept { bele->set32(p, v); } - inline void set_te64(void *p, upx_uint64_t v) noexcept { bele->set64(p, v); } #endif protected: diff --git a/src/util/util.cpp b/src/util/util.cpp index cd21c0ce..7c19324f 100644 --- a/src/util/util.cpp +++ b/src/util/util.cpp @@ -247,20 +247,6 @@ TEST_CASE("ptr_check_no_overlap 3") { } #endif // DEBUG -/************************************************************************* -// bele.h -**************************************************************************/ - -namespace N_BELE_CTP { -const BEPolicy be_policy; -const LEPolicy le_policy; -} // namespace N_BELE_CTP - -namespace N_BELE_RTP { -const BEPolicy be_policy; -const LEPolicy le_policy; -} // namespace N_BELE_RTP - /************************************************************************* // stdlib **************************************************************************/ @@ -312,25 +298,47 @@ TEST_CASE("upx_stable_sort") { CHECK((a[0] == 0 && a[1] == 1)); } { - LE64 a[3]; - a[0] = 2; - a[1] = 1; - a[2] = 0; - upx_stable_sort(a, 3, sizeof(*a), le64_compare); - CHECK((a[0] == 0 && a[1] == 1 && a[2] == 2)); + BE64 a[3]; + a[0] = 257; + a[1] = 256; + a[2] = 255; + upx_stable_sort(a, 3, sizeof(*a), be64_compare); + CHECK((a[0] == 255 && a[1] == 256 && a[2] == 257)); } -#if __cplusplus >= 202002L // use C++20 std::next_permutation() to test all permutations - { - upx_uint16_t perm[5] = {0, 1, 2, 3, 4}; // 120 permutations - do { - upx_uint16_t a[5] = {}; - memcpy(a, perm, sizeof(perm)); - upx_stable_sort(a, 5, sizeof(*a), ne16_compare); - CHECK((a[0] == 0 && a[1] == 1 && a[2] == 2 && a[3] == 3 && a[4] == 4)); - } while (std::next_permutation(perm, perm + 5)); - } -#endif } + +#if __cplusplus >= 202002L // use C++20 std::next_permutation() to test all permutations +namespace { +struct TestSortAllPermutations { + static upx_uint64_t test(size_t n) { + constexpr size_t N = 16; + assert(n > 0 && n <= N); + LE16 perm[N]; + for (size_t i = 0; i < n; i++) + perm[i] = 255 + i; + upx_uint64_t num_perms = 0; + do { + LE16 a[N]; + memcpy(a, perm, sizeof(*a) * n); + upx_stable_sort(a, n, sizeof(*a), le16_compare); + for (size_t i = 0; i < n; i++) + CHECK((a[i] == 255 + i)); + num_perms += 1; + } while (std::next_permutation(perm, perm + n)); + return num_perms; + } +}; +} // namespace +TEST_CASE("upx_stable_sort") { + CHECK(TestSortAllPermutations::test(1) == 1); + CHECK(TestSortAllPermutations::test(2) == 2); + CHECK(TestSortAllPermutations::test(3) == 6); + CHECK(TestSortAllPermutations::test(4) == 24); + CHECK(TestSortAllPermutations::test(5) == 120); + // CHECK(TestSortAllPermutations::test(6) == 720); + // CHECK(TestSortAllPermutations::test(7) == 5040); +} +#endif // C++20 #endif // DEBUG /************************************************************************* @@ -537,6 +545,20 @@ TEST_CASE("mem_replace") { CHECK(strcmp(b, "cdcdcdcdefgefghh") == 0); } +/************************************************************************* +// bele.h globals +**************************************************************************/ + +namespace N_BELE_CTP { +const BEPolicy be_policy; +const LEPolicy le_policy; +} // namespace N_BELE_CTP + +namespace N_BELE_RTP { +const BEPolicy be_policy; +const LEPolicy le_policy; +} // namespace N_BELE_RTP + /************************************************************************* // fn - FileName util **************************************************************************/ @@ -736,7 +758,7 @@ bool makebakname(char *ofilename, size_t size, const char *ifilename, bool force **************************************************************************/ unsigned get_ratio(upx_uint64_t u_len, upx_uint64_t c_len) { - const unsigned n = 1000 * 1000; + constexpr unsigned n = 1000 * 1000; if (u_len == 0) return c_len == 0 ? 0 : n; upx_uint64_t x = c_len * n;