From c4437cb2934caee8e0db52f969ed0d95bd5e2782 Mon Sep 17 00:00:00 2001 From: "Markus F.X.J. Oberhumer" Date: Thu, 6 Oct 2022 14:10:35 +0200 Subject: [PATCH] all: add support for a basic "make test" --- .github/travis_testsuite_1.sh | 1 + .github/workflows/ci.yml | 75 ++++++++++++++++++----------------- CMakeLists.txt | 19 ++++++++- src/main.cpp | 2 +- src/p_wcle.cpp | 2 +- src/pefile.cpp | 14 +++---- src/util/dt_check.cpp | 5 ++- src/util/xspan.cpp | 18 ++++++--- src/util/xspan_impl.h | 5 ++- 9 files changed, 87 insertions(+), 54 deletions(-) diff --git a/.github/travis_testsuite_1.sh b/.github/travis_testsuite_1.sh index f0c02469..0ad75632 100644 --- a/.github/travis_testsuite_1.sh +++ b/.github/travis_testsuite_1.sh @@ -174,6 +174,7 @@ if [[ $BM_B =~ (^|\+)coverage($|\+) ]]; then fi export UPX="--prefer-ucl --no-color --no-progress" +export UPX_DEBUG_DISABLE_GITREV_WARNING=1 export UPX_DISABLE_GITREV_WARNING=1 # let's go diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5f7c0b68..fbba7d79 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -49,7 +49,6 @@ jobs: name: ${{ format('{0} cmake', matrix.os) }} runs-on: ${{ matrix.os }} env: - MATRIX_OS: ${{ matrix.os }} UPX_CMAKE_BUILD_FLAGS: --verbose strategy: fail-fast: false @@ -72,7 +71,7 @@ jobs: - name: 'Make artifact' id: make_artifact run: | - N=upx-${GITHUB_REF_NAME}-${GITHUB_SHA:0:7}-${MATRIX_OS} + N=upx-${GITHUB_REF_NAME}-${GITHUB_SHA:0:7}-${{ matrix.os }} mkdir -p "tmp/artifact/$N" (cd build && cp -ai --parents */upx "../tmp/artifact/$N") (cd tmp/artifact && tar --sort=name -czf "$N.tar.gz" "$N" && rm -rf "./$N") @@ -83,13 +82,18 @@ jobs: with: name: ${{ steps.make_artifact.outputs.upload_name }} path: tmp/artifact + - name: 'Run basic tests' + run: | + make -C build/debug-gcc test + make -C build/release-gcc test + make -C build/debug-clang test + make -C build/release-clang test job-macos-cmake: needs: [ job-rebuild-and-verify-stubs ] name: ${{ format('{0} cmake', matrix.os) }} runs-on: ${{ matrix.os }} env: - MATRIX_OS: ${{ matrix.os }} UPX_CMAKE_BUILD_FLAGS: --verbose strategy: fail-fast: false @@ -115,7 +119,7 @@ jobs: - name: 'Make artifact' id: make_artifact run: | - N=upx-${GITHUB_REF_NAME}-${GITHUB_SHA:0:7}-${MATRIX_OS} + N=upx-${GITHUB_REF_NAME}-${GITHUB_SHA:0:7}-${{ matrix.os }} mkdir -p "tmp/artifact/$N" (cd build && rsync -R -a */upx "../tmp/artifact/$N/") (cd tmp/artifact && gtar --sort=name -czf "$N.tar.gz" "$N" && rm -rf "./$N") @@ -126,13 +130,16 @@ jobs: with: name: ${{ steps.make_artifact.outputs.upload_name }} path: tmp/artifact + - name: 'Run basic tests' + run: | + make -C build/debug-clang test + make -C build/release-clang test job-windows-cmake: needs: [ job-rebuild-and-verify-stubs ] name: ${{ format('{0} cmake', matrix.os) }} runs-on: ${{ matrix.os }} env: - MATRIX_OS: ${{ matrix.os }} UPX_CMAKE_BUILD_FLAGS: --verbose strategy: fail-fast: false @@ -162,7 +169,7 @@ jobs: id: make_artifact shell: bash run: | - N=upx-${GITHUB_REF_NAME}-${GITHUB_SHA:0:7}-${MATRIX_OS} + N=upx-${GITHUB_REF_NAME}-${GITHUB_SHA:0:7}-${{ matrix.os }} mkdir -p "tmp/artifact/$N" (cd build && cp -ai --parents */*/upx.exe "../tmp/artifact/$N") # GitHub Actions magic: set "upload_name" Javascript outputs value for use in next step @@ -172,6 +179,10 @@ jobs: with: name: ${{ steps.make_artifact.outputs.upload_name }} path: tmp/artifact + - name: 'Run basic tests' + run: | + cmake --build build/debug --config Debug --target RUN_TESTS + cmake --build build/release --config Release --target RUN_TESTS job-linux-toolchains: if: ${{ false }} # disable for now @@ -306,7 +317,6 @@ jobs: C: ${{ matrix.C }} B: release H: 'd:\a\upx' - MATRIX_NAME: ${{ matrix.name }} strategy: fail-fast: false @@ -319,7 +329,6 @@ jobs: - name: 'Check out code' uses: actions/checkout@v3 with: { submodules: true } - - name: 'Prepare sources' shell: cmd run: | @@ -330,12 +339,10 @@ jobs: md build build\%C% deps cd deps git clone --depth=1 https://github.com/upx/upx-testsuite - - name: 'Set up Developer Command Prompt' uses: ilammy/msvc-dev-cmd@v1 with: arch: ${{ matrix.A }} - - name: 'Build' shell: cmd run: | @@ -345,53 +352,49 @@ jobs: md %BDIR% %BDIR%\ucl %BDIR%\upx %BDIR%\upx-testsuite %BDIR%\zlib set DEFS=-D_CRT_NONSTDC_NO_WARNINGS -D_CRT_SECURE_NO_WARNINGS git rev-parse --short=12 HEAD > %BDIR%\upx\.GITREV.txt - @REM build UCL + @REM ===== build UCL ===== cd %BDIR%\ucl set s=%H%\upx\vendor\ucl cl -MT -J -O2 -W4 %DEFS% -I%s%\include -I%s% -c %s%\src\*.c link -lib -out:ucl.lib *.obj - @REM build zlib + @REM ===== build zlib ===== cd %BDIR%\zlib cl -MT -J -O2 -W3 %DEFS% -c %H%\upx\vendor\zlib\*.c link -lib -out:zlib.lib *.obj - @REM build UPX + @REM ===== build UPX ===== cd %BDIR%\upx set s=%H%\upx\src cat .GITREV.txt set /p GITREV=<.GITREV.txt cl -MT -EHsc -J -O2 -W4 -WX -DUPX_VERSION_GITREV="""%GITREV%""" %DEFS% -I%H%\upx\vendor\doctest -I%H%\upx\vendor\lzma-sdk -I%H%\upx\vendor\ucl\include -I%H%\upx\vendor\zlib -Feupx.exe %s%\*.cpp %s%\util\*.cpp %BDIR%\ucl\ucl.lib %BDIR%\zlib\zlib.lib /link setargv.obj - - - name: 'Basic tests' - shell: cmd + - name: 'Make artifact' + id: make_artifact + shell: bash run: | - cd %H%\build\%C%\%B%\upx - set UPX=--no-color --no-progress + N=upx-${GITHUB_REF_NAME}-${GITHUB_SHA:0:7}-${{ matrix.name }} + mkdir -p "tmp/artifact/$N/$B" + cp -ai ../build/$C/$B/upx/upx*.exe "tmp/artifact/$N/$B" + # GitHub Actions magic: set "upload_name" Javascript outputs value for use in next step + echo "::set-output name=upload_name::$N" + - name: 'Upload artifact' + uses: actions/upload-artifact@v3 + with: + name: ${{ steps.make_artifact.outputs.upload_name }} + path: tmp/artifact + - name: 'Run basic tests' + run: | + $ErrorActionPreference = 'stop' + $ErrorView = 'NormalView' + cd $Env:H\build\$Env:C\$Env:B\upx + $Env:UPX = "--no-color --no-progress" .\upx.exe --version .\upx.exe upx.exe -o upx_packed.exe dir *.exe .\upx.exe -l upx_packed.exe .\upx.exe -t upx_packed.exe .\upx_packed.exe --version - - name: 'Run test suite' - shell: cmd run: | bash ./.github/travis_testsuite_1.sh - - name: 'Make artifact' - id: make_artifact - shell: bash - run: | - N=upx-${GITHUB_REF_NAME}-${GITHUB_SHA:0:7}-${MATRIX_NAME} - mkdir -p "tmp/artifact/$N/$B" - cp -ai ../build/$C/$B/upx/upx*.exe "tmp/artifact/$N/$B" - # GitHub Actions magic: set "upload_name" Javascript outputs value for use in next step - echo "::set-output name=upload_name::$N" - - - name: 'Upload artifact' - uses: actions/upload-artifact@v3 - with: - name: ${{ steps.make_artifact.outputs.upload_name }} - path: tmp/artifact - # vim:set ts=2 sw=2 et: diff --git a/CMakeLists.txt b/CMakeLists.txt index 8b0410cf..beb42d35 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -161,11 +161,26 @@ endif() # "make test" #*********************************************************************** -# TODO: could add some explicit test programs; but then, the integrated +if (NOT CMAKE_CROSSCOMPILING) + include(CTest) + set(exe ${CMAKE_EXECUTABLE_SUFFIX}) + set(upx_self_exe "$") + add_test(NAME upx-test-cleanup COMMAND rm -f ./upx.packed${exe} ./upx.unpacked${exe}) + add_test(NAME upx-version COMMAND upx --version) + add_test(NAME upx-help COMMAND upx --help) + add_test(NAME upx-self-pack COMMAND upx -3 ${upx_self_exe} -o upx.packed${exe}) + add_test(NAME upx-list COMMAND upx -l upx.packed${exe}) + add_test(NAME upx-fileinfo COMMAND upx --fileinfo upx.packed${exe}) + add_test(NAME upx-test COMMAND upx -t upx.packed${exe}) + add_test(NAME upx-unpack COMMAND upx -d upx.packed${exe} -o upx.unpacked${exe}) + add_test(NAME upx-run-unpacked COMMAND ./upx.unpacked${exe} --version) + add_test(NAME upx-run-packed COMMAND ./upx.packed${exe} --version) +endif() + +# TODO: could add some more explicit test programs; but then, the integrated # "doctest" is quite convenient and already covers a number of basic # checks - and more complex cases better should be handled by an # external test suite. -##include(CTest) #*********************************************************************** # "make install" diff --git a/src/main.cpp b/src/main.cpp index 7afaead3..095ee3c9 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1223,7 +1223,7 @@ int upx_main(int argc, char *argv[]) { if (gitrev[0]) { bool warn = true; - const char *ee = getenv("UPX_DISABLE_GITREV_WARNING"); + const char *ee = getenv("UPX_DEBUG_DISABLE_GITREV_WARNING"); if (ee && ee[0] && strcmp(ee, "1") == 0) warn = false; if (warn) { diff --git a/src/p_wcle.cpp b/src/p_wcle.cpp index 0f174534..e525036f 100644 --- a/src/p_wcle.cpp +++ b/src/p_wcle.cpp @@ -413,7 +413,7 @@ void PackWcle::preprocessFixups() set_le32(fix,0xFFFFFFFFUL); fix += 4; - sofixups = ptr_udiff(fix, ifixups); + sofixups = ptr_udiff_bytes(fix, ifixups); } diff --git a/src/pefile.cpp b/src/pefile.cpp index 1ae8c7aa..78700ff1 100644 --- a/src/pefile.cpp +++ b/src/pefile.cpp @@ -1061,7 +1061,7 @@ unsigned PeFile::processImports0(ord_mask_t ord_mask) // pass 1 unsigned esize = ptr_diff_bytes(tarr, idlls[ic]->lookupt); lookups.add(idlls[ic]->lookupt,esize); - if (ptr_diff(ibuf.subref("bad import name %#x", idlls[ic]->iat, 1), (char *)idlls[ic]->lookupt)) + if (ptr_diff_bytes(ibuf.subref("bad import name %#x", idlls[ic]->iat, 1), (char *)idlls[ic]->lookupt) != 0) { memcpy(ibuf.subref("bad import name %#x", idlls[ic]->iat, esize), idlls[ic]->lookupt, esize); iats.add(idlls[ic]->iat,esize); @@ -1215,18 +1215,18 @@ void PeFile::Export::build(char *newbase, unsigned newoffs) char * const enamep = ordinalp + 2 * edir.names; char * exports = enamep + strlen(ename) + 1; - edir.addrtable = newoffs + ptr_diff(functionp, newbase); - edir.ordinaltable = newoffs + ptr_diff(ordinalp, newbase); + edir.addrtable = newoffs + ptr_diff_bytes(functionp, newbase); + edir.ordinaltable = newoffs + ptr_diff_bytes(ordinalp, newbase); memcpy(ordinalp,ordinals,2 * edir.names); - edir.name = newoffs + ptr_diff(enamep, newbase); + edir.name = newoffs + ptr_diff_bytes(enamep, newbase); strcpy(enamep,ename); - edir.nameptrtable = newoffs + ptr_diff(namep, newbase); + edir.nameptrtable = newoffs + ptr_diff_bytes(namep, newbase); unsigned ic; for (ic = 0; ic < edir.names; ic++) { strcpy(exports,names[ic]); - set_le32(namep + 4 * ic,newoffs + ptr_diff(exports, newbase)); + set_le32(namep + 4 * ic,newoffs + ptr_diff_bytes(exports, newbase)); exports += strlen(exports) + 1; } @@ -1235,7 +1235,7 @@ void PeFile::Export::build(char *newbase, unsigned newoffs) if (names[edir.names + ic]) { strcpy(exports,names[edir.names + ic]); - set_le32(functionp + 4 * ic,newoffs + ptr_diff(exports, newbase)); + set_le32(functionp + 4 * ic,newoffs + ptr_diff_bytes(exports, newbase)); exports += strlen(exports) + 1; } diff --git a/src/util/dt_check.cpp b/src/util/dt_check.cpp index 3e3c7780..ab5335a7 100644 --- a/src/util/dt_check.cpp +++ b/src/util/dt_check.cpp @@ -36,10 +36,13 @@ bool upx_doctest_check(int argc, char **argv) { UNUSED(argc); UNUSED(argv); #else + const char *e = getenv("UPX_DEBUG_DOCTEST_DISABLE"); + if (e && e[0] && strcmp(e, "0") != 0) + return true; bool minimal = true; // only show failing tests bool duration = false; // show timings bool success = false; // show all tests - const char *e = getenv("UPX_DEBUG_DOCTEST_VERBOSE"); + e = getenv("UPX_DEBUG_DOCTEST_VERBOSE"); if (e && e[0] && strcmp(e, "0") != 0) { minimal = false; if (strcmp(e, "2") == 0) diff --git a/src/util/xspan.cpp b/src/util/xspan.cpp index a7b35352..c9e72cc5 100644 --- a/src/util/xspan.cpp +++ b/src/util/xspan.cpp @@ -35,19 +35,27 @@ unsigned long long span_check_stats_check_range = 0; __acc_noinline void span_fail_nullptr() { throwCantUnpack("span unexpected NULL pointer; take care!"); } - __acc_noinline void span_fail_not_same_base() { throwInternalError("span unexpected base pointer; take care!"); } +__acc_noinline void span_fail_range_nullptr() { + throwCantUnpack("span_check_range: unexpected NULL pointer; take care!"); +} +__acc_noinline void span_fail_range_nullbase() { + throwCantUnpack("span_check_range: unexpected NULL base; take care!"); +} +__acc_noinline void span_fail_range_range() { + throwCantUnpack("span_check_range: pointer out of range; take care!"); +} -__acc_noinline void span_check_range(const void *p, const void *base, ptrdiff_t size_in_bytes) { +void span_check_range(const void *p, const void *base, ptrdiff_t size_in_bytes) { if __acc_very_unlikely (p == nullptr) - throwCantUnpack("span_check_range: unexpected NULL pointer; take care!"); + span_fail_range_nullptr(); if __acc_very_unlikely (base == nullptr) - throwCantUnpack("span_check_range: unexpected NULL base; take care!"); + span_fail_range_nullbase(); ptrdiff_t off = (const char *) p - (const char *) base; if __acc_very_unlikely (off < 0 || off > size_in_bytes) - throwCantUnpack("span_check_range: pointer out of range; take care!"); + span_fail_range_range(); span_check_stats_check_range += 1; // fprintf(stderr, "span_check_range done\n"); } diff --git a/src/util/xspan_impl.h b/src/util/xspan_impl.h index 628a29be..1caf32ca 100644 --- a/src/util/xspan_impl.h +++ b/src/util/xspan_impl.h @@ -43,7 +43,10 @@ SPAN_NAMESPACE_BEGIN __acc_noinline void span_fail_nullptr(); __acc_noinline void span_fail_not_same_base(); -__acc_noinline void span_check_range(const void *p, const void *base, ptrdiff_t size_in_bytes); +__acc_noinline void span_fail_range_nullptr(); +__acc_noinline void span_fail_range_nullbase(); +__acc_noinline void span_fail_range_range(); +void span_check_range(const void *p, const void *base, ptrdiff_t size_in_bytes); // help constructor to distinguish between number of elements and bytes struct SpanCount {