CI updates and minor cleanups

This commit is contained in:
Markus F.X.J. Oberhumer 2024-04-01 20:31:05 +02:00
parent 70b20d7d89
commit 24f3824524
29 changed files with 176 additions and 128 deletions

4
.gitattributes vendored
View File

@ -3,6 +3,10 @@
# #
# HINT: check settings with # HINT: check settings with
# git ls-files | git check-attr --stdin --all # git ls-files | git check-attr --stdin --all
# git ls-files --eol
# disable all line ending conversions
* -text
# #
# tell diff tools that these files are generated automatically # tell diff tools that these files are generated automatically

View File

@ -16,8 +16,9 @@ env:
UPX_CMAKE_BUILD_FLAGS: --verbose UPX_CMAKE_BUILD_FLAGS: --verbose
UPX_CMAKE_CONFIG_FLAGS: -Wdev --warn-uninitialized UPX_CMAKE_CONFIG_FLAGS: -Wdev --warn-uninitialized
UPX_DEBUG_TEST_FLOAT_DIVISION_BY_ZERO: 1 UPX_DEBUG_TEST_FLOAT_DIVISION_BY_ZERO: 1
# 2024-03-29 UPX_DEBUG_TEST_LIBC_QSORT: 1
ZIG_DIST_VERSION: 0.12.0-dev.3484+7aa42f47b # 2024-04-01
ZIG_DIST_VERSION: 0.12.0-dev.3508+a6ed3e6d2
jobs: jobs:
job-rebuild-and-verify-stubs: job-rebuild-and-verify-stubs:
@ -183,7 +184,7 @@ jobs:
job-macos-cmake: # uses cmake + make job-macos-cmake: # uses cmake + make
if: true if: true
needs: [ job-rebuild-and-verify-stubs ] needs: [ job-rebuild-and-verify-stubs ]
name: ${{ format('{0} {1}', matrix.os, matrix.xcode_version) }} name: ${{ format('{0} {1}{2}', matrix.os, matrix.xcode_version && 'xcode-' || '', matrix.xcode_version) }}
runs-on: ${{ matrix.os }} runs-on: ${{ matrix.os }}
strategy: strategy:
fail-fast: false fail-fast: false
@ -193,8 +194,8 @@ jobs:
# NOTE: macos-11 does not have "readlink -f"; only on macos >= 12 or with brew coreutils # NOTE: macos-11 does not have "readlink -f"; only on macos >= 12 or with brew coreutils
- { os: macos-11, gcc: gcc-10, gxx: 'g++-10', testsuite: true } - { os: macos-11, gcc: gcc-10, gxx: 'g++-10', testsuite: true }
- { os: macos-12, gcc: gcc-11, gxx: 'g++-11', testsuite: true } - { os: macos-12, gcc: gcc-11, gxx: 'g++-11', testsuite: true }
- { os: macos-13, gcc: gcc-12, gxx: 'g++-12', testsuite: true, xcode_version: 14.3.1 }
- { os: macos-13, testsuite: true } # use default Xcode-15 - { os: macos-13, testsuite: true } # use default Xcode-15
- { os: macos-13, gcc: gcc-12, gxx: 'g++-12', testsuite: true, xcode_version: 14.3.1 }
# { os: macos-14, gcc: gcc-13, gxx: 'g++-13', testsuite: true } # gcc-13: INTERNAL ERROR in ld64 # { os: macos-14, gcc: gcc-13, gxx: 'g++-13', testsuite: true } # gcc-13: INTERNAL ERROR in ld64
# { os: macos-14, gcc: gcc-13, gxx: 'g++-13', testsuite: true, xcode_version: 14.3.1 } # gcc-13: MISSING HEADER FILES # { os: macos-14, gcc: gcc-13, gxx: 'g++-13', testsuite: true, xcode_version: 14.3.1 } # gcc-13: MISSING HEADER FILES
- { os: macos-14, gcc: gcc-12, gxx: 'g++-12', testsuite: true } # => use gcc-12 for now - { os: macos-14, gcc: gcc-12, gxx: 'g++-12', testsuite: true } # => use gcc-12 for now
@ -465,16 +466,18 @@ jobs:
- { zig_target: aarch64-windows-gnu } - { zig_target: aarch64-windows-gnu }
- { zig_target: arm-linux-musleabihf, qemu: qemu-arm } - { zig_target: arm-linux-musleabihf, qemu: qemu-arm }
# { zig_target: arm-linux-musleabihf, qemu: qemu-arm, zig_pic: -fPIE } # { zig_target: arm-linux-musleabihf, qemu: qemu-arm, zig_pic: -fPIE }
- { zig_target: i386-linux-musl, qemu: qemu-i386 } - { zig_target: i386-linux-gnu.2.3.4, zig_flags: -march=i586 }
# { zig_target: i386-linux-musl, qemu: qemu-i386, zig_pic: -fPIE } - { zig_target: i386-linux-musl, zig_flags: -march=i586, qemu: qemu-i386 }
# { zig_target: i386-linux-musl, zig_flags: -march=i586, qemu: qemu-i386, zig_pic: -fPIE }
- { zig_target: i386-windows-gnu } - { zig_target: i386-windows-gnu }
# mips and mipsel: bad hard-float code generation(??); or QEMU bug; or UPX bug; see https://github.com/upx/upx/issues/788 # mips and mipsel: bad hard-float code generation(??); or QEMU bug; or UPX bug; see https://github.com/upx/upx/issues/788
- { zig_target: mips-linux-musl, zig_flags: -msoft-float, qemu: qemu-mips } - { zig_target: mips-linux-musl, zig_flags: -msoft-float, qemu: qemu-mips }
- { zig_target: mipsel-linux-musl, zig_flags: -msoft-float, qemu: qemu-mipsel } - { zig_target: mipsel-linux-musl, zig_flags: -msoft-float, qemu: qemu-mipsel }
- { zig_target: powerpc-linux-musl, qemu: qemu-ppc } - { zig_target: powerpc-linux-musl, qemu: qemu-ppc }
# powerpc64: obscure problem with C++ exceptions in doctest checks when *NOT* using -fstack-protector # powerpc64: obscure problem with C++ exceptions in UPX doctest checks when *NOT* using -fstack-protector
- { zig_target: powerpc64-linux-musl, zig_flags: -fstack-protector, qemu: qemu-ppc64 } - { zig_target: powerpc64-linux-musl, zig_flags: -fstack-protector, qemu: qemu-ppc64 }
- { zig_target: powerpc64le-linux-musl, qemu: qemu-ppc64le } - { zig_target: powerpc64le-linux-musl, qemu: qemu-ppc64le }
- { zig_target: x86_64-linux-gnu.2.3.4 }
- { zig_target: x86_64-linux-musl, qemu: qemu-x86_64 } - { zig_target: x86_64-linux-musl, qemu: qemu-x86_64 }
# { zig_target: x86_64-linux-musl, qemu: qemu-x86_64, zig_pic: -fPIE } # { zig_target: x86_64-linux-musl, qemu: qemu-x86_64, zig_pic: -fPIE }
# { zig_target: x86_64-macos-none } # { zig_target: x86_64-macos-none }

