diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 055e006b..6da5e6d5 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -384,8 +384,8 @@ jobs: - { zig_target: x86_64-macos.13-none } - { zig_target: x86_64-windows-gnu } env: - # 2023-05-19 - ZIG_DIST_VERSION: 0.11.0-dev.3203+7cf2cbb33 + # 2023-05-27 + ZIG_DIST_VERSION: 0.11.0-dev.3309+8f5f8090c # for zig-cc wrapper scripts (see below): ZIG_CPPFLAGS: -DUPX_DOCTEST_CONFIG_MULTITHREADING ZIG_FLAGS: ${{ matrix.zig_flags }} diff --git a/.github/workflows/test-alpine-linux.yml b/.github/workflows/test-alpine-linux.yml index 14f0b660..b5c98db0 100644 --- a/.github/workflows/test-alpine-linux.yml +++ b/.github/workflows/test-alpine-linux.yml @@ -3,22 +3,24 @@ on: [workflow_dispatch] jobs: job-alpine-clang: strategy: { matrix: { container: ['alpine:edge','i386/alpine:edge'] } } - name: ${{ format('container {0}', matrix.container) }} + name: ${{ format('clang {0}', matrix.container) }} runs-on: ubuntu-latest container: ${{ matrix.container }} steps: - name: ${{ format('Build clang {0}', matrix.container) }} run: | - apk update && apk upgrade && apk add clang cmake make + apk update && apk upgrade && apk add clang cmake g++ make wget https://github.com/upx/upx/releases/download/v4.0.2/upx-4.0.2-src.tar.xz tar -xoaf upx-4.0.2-src.tar.xz cd upx-4.0.2-src - make build/extra/clang/release CC="clang -static" CXX="clang++ -static" - make -C build/extra/clang/release test - make -C build/extra/clang/release install DESTDIR="$PWD/Install-with-make" + make build/debug CC="clang -static" CXX="clang++ -static" + make build/release CC="clang -static" CXX="clang++ -static" + make -C build/debug test + make -C build/release test + make -C build/release install DESTDIR="$PWD/Install" job-alpine-gcc: strategy: { matrix: { container: ['alpine:edge','i386/alpine:edge'] } } - name: ${{ format('container {0}', matrix.container) }} + name: ${{ format('gcc {0}', matrix.container) }} runs-on: ubuntu-latest container: ${{ matrix.container }} steps: @@ -28,6 +30,8 @@ jobs: wget https://github.com/upx/upx/releases/download/v4.0.2/upx-4.0.2-src.tar.xz tar -xoaf upx-4.0.2-src.tar.xz cd upx-4.0.2-src - make build/extra/gcc/release CC="gcc -static" CXX="g++ -static" - make -C build/extra/gcc/release test - make -C build/extra/gcc/release install DESTDIR="$PWD/Install-with-make" + make build/debug CC="gcc -static" CXX="g++ -static" + make build/release CC="gcc -static" CXX="g++ -static" + make -C build/debug test + make -C build/release test + make -C build/release install DESTDIR="$PWD/Install" diff --git a/misc/rebuild-stubs-with-podman/Dockerfile b/misc/rebuild-stubs-with-podman/Dockerfile index a29e347f..4c561f92 100644 --- a/misc/rebuild-stubs-with-podman/Dockerfile +++ b/misc/rebuild-stubs-with-podman/Dockerfile @@ -52,7 +52,7 @@ RUN cd /root \ # create default user upx 2000:2000 RUN useradd upx -U --uid 2000 --shell /bin/bash -m \ - && mkdir -p /home/upx/.cache/zig /home/upx/.local/bin /home/upx/src/upx \ + && mkdir -p /home/upx/.cache/zig /home/upx/.local/bin /home/upx/.wine /home/upx/src/upx \ && ln -s /usr/local/bin/bin-upx-20221212 /home/upx/.local/bin/bin-upx \ && chown -R upx:upx /home/upx \ && true diff --git a/src/check/dt_check.cpp b/src/check/dt_check.cpp index cea31c02..f0cf165f 100644 --- a/src/check/dt_check.cpp +++ b/src/check/dt_check.cpp @@ -165,41 +165,40 @@ namespace { template struct CheckIntegral { + template + struct TestU { + U a = {}; + const U b = {}; + static constexpr U c = {}; + }; template static void checkU(void) { U a = {}; const U b = {}; constexpr U c = {}; - UNUSED(a); - UNUSED(b); - UNUSED(c); + assert(a == 0); + assert(b == 0); + assert(c == 0); + TestU t; + assert(t.a == 0); + assert(t.b == 0); + assert(t.c == 0); #if __cplusplus < 202002L - COMPILE_TIME_ASSERT(std::is_pod::value) // deprecated in C++20 + COMPILE_TIME_ASSERT(std::is_pod::value) // std::is_pod is deprecated in C++20 #endif COMPILE_TIME_ASSERT(std::is_standard_layout::value) COMPILE_TIME_ASSERT(std::is_trivial::value) - // extra checks, these are probably implied by std::is_trivial + // more checks, these are probably implied by std::is_trivial COMPILE_TIME_ASSERT(std::is_nothrow_default_constructible::value) COMPILE_TIME_ASSERT(std::is_trivially_copyable::value) COMPILE_TIME_ASSERT(std::is_trivially_default_constructible::value) - // UPX + // UPX extras COMPILE_TIME_ASSERT(upx_is_integral::value) COMPILE_TIME_ASSERT(upx_is_integral_v) } static void check(void) { - T a = {}; - const T b = {}; - constexpr T c = {}; - assert(a == 0); - assert(b == 0); - assert(c == 0); checkU(); checkU::type>(); -#if !defined(__GNUC__) - // TODO later: "volatile" seems to be broken with some older g++/libstdc++ versions?? - checkU::type>(); - checkU::type>(); -#endif } }; template @@ -439,7 +438,7 @@ void upx_compiler_sanity_check(void) { assert(get_ne32(&b) == 0x04030201); assert(get_ne64(&c) == 0x0807060504030201ull); } -#endif +#endif // DEBUG union { short v_short; int v_int; diff --git a/src/p_exe.cpp b/src/p_exe.cpp index 5b58f7b0..e720f0ac 100644 --- a/src/p_exe.cpp +++ b/src/p_exe.cpp @@ -217,14 +217,13 @@ int PackExe::readFileHeader() { if (ih.ident != 'M' + 'Z' * 256 && ih.ident != 'Z' + 'M' * 256) return 0; ih_exesize = ih.m512 + ih.p512 * 512 - (ih.m512 ? 512 : 0); - if (!ih_exesize) { + if (ih_exesize == 0) ih_exesize = file_size; - } ih_imagesize = ih_exesize - ih.headsize16 * 16; ih_overlay = file_size - ih_exesize; if (file_size_u < sizeof(ih) || ((ih.m512 | ih.p512) && ih.m512 + ih.p512 * 512u < sizeof(ih))) throwCantPack("illegal exe header"); - if (ih_exesize > file_size_u || ih_imagesize <= 0 || ih_imagesize > ih_exesize) + if (ih_exesize > file_size_u || ih_imagesize < 4 || ih_imagesize > ih_exesize) throwCantPack("exe header corrupted"); NO_printf("dos/exe header: %d %d %d\n", ih_exesize, ih_imagesize, ih_overlay); return UPX_F_DOS_EXE; diff --git a/src/p_tos.cpp b/src/p_tos.cpp index a94af9ab..ca38a295 100644 --- a/src/p_tos.cpp +++ b/src/p_tos.cpp @@ -25,8 +25,10 @@ */ -#include "conf.h" +// atari/tos: lots of micro-optimizations because this was written at a time +// where bytes and CPU cycles really mattered +#include "conf.h" #include "file.h" #include "filter.h" #include "packer.h" @@ -258,7 +260,7 @@ int PackTos::readFileHeader() { fi->readx(&ih, FH_SIZE); if (ih.fh_magic != 0x601a) return 0; - if (FH_SIZE + ih.fh_text + ih.fh_data + ih.fh_sym > (unsigned) file_size) + if (0ull + FH_SIZE + ih.fh_text + ih.fh_data + ih.fh_sym > file_size_u) return 0; return UPX_F_ATARI_TOS; } @@ -295,36 +297,37 @@ bool PackTos::checkFileHeader() { // relocs **************************************************************************/ -// Check relocation for errors to make sure our loader can handle them -static int check_relocs(const byte *relocs, unsigned rsize, unsigned image_size, unsigned *relocnum, - unsigned *relocsize, unsigned *overlay) { +// Check relocations for errors to make sure our loader can handle them +static bool check_relocs(const byte *relocs, unsigned rsize, unsigned image_size, + unsigned *relocnum, unsigned *relocsize, unsigned *overlay) { assert(rsize >= 4); assert(image_size >= 4); unsigned fixup = get_be32(relocs); - assert(fixup > 0); + if (fixup == 0 || fixup >= image_size) + return false; unsigned last_fixup = fixup; unsigned i = 4; *relocnum = 1; for (;;) { if (fixup & 1) // must be word-aligned - return -1; + return false; if (fixup + 4 > image_size) // out of bounds - return -1; + return false; if (i >= rsize) // premature EOF in relocs - return -1; + return false; unsigned c = relocs[i++]; if (c == 0) // EOF end marker break; else if (c == 1) // increase fixup, no reloc fixup += 254; else if (c & 1) // must be word-aligned - return -1; + return false; else // next reloc is here { fixup += c; if (fixup - last_fixup < 4) // overlapping relocation - return -1; + return false; last_fixup = fixup; *relocnum += 1; } @@ -332,7 +335,7 @@ static int check_relocs(const byte *relocs, unsigned rsize, unsigned image_size, *relocsize = i; *overlay = rsize - i; - return 0; + return true; } /************************************************************************* @@ -389,7 +392,7 @@ void PackTos::pack(OutputFile *fo) { symbols.up31_base_a6 = 65536 + 1; // read file - const unsigned isize = file_size - i_sym; + const unsigned isize = file_size_u - i_sym; ibuf.alloc(isize); fi->seek(FH_SIZE, SEEK_SET); // read text + data @@ -400,7 +403,7 @@ void PackTos::pack(OutputFile *fo) { throwCantPackExact(); fi->seek(i_sym, SEEK_CUR); // read relocations + overlay - overlay = file_size - (FH_SIZE + i_text + i_data + i_sym); + overlay = file_size_u - (FH_SIZE + i_text + i_data + i_sym); fi->readx(ibuf + t, overlay); #if TESTING @@ -424,8 +427,7 @@ void PackTos::pack(OutputFile *fo) { } else if (ih.fh_reloc != 0) relocsize = 0; else { - int r = check_relocs(ibuf + t, overlay, t, &relocnum, &relocsize, &overlay); - if (r != 0) + if (!check_relocs(ibuf + t, overlay, t, &relocnum, &relocsize, &overlay)) throwCantPack("bad relocation table"); symbols.need_reloc = true; } @@ -702,7 +704,7 @@ void PackTos::unpack(OutputFile *fo) { // write original header & decompressed file if (fo) { - unsigned overlay = file_size - (FH_SIZE + ih.fh_text + ih.fh_data); + unsigned overlay = file_size_u - (FH_SIZE + ih.fh_text + ih.fh_data); if (ih.fh_reloc == 0 && overlay >= 4) overlay -= 4; // this is our empty fixup checkOverlay(overlay); diff --git a/src/packer.cpp b/src/packer.cpp index 18cbdab3..196f4516 100644 --- a/src/packer.cpp +++ b/src/packer.cpp @@ -686,6 +686,7 @@ bool Packer::readPackHeader(int len, bool allow_incompressible) { } void Packer::checkAlreadyPacked(const void *b, int blen) { + assert(blen >= 4); int boff = find_le32(b, blen, UPX_MAGIC_LE32); if (boff < 0) return;