View File

@ -516,7 +516,7 @@ if(Threads_FOUND)
elseif(UPX_CONFIG_REQUIRE_THREADS) elseif(UPX_CONFIG_REQUIRE_THREADS)
message(FATAL_ERROR "ERROR: WITH_THREADS required") message(FATAL_ERROR "ERROR: WITH_THREADS required")
elseif(UPX_CONFIG_EXPECT_THREADS AND NOT UPX_CONFIG_DISABLE_THREADS) elseif(UPX_CONFIG_EXPECT_THREADS AND NOT UPX_CONFIG_DISABLE_THREADS)
message(FATAL_ERROR "ERROR: WITH_THREADS expected") message(FATAL_ERROR "ERROR: WITH_THREADS expected; set UPX_CONFIG_EXPECT_THREADS=OFF to disable")
endif() endif()
if(CMAKE_BUILD_TYPE AND NOT CMAKE_BUILD_TYPE MATCHES "^(Debug|None|Release)$") if(CMAKE_BUILD_TYPE AND NOT CMAKE_BUILD_TYPE MATCHES "^(Debug|None|Release)$")
message(WARNING "WARNING: unsupported CMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}; please use \"Debug\" or \"Release\"") message(WARNING "WARNING: unsupported CMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}; please use \"Debug\" or \"Release\"")

View File

@ -236,8 +236,8 @@ build/analyze/clang-tidy/debug build/analyze/clang-tidy/release: build/analyze/c
build/analyze/clang-tidy/debug build/analyze/clang-tidy/release: build/analyze/clang-tidy-zstd/$$(notdir $$@) build/analyze/clang-tidy/debug build/analyze/clang-tidy/release: build/analyze/clang-tidy-zstd/$$(notdir $$@)
# OLD names [deprecated] # OLD names [deprecated]
build/extra/scan-build/debug: build/analyze/clang-analyzer/debug build/extra/scan-build/debug: build/analyze/clang-analyzer/debug PHONY
build/extra/scan-build/release: build/analyze/clang-analyzer/release build/extra/scan-build/release: build/analyze/clang-analyzer/release PHONY
#*********************************************************************** #***********************************************************************
# advanced: generic eXtra target # advanced: generic eXtra target

View File

@ -33,10 +33,6 @@ debug+test release+test all+test: PHONY; $(MAKE) -C $(top_srcd
test:: build/all+test PHONY test:: build/all+test PHONY
# OLD target names [deprecated]
$(top_srcdir)/build/debug: build/debug PHONY
$(top_srcdir)/build/release: build/release PHONY
#*********************************************************************** #***********************************************************************
# make run-testsuite # make run-testsuite
# git clone https://github.com/upx/upx-testsuite.git # git clone https://github.com/upx/upx-testsuite.git

View File

@ -785,6 +785,26 @@ inline unsigned UPX_MIN(const LE32 &a, unsigned b) { return UPX_MIN(unsigned(a),
// misc support // misc support
**************************************************************************/ **************************************************************************/
// for use with qsort()
extern "C" {
int __acc_cdecl_qsort be16_compare(const void *, const void *);
int __acc_cdecl_qsort be24_compare(const void *, const void *);
int __acc_cdecl_qsort be32_compare(const void *, const void *);
int __acc_cdecl_qsort be64_compare(const void *, const void *);
int __acc_cdecl_qsort le16_compare(const void *, const void *);
int __acc_cdecl_qsort le24_compare(const void *, const void *);
int __acc_cdecl_qsort le32_compare(const void *, const void *);
int __acc_cdecl_qsort le64_compare(const void *, const void *);
int __acc_cdecl_qsort be16_compare_signed(const void *, const void *);
int __acc_cdecl_qsort be24_compare_signed(const void *, const void *);
int __acc_cdecl_qsort be32_compare_signed(const void *, const void *);
int __acc_cdecl_qsort be64_compare_signed(const void *, const void *);
int __acc_cdecl_qsort le16_compare_signed(const void *, const void *);
int __acc_cdecl_qsort le24_compare_signed(const void *, const void *);
int __acc_cdecl_qsort le32_compare_signed(const void *, const void *);
int __acc_cdecl_qsort le64_compare_signed(const void *, const void *);
} // extern "C"
// <type_traits> upx_is_integral; see conf.h // <type_traits> upx_is_integral; see conf.h
#define TT_UPX_IS_INTEGRAL(T) \ #define TT_UPX_IS_INTEGRAL(T) \
template <> \ template <> \
@ -826,26 +846,6 @@ typedef LE64 NE64;
#define ne64_compare_signed le64_compare_signed #define ne64_compare_signed le64_compare_signed
#endif #endif
// for use with qsort()
extern "C" {
int __acc_cdecl_qsort be16_compare(const void *, const void *);
int __acc_cdecl_qsort be24_compare(const void *, const void *);
int __acc_cdecl_qsort be32_compare(const void *, const void *);
int __acc_cdecl_qsort be64_compare(const void *, const void *);
int __acc_cdecl_qsort le16_compare(const void *, const void *);
int __acc_cdecl_qsort le24_compare(const void *, const void *);
int __acc_cdecl_qsort le32_compare(const void *, const void *);
int __acc_cdecl_qsort le64_compare(const void *, const void *);
int __acc_cdecl_qsort be16_compare_signed(const void *, const void *);
int __acc_cdecl_qsort be24_compare_signed(const void *, const void *);
int __acc_cdecl_qsort be32_compare_signed(const void *, const void *);
int __acc_cdecl_qsort be64_compare_signed(const void *, const void *);
int __acc_cdecl_qsort le16_compare_signed(const void *, const void *);
int __acc_cdecl_qsort le24_compare_signed(const void *, const void *);
int __acc_cdecl_qsort le32_compare_signed(const void *, const void *);
int __acc_cdecl_qsort le64_compare_signed(const void *, const void *);
} // extern "C"
/************************************************************************* /*************************************************************************
// Provide namespaces and classes to abstract endianness policies. // Provide namespaces and classes to abstract endianness policies.
// //

View File

@ -92,9 +92,9 @@ private:
#define C const noexcept override #define C const noexcept override
#endif #endif
struct BEPolicy struct BEPolicy final
#if defined(BELE_RTP) #if defined(BELE_RTP)
final : public AbstractPolicy : public AbstractPolicy
#endif #endif
{ {
explicit inline BEPolicy() noexcept {} explicit inline BEPolicy() noexcept {}
@ -151,9 +151,9 @@ private:
UPX_CXX_DISABLE_NEW_DELETE(BEPolicy) UPX_CXX_DISABLE_NEW_DELETE(BEPolicy)
}; };
struct LEPolicy struct LEPolicy final
#if defined(BELE_RTP) #if defined(BELE_RTP)
final : public AbstractPolicy : public AbstractPolicy
#endif #endif
{ {
explicit inline LEPolicy() noexcept {} explicit inline LEPolicy() noexcept {}

View File

@ -24,6 +24,9 @@
<markus@oberhumer.com> <markus@oberhumer.com>
*/ */
// doctest checks, and various tests to catch toolchain/qemu/sanitizer/valgrind/wine/etc
// problems; grown historically
#include "../util/system_headers.h" #include "../util/system_headers.h"
#include <cmath> // std::isinf std::isnan #include <cmath> // std::isinf std::isnan
#include "../conf.h" #include "../conf.h"
@ -376,6 +379,7 @@ struct TestFloat {
static noinline Float add_div_x(Int a, Int b) { return Float(a + b) / Float(X); } static noinline Float add_div_x(Int a, Int b) { return Float(a + b) / Float(X); }
static noinline Float sub_div_x(Int a, Int b) { return Float(a - b) / Float(X); } static noinline Float sub_div_x(Int a, Int b) { return Float(a - b) / Float(X); }
static noinline void check() noexcept { static noinline void check() noexcept {
assert_noexcept(div(2 * X, Float(X)) == Float(2));
assert_noexcept(add_div(X, X, Float(X)) == Float(2)); assert_noexcept(add_div(X, X, Float(X)) == Float(2));
assert_noexcept(add_div_x(X, X) == Float(2)); assert_noexcept(add_div_x(X, X) == Float(2));
assert_noexcept(sub_div(3 * X, X, Float(X)) == Float(2)); assert_noexcept(sub_div(3 * X, X, Float(X)) == Float(2));
@ -391,6 +395,7 @@ struct TestFloat {
#else #else
assert_noexcept(std::isnan(div(0, Float(0)))); assert_noexcept(std::isnan(div(0, Float(0))));
assert_noexcept(std::isinf(div(1, Float(0)))); assert_noexcept(std::isinf(div(1, Float(0))));
assert_noexcept(std::isinf(div(Int(-1), Float(0))));
#endif #endif
} }
} }
@ -432,6 +437,19 @@ void upx_compiler_sanity_check(void) noexcept {
check_basic_floating_point(); check_basic_floating_point();
// check_basic_decltype()
{
auto a = +0;
constexpr auto b = -0;
const auto &c = -1;
COMPILE_TIME_ASSERT((std::is_same<int, decltype(a)>::value))
COMPILE_TIME_ASSERT((std::is_same<const int, decltype(b)>::value))
COMPILE_TIME_ASSERT((std::is_same<const int &, decltype(c)>::value))
UNUSED(a);
UNUSED(b);
UNUSED(c);
}
#define ACC_WANT_ACC_CHK_CH 1 #define ACC_WANT_ACC_CHK_CH 1
#undef ACCCHK_ASSERT #undef ACCCHK_ASSERT
#define ACCCHK_ASSERT(expr) ACC_COMPILE_TIME_ASSERT(expr) #define ACCCHK_ASSERT(expr) ACC_COMPILE_TIME_ASSERT(expr)
@ -646,7 +664,7 @@ void upx_compiler_sanity_check(void) noexcept {
**************************************************************************/ **************************************************************************/
TEST_CASE("assert_noexcept") { TEST_CASE("assert_noexcept") {
// just to make sure that our own assert() macros don't generate any warnings // just to make sure that our own assert() macros do not trigger any compiler warnings
byte dummy = 0; byte dummy = 0;
byte *ptr1 = &dummy; byte *ptr1 = &dummy;
const byte *const ptr2 = &dummy; const byte *const ptr2 = &dummy;
@ -668,10 +686,13 @@ TEST_CASE("acc_vget") {
CHECK_EQ(acc_vget_long(1, -1), 1); CHECK_EQ(acc_vget_long(1, -1), 1);
CHECK_EQ(acc_vget_acc_int64l_t(2, 1), 2); CHECK_EQ(acc_vget_acc_int64l_t(2, 1), 2);
CHECK_EQ(acc_vget_acc_hvoid_p(nullptr, 0), nullptr); CHECK_EQ(acc_vget_acc_hvoid_p(nullptr, 0), nullptr);
if (acc_vget_int(1, 0) > 0)
return;
assert_noexcept(false);
} }
TEST_CASE("ptr_invalidate_and_poison") { TEST_CASE("ptr_invalidate_and_poison") {
int *ip = nullptr; int *ip = nullptr; // initialized
ptr_invalidate_and_poison(ip); ptr_invalidate_and_poison(ip);
assert(ip != nullptr); assert(ip != nullptr);
(void) ip; (void) ip;
@ -751,11 +772,13 @@ TEST_CASE("libc snprintf") {
CHECK_EQ(strcmp(buf, "0X1A 0x1b 0x1c "), 0); CHECK_EQ(strcmp(buf, "0X1A 0x1b 0x1c "), 0);
} }
#if 0
TEST_CASE("libc qsort") { TEST_CASE("libc qsort") {
// runtime check that libc qsort() never compares identical objects // runtime check that libc qsort() never compares identical objects
// UPDATE: while only poor implementations of qsort() would actually do // UPDATE: while only poor implementations of qsort() would actually do this
// this, it is probably allowed by the standard; so skip this test case // it is probably allowed by the standard, so skip this test by default
if (!is_envvar_true("UPX_DEBUG_TEST_LIBC_QSORT"))
return;
struct Elem { struct Elem {
upx_uint16_t id; upx_uint16_t id;
upx_uint16_t value; upx_uint16_t value;
@ -765,8 +788,8 @@ TEST_CASE("libc qsort") {
assert_noexcept(a->id != b->id); // check not IDENTICAL assert_noexcept(a->id != b->id); // check not IDENTICAL
return a->value < b->value ? -1 : (a->value == b->value ? 0 : 1); return a->value < b->value ? -1 : (a->value == b->value ? 0 : 1);
} }
static bool check_sort(upx_sort_func_t sort, Elem *e, size_t n) { static noinline bool check_sort(upx_sort_func_t sort, Elem *e, size_t n) {
upx_uint32_t x = 5381 + n + ((upx_uintptr_t) e & 0xff); upx_uint32_t x = 5381 + n + (upx_rand() & 0xff);
for (size_t i = 0; i < n; i++) { for (size_t i = 0; i < n; i++) {
e[i].id = (upx_uint16_t) i; e[i].id = (upx_uint16_t) i;
x = x * 33 + 1 + (i & 255); x = x * 33 + 1 + (i & 255);
@ -782,18 +805,19 @@ TEST_CASE("libc qsort") {
constexpr size_t N = 4096; constexpr size_t N = 4096;
Elem e[N]; Elem e[N];
for (size_t n = 0; n <= N; n = 2 * n + 1) { for (size_t n = 0; n <= N; n = 2 * n + 1) {
// CHECK(Elem::check_sort(qsort, e, n)); // libc qsort() // system sort functions
CHECK(Elem::check_sort(upx_gnomesort, e, n)); CHECK(Elem::check_sort(::qsort, e, n)); // libc qsort()
CHECK(Elem::check_sort(upx_shellsort_memswap, e, n));
CHECK(Elem::check_sort(upx_shellsort_memcpy, e, n));
#if UPX_CONFIG_USE_STABLE_SORT #if UPX_CONFIG_USE_STABLE_SORT
upx_sort_func_t wrap_stable_sort = [](void *aa, size_t nn, size_t, upx_compare_func_t cc) { upx_sort_func_t wrap_stable_sort = [](void *aa, size_t nn, size_t, upx_compare_func_t cc) {
upx_std_stable_sort<sizeof(Elem)>(aa, nn, cc); upx_std_stable_sort<sizeof(Elem)>(aa, nn, cc);
}; };
CHECK(Elem::check_sort(wrap_stable_sort, e, n)); CHECK(Elem::check_sort(wrap_stable_sort, e, n)); // std::stable_sort()
#endif #endif
// UPX sort functions
CHECK(Elem::check_sort(upx_gnomesort, e, n));
CHECK(Elem::check_sort(upx_shellsort_memswap, e, n));
CHECK(Elem::check_sort(upx_shellsort_memcpy, e, n));
} }
} }
#endif
/* vim:set ts=4 sw=4 et: */ /* vim:set ts=4 sw=4 et: */

View File

@ -27,24 +27,8 @@
// lots of tests (and probably quite a number of redundant tests) // lots of tests (and probably quite a number of redundant tests)
// modern compilers will optimize away much of this code // modern compilers will optimize away much of this code
#if 0 // TODO later
// libc++ hardenining
#if defined(__clang__) && defined(__clang_major__) && (__clang_major__ + 0 >= 18)
#if DEBUG
#define _LIBCPP_HARDENING_MODE _LIBCPP_HARDENING_MODE_DEBUG
#else
#define _LIBCPP_HARDENING_MODE _LIBCPP_HARDENING_MODE_EXTENSIVE
#endif
#endif
#if defined(__clang__) && defined(__clang_major__) && (__clang_major__ + 0 < 18)
#if DEBUG
#define _LIBCPP_ENABLE_ASSERTIONS 1
#endif
#endif
#endif // TODO later
#include "../util/system_headers.h" #include "../util/system_headers.h"
#include <vector> #include <vector> // std::vector
#include "../conf.h" #include "../conf.h"
/************************************************************************* /*************************************************************************
@ -125,7 +109,7 @@ ACC_COMPILE_TIME_ASSERT_HEADER(compile_time::string_le("abc", "abz"))
// //
**************************************************************************/ **************************************************************************/
TEST_CASE("libc++") { TEST_CASE("std::vector") {
constexpr size_t N = 16; constexpr size_t N = 16;
std::vector<int> v(N); std::vector<int> v(N);
CHECK(v.end() - v.begin() == N); CHECK(v.end() - v.begin() == N);
@ -298,7 +282,7 @@ TEST_CASE("upx::ObjectDeleter 2") {
} }
TEST_CASE("upx::ptr_static_cast") { TEST_CASE("upx::ptr_static_cast") {
// check that we don't trigger any -Wcast-align warnings // check that we do not trigger any -Wcast-align warnings
using upx::ptr_static_cast; using upx::ptr_static_cast;
void *vp = nullptr; void *vp = nullptr;
byte *bp = nullptr; byte *bp = nullptr;

View File

@ -162,7 +162,7 @@ ACC_COMPILE_TIME_ASSERT_HEADER(sizeof(upx_charptr_unit_type) == 1)
typedef upx_int64_t upx_off_t; typedef upx_int64_t upx_off_t;
#undef off_t #undef off_t
#if 0 #if 0
// TODO cleanup: at some future point we can do this: // TODO later cleanup: at some future point we can do this:
#define off_t DO_NOT_USE_off_t #define off_t DO_NOT_USE_off_t
#else #else
#define off_t upx_off_t #define off_t upx_off_t
@ -230,12 +230,6 @@ typedef upx_int64_t upx_off_t;
#undef sopen #undef sopen
#endif #endif
#if defined(HAVE_DUP) && (HAVE_DUP + 0 == 0)
// TODO later: add upx_fd_dup() util
#undef dup
#define dup(x) (-1)
#endif
#ifndef STDIN_FILENO #ifndef STDIN_FILENO
#define STDIN_FILENO (fileno(stdin)) #define STDIN_FILENO (fileno(stdin))
#endif #endif
@ -338,7 +332,7 @@ typedef upx_int64_t upx_off_t;
// TODO later: check __MINGW_PRINTF_FORMAT // TODO later: check __MINGW_PRINTF_FORMAT
#if defined(_WIN32) && defined(__MINGW32__) && defined(__GNUC__) && !defined(__clang__) #if defined(_WIN32) && defined(__MINGW32__) && defined(__GNUC__) && !defined(__clang__)
#define attribute_format(a, b) __attribute__((__format__(__gnu_printf__, a, b))) #define attribute_format(a, b) __attribute__((__format__(__gnu_printf__, a, b)))
#elif (ACC_CC_CLANG || ACC_CC_GNUC) #elif defined(__clang__) || defined(__GNUC__)
#define attribute_format(a, b) __attribute__((__format__(__printf__, a, b))) #define attribute_format(a, b) __attribute__((__format__(__printf__, a, b)))
#else #else
#define attribute_format(a, b) /*empty*/ #define attribute_format(a, b) /*empty*/
@ -442,6 +436,7 @@ inline void mem_clear(T *object) noexcept {
static_assert(size >= 1 && size <= UPX_RSIZE_MAX_MEM); static_assert(size >= 1 && size <= UPX_RSIZE_MAX_MEM);
memset((void *) object, 0, size); memset((void *) object, 0, size);
} }
// disable some overloads
#if defined(__clang__) || __GNUC__ != 7 #if defined(__clang__) || __GNUC__ != 7
template <class T> template <class T>
inline void mem_clear(T (&array)[]) noexcept DELETED_FUNCTION; inline void mem_clear(T (&array)[]) noexcept DELETED_FUNCTION;

View File

@ -203,7 +203,7 @@ const char *prettyName(const char *n) noexcept {
n++; n++;
else if (*n == ' ') else if (*n == ' ')
n++; n++;
else if (strncmp(n, "class ", 6) == 0) // Visual C++ (msvc) else if (strncmp(n, "class ", 6) == 0) // Visual C++ (MSVC)
n += 6; n += 6;
else else
break; break;

View File

@ -40,6 +40,7 @@
#else #else
UNUSED(name); UNUSED(name);
UNUSED(mode); UNUSED(mode);
// no error
#endif #endif
} }
@ -88,7 +89,7 @@ bool FileBase::do_sopen() {
else { else {
#if (ACC_OS_DOS32) && defined(__DJGPP__) #if (ACC_OS_DOS32) && defined(__DJGPP__)
_fd = ::open(_name, _flags | _shflags, _mode); _fd = ::open(_name, _flags | _shflags, _mode);
#elif defined(__MINT__) #elif (ACC_ARCH_M68K && ACC_OS_TOS && ACC_CC_GNUC) && defined(__MINT__)
_fd = ::open(_name, _flags | (_shflags & O_SHMODE), _mode); _fd = ::open(_name, _flags | (_shflags & O_SHMODE), _mode);
#elif defined(SH_DENYRW) #elif defined(SH_DENYRW)
_fd = ::sopen(_name, _flags, _shflags, _mode); _fd = ::sopen(_name, _flags, _shflags, _mode);
@ -98,6 +99,7 @@ bool FileBase::do_sopen() {
} }
if (_fd < 0) if (_fd < 0)
return false; return false;
st.st_size = 0;
if (::fstat(_fd, &st) != 0) if (::fstat(_fd, &st) != 0)
throwIOException(_name, errno); throwIOException(_name, errno);
_length = st.st_size; _length = st.st_size;
@ -212,6 +214,20 @@ upx_off_t InputFile::seek(upx_off_t off, int whence) {
upx_off_t InputFile::st_size_orig() const { return _length_orig; } upx_off_t InputFile::st_size_orig() const { return _length_orig; }
int InputFile::dup() may_throw {
if (!isOpen())
throwIOException("bad dup");
#if defined(HAVE_DUP) && (HAVE_DUP + 0 == 0)
errno = ENOSYS;
int r = -1;
#else
int r = ::dup(getFd());
#endif
if (r < 0)
throwIOException("dup", errno);
return r;
}
/************************************************************************* /*************************************************************************
// OutputFile // OutputFile
**************************************************************************/ **************************************************************************/
@ -333,6 +349,7 @@ void OutputFile::set_extent(upx_off_t offset, upx_off_t length) {
super::set_extent(offset, length); super::set_extent(offset, length);
bytes_written = 0; bytes_written = 0;
if (0 == offset && 0xffffffffLL == length) { // TODO: check all callers of this method if (0 == offset && 0xffffffffLL == length) { // TODO: check all callers of this method
st.st_size = 0;
if (::fstat(_fd, &st) != 0) if (::fstat(_fd, &st) != 0)
throwIOException(_name, errno); throwIOException(_name, errno);
_length = st.st_size - offset; _length = st.st_size - offset;

View File

@ -88,6 +88,8 @@ public:
virtual upx_off_t seek(upx_off_t off, int whence) override; virtual upx_off_t seek(upx_off_t off, int whence) override;
upx_off_t st_size_orig() const; upx_off_t st_size_orig() const;
noinline int dup() may_throw;
protected: protected:
upx_off_t _length_orig = 0; upx_off_t _length_orig = 0;
}; };

View File

@ -60,7 +60,7 @@ ElfLinker::Section::Section(const char *n, const void *i, unsigned s, unsigned a
: name(nullptr), output(nullptr), size(s), offset(0), p2align(a), next(nullptr) { : name(nullptr), output(nullptr), size(s), offset(0), p2align(a), next(nullptr) {
name = strdup(n); name = strdup(n);
assert(name != nullptr); assert(name != nullptr);
input = malloc(s + 1); input = ::malloc(s + 1);
assert(input != nullptr); assert(input != nullptr);
if (s != 0) { if (s != 0) {
assert(i != nullptr); assert(i != nullptr);
@ -70,8 +70,8 @@ ElfLinker::Section::Section(const char *n, const void *i, unsigned s, unsigned a
} }
ElfLinker::Section::~Section() noexcept { ElfLinker::Section::~Section() noexcept {
free(name); ::free(name);
free(input); ::free(input);
} }
/************************************************************************* /*************************************************************************
@ -85,7 +85,7 @@ ElfLinker::Symbol::Symbol(const char *n, Section *s, upx_uint64_t o)
assert(section != nullptr); assert(section != nullptr);
} }
ElfLinker::Symbol::~Symbol() noexcept { free(name); } ElfLinker::Symbol::~Symbol() noexcept { ::free(name); }
/************************************************************************* /*************************************************************************
// Relocation // Relocation
@ -110,13 +110,13 @@ ElfLinker::~ElfLinker() noexcept {
unsigned ic; unsigned ic;
for (ic = 0; ic < nsections; ic++) for (ic = 0; ic < nsections; ic++)
delete sections[ic]; delete sections[ic];
free(sections); ::free(sections);
for (ic = 0; ic < nsymbols; ic++) for (ic = 0; ic < nsymbols; ic++)
delete symbols[ic]; delete symbols[ic];
free(symbols); ::free(symbols);
for (ic = 0; ic < nrelocations; ic++) for (ic = 0; ic < nrelocations; ic++)
delete relocations[ic]; delete relocations[ic];
free(relocations); ::free(relocations);
} }
void ElfLinker::init(const void *pdata_v, int plen, unsigned pxtra) { void ElfLinker::init(const void *pdata_v, int plen, unsigned pxtra) {
@ -425,7 +425,7 @@ int ElfLinker::addLoader(const char *sname) {
} }
sect += strlen(sect) + 1; sect += strlen(sect) + 1;
} }
free(begin); ::free(begin);
return outputlen; return outputlen;
} }

View File

@ -923,7 +923,7 @@ int main_get_options(int argc, char **argv) {
// atari/tos // atari/tos
{"split-segments", 0x90, N, 650}, {"split-segments", 0x90, N, 650},
// darwin/macho // darwin/macho
{"force-macos", 0x90, N, 690}, // undocumented temporary until we fix macOS 13+ {"force-macos", 0x90, N, 690}, // undocumented temporary option until we do fix macOS 13+
// djgpp2/coff // djgpp2/coff
{"coff", 0x90, N, 610}, // produce COFF output {"coff", 0x90, N, 610}, // produce COFF output
// dos/exe // dos/exe
@ -1355,9 +1355,9 @@ int __acc_cdecl_main main(int argc, char *argv[]) /*noexcept*/ {
#endif #endif
acc_wildargv(&argc, &argv); acc_wildargv(&argc, &argv);
#if defined(__wasi__) #if defined(__wasi__)
srand((int) time(nullptr)); ::srand((unsigned) time(nullptr));
#else #else
srand((int) clock()); ::srand((unsigned) clock());
#endif #endif
// info: main() is implicitly "noexcept", so we need a try block // info: main() is implicitly "noexcept", so we need a try block

View File

@ -28,9 +28,10 @@
#pragma once #pragma once
struct Options; struct Options;
extern Options *opt; // global options, see class PackMaster for per-file local options
#define options_t Options // old name #define options_t Options // old name
extern Options *opt; // global options, see class PackMaster for per-file local options
#if WITH_THREADS #if WITH_THREADS
extern std::mutex opt_lock_mutex; extern std::mutex opt_lock_mutex;
#endif #endif
@ -177,6 +178,9 @@ struct Options final {
int strip_relocs; int strip_relocs;
const char *keep_resource; const char *keep_resource;
} win32_pe; } win32_pe;
private: // UPX conventions
UPX_CXX_DISABLE_NEW_DELETE(Options)
}; };
/* vim:set ts=4 sw=4 et: */ /* vim:set ts=4 sw=4 et: */

View File

@ -267,7 +267,7 @@ int PackVmlinuzI386::decompressKernel()
fd_pos = -1; fd_pos = -1;
// open // open
fi->seek(gzoff, SEEK_SET); fi->seek(gzoff, SEEK_SET);
fd = dup(fi->getFd()); fd = fi->dup();
if (fd < 0) if (fd < 0)
break; break;
gzFile zf = gzdopen(fd, "rb"); gzFile zf = gzdopen(fd, "rb");
@ -849,7 +849,7 @@ int PackVmlinuzARMEL::decompressKernel()
fd_pos = -1; fd_pos = -1;
// open // open
fi->seek(gzoff, SEEK_SET); fi->seek(gzoff, SEEK_SET);
fd = dup(fi->getFd()); fd = fi->dup();
if (fd < 0) if (fd < 0)
break; break;
gzFile zf = gzdopen(fd, "rb"); gzFile zf = gzdopen(fd, "rb");

View File

@ -743,6 +743,7 @@ tribool PackWcle::canUnpack() {
return readPackHeader(len) ? 1 : -1; return readPackHeader(len) ? 1 : -1;
} }
/*static*/
void PackWcle::virt2rela(const le_object_table_entry_t *entr, unsigned *objn, unsigned *addr) { void PackWcle::virt2rela(const le_object_table_entry_t *entr, unsigned *objn, unsigned *addr) {
for (; *objn > 1; objn[0]--) { for (; *objn > 1; objn[0]--) {
if (entr[*objn - 1].my_base_address > *addr) if (entr[*objn - 1].my_base_address > *addr)

View File

@ -495,7 +495,7 @@ unsigned Packer::getRandomId() const {
#endif #endif
id ^= (unsigned) fi->st.st_ino; id ^= (unsigned) fi->st.st_ino;
id ^= (unsigned) fi->st.st_atime; id ^= (unsigned) fi->st.st_atime;
id ^= (unsigned) rand(); id ^= (unsigned) upx_rand();
} }
return id; return id;
} }
@ -947,7 +947,7 @@ int Packer::prepareMethods(int *methods, int ph_method, const int *all_methods)
} }
// debug // debug
if (opt->debug.use_random_method && nmethods >= 2) { if (opt->debug.use_random_method && nmethods >= 2) {
int method = methods[rand() % nmethods]; int method = methods[upx_rand() % nmethods];
methods[0] = method; methods[0] = method;
nmethods = 1; nmethods = 1;
NO_printf("\nuse_random_method = %d\n", method); NO_printf("\nuse_random_method = %d\n", method);
@ -1015,7 +1015,7 @@ done:
filters[nfilters++] = 0; filters[nfilters++] = 0;
// debug // debug
if (opt->debug.use_random_filter && nfilters >= 3 && filters[nfilters - 1] == 0) { if (opt->debug.use_random_filter && nfilters >= 3 && filters[nfilters - 1] == 0) {
int filter_id = filters[rand() % (nfilters - 1)]; int filter_id = filters[upx_rand() % (nfilters - 1)];
if (filter_id > 0) { if (filter_id > 0) {
filters[0] = filter_id; filters[0] = filter_id;
filters[1] = 0; filters[1] = 0;

View File

@ -84,10 +84,14 @@ struct PackHeader final {
// info fields set by Packer::compressWithFilters() // info fields set by Packer::compressWithFilters()
unsigned overlap_overhead; unsigned overlap_overhead;
private: // UPX conventions
UPX_CXX_DISABLE_ADDRESS(PackHeader)
UPX_CXX_DISABLE_NEW_DELETE(PackHeader)
}; };
/************************************************************************* /*************************************************************************
// ph default util functions // PackHeader ph util functions
**************************************************************************/ **************************************************************************/
bool ph_is_forced_method(int method) noexcept; // predicate bool ph_is_forced_method(int method) noexcept; // predicate

View File

@ -59,6 +59,11 @@ private:
// setup local options for each file // setup local options for each file
Options local_options; Options local_options;
Options *saved_opt = nullptr; Options *saved_opt = nullptr;
private: // UPX conventions
UPX_CXX_DISABLE_ADDRESS(PackMaster)
UPX_CXX_DISABLE_COPY_MOVE(PackMaster)
UPX_CXX_DISABLE_NEW_DELETE(PackMaster)
}; };
/* vim:set ts=4 sw=4 et: */ /* vim:set ts=4 sw=4 et: */

View File

@ -215,7 +215,7 @@ int PeFile::readFileHeader() {
PeFile::Interval::Interval(SPAN_P(byte) b) : base(b) {} PeFile::Interval::Interval(SPAN_P(byte) b) : base(b) {}
PeFile::Interval::~Interval() noexcept { free(ivarr); } PeFile::Interval::~Interval() noexcept { ::free(ivarr); }
int __acc_cdecl_qsort PeFile::Interval::compare(const void *p1, const void *p2) { int __acc_cdecl_qsort PeFile::Interval::compare(const void *p1, const void *p2) {
const interval *i1 = (const interval *) p1; const interval *i1 = (const interval *) p1;
@ -1175,14 +1175,14 @@ PeFile::Export::Export(char *_base) : base(_base), iv((byte *) _base) {
} }
PeFile::Export::~Export() noexcept { PeFile::Export::~Export() noexcept {
free(ename); ::free(ename);
delete[] functionptrs; delete[] functionptrs;
delete[] ordinals; delete[] ordinals;
if (names) { if (names) {
const unsigned limit = edir.names + edir.functions; const unsigned limit = edir.names + edir.functions;
for (unsigned ic = 0; ic < limit; ic++) for (unsigned ic = 0; ic < limit; ic++)
if (names[ic]) if (names[ic])
free(names[ic]); // allocated by strdup() ::free(names[ic]); // allocated by strdup()
delete[] names; delete[] names;
} }
} }

View File

@ -104,6 +104,10 @@ protected:
static unsigned update_u_len; static unsigned update_u_len;
static unsigned update_fc_len; static unsigned update_fc_len;
static unsigned update_fu_len; static unsigned update_fu_len;
private: // UPX conventions
UPX_CXX_DISABLE_ADDRESS(UiPacker)
UPX_CXX_DISABLE_COPY_MOVE(UiPacker)
}; };
/* vim:set ts=4 sw=4 et: */ /* vim:set ts=4 sw=4 et: */

View File

@ -427,7 +427,7 @@ template <class T>
inline void owner_free(OwningPointer(T)(&object)) noexcept { inline void owner_free(OwningPointer(T)(&object)) noexcept {
static_assert(!std::is_class_v<T>); // UPX convention static_assert(!std::is_class_v<T>); // UPX convention
if (object != nullptr) { if (object != nullptr) {
free((T *) object); ::free((T *) object);
object = nullptr; object = nullptr;
} }
assert_noexcept((T *) object == nullptr); assert_noexcept((T *) object == nullptr);

View File

@ -128,7 +128,7 @@ int upx_safe_vasprintf(char **ptr, const char *format, va_list ap) {
va_end(ap_copy); va_end(ap_copy);
if (len >= 0) { if (len >= 0) {
*ptr = (char *) malloc(len + 1); *ptr = (char *) ::malloc(len + 1);
assert(*ptr != nullptr); assert(*ptr != nullptr);
if (*ptr == nullptr) if (*ptr == nullptr)
return -1; return -1;

View File

@ -55,7 +55,7 @@
#if DEBUG #if DEBUG
#define _LIBCPP_ENABLE_ASSERTIONS 1 #define _LIBCPP_ENABLE_ASSERTIONS 1
#endif #endif
#endif #endif // clang >= 18
#endif // TODO later #endif // TODO later
/* vim:set ts=4 sw=4 et: */ /* vim:set ts=4 sw=4 et: */

View File

@ -254,17 +254,19 @@ TEST_CASE("ptr_check_no_overlap 3") {
// stdlib // stdlib
**************************************************************************/ **************************************************************************/
int upx_rand(void) noexcept { return ::rand(); }
void *upx_calloc(size_t n, size_t element_size) may_throw { void *upx_calloc(size_t n, size_t element_size) may_throw {
size_t bytes = mem_size(element_size, n); // assert size size_t bytes = mem_size(element_size, n); // assert size
void *p = malloc(bytes); void *p = ::malloc(bytes);
if (p != nullptr) if (p != nullptr)
memset(p, 0, bytes); memset(p, 0, bytes);
return p; return p;
} }
// simple unoptimized memswap() // simple unoptimized memswap()
void upx_memswap(void *a, void *b, size_t n) noexcept { void upx_memswap(void *a, void *b, size_t bytes) noexcept {
if (a != b && n != 0) { if (a != b && bytes != 0) {
byte *x = (byte *) a; byte *x = (byte *) a;
byte *y = (byte *) b; byte *y = (byte *) b;
do { do {
@ -273,16 +275,16 @@ void upx_memswap(void *a, void *b, size_t n) noexcept {
byte tmp = *x; // NOLINT(*core.uninitialized.Assign) // bogus clang-analyzer warning byte tmp = *x; // NOLINT(*core.uninitialized.Assign) // bogus clang-analyzer warning
*x++ = *y; *x++ = *y;
*y++ = tmp; *y++ = tmp;
} while (--n != 0); } while (--bytes != 0);
} }
} }
// much better memswap(), optimized for our use case in sort functions below // much better memswap(), optimized for our use case in sort functions below
static void memswap_no_overlap(byte *a, byte *b, size_t n) noexcept { static inline void memswap_no_overlap(byte *a, byte *b, size_t bytes) noexcept {
#if defined(__clang__) && __clang_major__ < 15 #if defined(__clang__) && __clang_major__ < 15
// work around a clang < 15 ICE (Internal Compiler Error) // work around a clang < 15 ICE (Internal Compiler Error)
// @COMPILER_BUG @CLANG_BUG // @COMPILER_BUG @CLANG_BUG
upx_memswap(a, b, n); upx_memswap(a, b, bytes);
#else // clang bug #else // clang bug
upx_alignas_max byte tmp_buf[16]; upx_alignas_max byte tmp_buf[16];
#define SWAP(x) \ #define SWAP(x) \
@ -294,15 +296,15 @@ static void memswap_no_overlap(byte *a, byte *b, size_t n) noexcept {
b += x; \ b += x; \
} while (0) } while (0)
for (; n >= 16; n -= 16) for (; bytes >= 16; bytes -= 16)
SWAP(16); SWAP(16);
if (n & 8) if (bytes & 8)
SWAP(8); SWAP(8);
if (n & 4) if (bytes & 4)
SWAP(4); SWAP(4);
if (n & 2) if (bytes & 2)
SWAP(2); SWAP(2);
if (n & 1) { if (bytes & 1) {
byte tmp = *a; byte tmp = *a;
*a = *b; *a = *b;
*b = tmp; *b = tmp;
@ -347,7 +349,7 @@ void upx_shellsort_memcpy(void *array, size_t n, size_t element_size, upx_compar
upx_alignas_max byte tmp_buf[MAX_INLINE_ELEMENT_SIZE]; // buffer for one element upx_alignas_max byte tmp_buf[MAX_INLINE_ELEMENT_SIZE]; // buffer for one element
byte *tmp = tmp_buf; byte *tmp = tmp_buf;
if (element_size > MAX_INLINE_ELEMENT_SIZE) { if (element_size > MAX_INLINE_ELEMENT_SIZE) {
tmp = (byte *) malloc(element_size); tmp = (byte *) ::malloc(element_size);
assert(tmp != nullptr); assert(tmp != nullptr);
} }
size_t gap = 0; // 0, 1, 4, 13, 40, 121, 364, 1093, ... size_t gap = 0; // 0, 1, 4, 13, 40, 121, 364, 1093, ...
@ -368,7 +370,7 @@ void upx_shellsort_memcpy(void *array, size_t n, size_t element_size, upx_compar
} }
} }
if (element_size > MAX_INLINE_ELEMENT_SIZE) if (element_size > MAX_INLINE_ELEMENT_SIZE)
free(tmp); ::free(tmp);
} }
// wrap std::stable_sort() // wrap std::stable_sort()
@ -391,9 +393,10 @@ void upx_std_stable_sort(void *array, size_t n, upx_compare_func_t compare) {
} }
#if UPX_CONFIG_USE_STABLE_SORT #if UPX_CONFIG_USE_STABLE_SORT
// instantiate function templates for all element sizes we need; efficient run time, but code size // instantiate function templates for all element sizes we need; efficient
// bloat (about 4KiB code size for each function with my current libstdc++); not really needed as // run-time, but code size bloat (about 4KiB code size for each function
// libc qsort() is good enough for our use cases // 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<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<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<4>(void *, size_t, upx_compare_func_t);
@ -405,7 +408,7 @@ 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); template void upx_std_stable_sort<72>(void *, size_t, upx_compare_func_t);
#endif #endif
#if !defined(DOCTEST_CONFIG_DISABLE) && DEBUG >= 1 #if !defined(DOCTEST_CONFIG_DISABLE) && DEBUG
#if __cplusplus >= 202002L // use C++20 std::next_permutation() to test all permutations #if __cplusplus >= 202002L // use C++20 std::next_permutation() to test all permutations
namespace { namespace {
template <class ElementType, upx_compare_func_t CompareFunc> template <class ElementType, upx_compare_func_t CompareFunc>
@ -588,7 +591,7 @@ int find(const void *buf, int blen, const void *what, int wlen) noexcept {
return -1; return -1;
const byte *b = (const byte *) buf; const byte *b = (const byte *) buf;
byte first_byte = *(const byte *) what; const byte first_byte = *(const byte *) what;
blen -= wlen; blen -= wlen;
for (int i = 0; i <= blen; i++, b++) for (int i = 0; i <= blen; i++, b++)
@ -769,8 +772,8 @@ int fn_strcmp(const char *n1, const char *n2) {
// misc // misc
**************************************************************************/ **************************************************************************/
// UPX convention: any environment variable that is set and is not strictly equal to "0" is true
bool is_envvar_true(const char *envvar, const char *alternate_name) noexcept { bool is_envvar_true(const char *envvar, const char *alternate_name) noexcept {
// UPX convention: any environment variable that is set and is not strictly equal to "0" is true
const char *e = getenv(envvar); const char *e = getenv(envvar);
if (e != nullptr && e[0]) if (e != nullptr && e[0])
return strcmp(e, "0") != 0; return strcmp(e, "0") != 0;

View File

@ -143,9 +143,11 @@ inline void ptr_invalidate_and_poison(T *(&ptr)) noexcept {
// stdlib // stdlib
**************************************************************************/ **************************************************************************/
void *upx_calloc(size_t n, size_t element_size) may_throw; noinline void *upx_calloc(size_t n, size_t element_size) may_throw;
void upx_memswap(void *a, void *b, size_t n) noexcept; void upx_memswap(void *a, void *b, size_t bytes) noexcept;
noinline int upx_rand(void) noexcept;
typedef int(__acc_cdecl_qsort *upx_compare_func_t)(const void *, const void *); 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); typedef void (*upx_sort_func_t)(void *array, size_t n, size_t element_size, upx_compare_func_t);
@ -165,7 +167,7 @@ void upx_std_stable_sort(void *array, size_t n, upx_compare_func_t compare);
upx_std_stable_sort<(element_size)>((a), (n), (compare)) upx_std_stable_sort<(element_size)>((a), (n), (compare))
#else #else
// use libc qsort(); good enough for our use cases // use libc qsort(); good enough for our use cases
#define upx_qsort qsort #define upx_qsort ::qsort
#endif #endif
/************************************************************************* /*************************************************************************

View File

@ -30,7 +30,7 @@
// of class PackerBase which then does the actual work. // of class PackerBase which then does the actual work.
// And see p_com.cpp for a simple executable format. // And see p_com.cpp for a simple executable format.
// //
// This file also has the burden to deal with all those pesky low-level // And this file also has the burden to deal with all those pesky low-level
// file handling issues. // file handling issues.
#define WANT_WINDOWS_LEAN_H 1 // _get_osfhandle, GetFileTime, SetFileTime #define WANT_WINDOWS_LEAN_H 1 // _get_osfhandle, GetFileTime, SetFileTime
@ -47,7 +47,7 @@
#include "util/membuffer.h" #include "util/membuffer.h"
#if USE_UTIMENSAT && defined(AT_FDCWD) #if USE_UTIMENSAT && defined(AT_FDCWD)
#elif (defined(_WIN32) || defined(__CYGWIN__)) && 1 #elif defined(_WIN32) || defined(__CYGWIN__)
#define USE_SETFILETIME 1 #define USE_SETFILETIME 1
#elif (ACC_OS_DOS32) && defined(__DJGPP__) #elif (ACC_OS_DOS32) && defined(__DJGPP__)
#define USE_FTIME 1 #define USE_FTIME 1