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
# 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

View File

@ -16,8 +16,9 @@ env:
UPX_CMAKE_BUILD_FLAGS: --verbose
UPX_CMAKE_CONFIG_FLAGS: -Wdev --warn-uninitialized
UPX_DEBUG_TEST_FLOAT_DIVISION_BY_ZERO: 1
# 2024-03-29
ZIG_DIST_VERSION: 0.12.0-dev.3484+7aa42f47b
UPX_DEBUG_TEST_LIBC_QSORT: 1
# 2024-04-01
ZIG_DIST_VERSION: 0.12.0-dev.3508+a6ed3e6d2
jobs:
job-rebuild-and-verify-stubs:
@ -183,7 +184,7 @@ jobs:
job-macos-cmake: # uses cmake + make
if: true
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 }}
strategy:
fail-fast: false
@ -193,8 +194,8 @@ jobs:
# 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-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, 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, 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
@ -465,16 +466,18 @@ jobs:
- { zig_target: aarch64-windows-gnu }
- { zig_target: arm-linux-musleabihf, qemu: qemu-arm }
# { zig_target: arm-linux-musleabihf, qemu: qemu-arm, zig_pic: -fPIE }
- { zig_target: i386-linux-musl, qemu: qemu-i386 }
# { zig_target: i386-linux-musl, qemu: qemu-i386, zig_pic: -fPIE }
- { zig_target: i386-linux-gnu.2.3.4, zig_flags: -march=i586 }
- { 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 }
# 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: mipsel-linux-musl, zig_flags: -msoft-float, qemu: qemu-mipsel }
- { 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: 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_pic: -fPIE }
# { zig_target: x86_64-macos-none }

View File

@ -516,7 +516,7 @@ if(Threads_FOUND)
elseif(UPX_CONFIG_REQUIRE_THREADS)
message(FATAL_ERROR "ERROR: WITH_THREADS required")
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()
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\"")

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 $$@)
# OLD names [deprecated]
build/extra/scan-build/debug: build/analyze/clang-analyzer/debug
build/extra/scan-build/release: build/analyze/clang-analyzer/release
build/extra/scan-build/debug: build/analyze/clang-analyzer/debug PHONY
build/extra/scan-build/release: build/analyze/clang-analyzer/release PHONY
#***********************************************************************
# 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
# OLD target names [deprecated]
$(top_srcdir)/build/debug: build/debug PHONY
$(top_srcdir)/build/release: build/release PHONY
#***********************************************************************
# make run-testsuite
# 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
**************************************************************************/
// 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
#define TT_UPX_IS_INTEGRAL(T) \
template <> \
@ -826,26 +846,6 @@ typedef LE64 NE64;
#define ne64_compare_signed le64_compare_signed
#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.
//

View File

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

View File

@ -24,6 +24,9 @@
<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 <cmath> // std::isinf std::isnan
#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 sub_div_x(Int a, Int b) { return Float(a - b) / Float(X); }
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, X) == Float(2));
assert_noexcept(sub_div(3 * X, X, Float(X)) == Float(2));
@ -391,6 +395,7 @@ struct TestFloat {
#else
assert_noexcept(std::isnan(div(0, Float(0))));
assert_noexcept(std::isinf(div(1, Float(0))));
assert_noexcept(std::isinf(div(Int(-1), Float(0))));
#endif
}
}
@ -432,6 +437,19 @@ void upx_compiler_sanity_check(void) noexcept {
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
#undef ACCCHK_ASSERT
#define ACCCHK_ASSERT(expr) ACC_COMPILE_TIME_ASSERT(expr)
@ -646,7 +664,7 @@ void upx_compiler_sanity_check(void) 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 *ptr1 = &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_acc_int64l_t(2, 1), 2);
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") {
int *ip = nullptr;
int *ip = nullptr; // initialized
ptr_invalidate_and_poison(ip);
assert(ip != nullptr);
(void) ip;
@ -751,11 +772,13 @@ TEST_CASE("libc snprintf") {
CHECK_EQ(strcmp(buf, "0X1A 0x1b 0x1c "), 0);
}
#if 0
TEST_CASE("libc qsort") {
// runtime check that libc qsort() never compares identical objects
// UPDATE: while only poor implementations of qsort() would actually do
// this, it is probably allowed by the standard; so skip this test case
// UPDATE: while only poor implementations of qsort() would actually do this
// 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 {
upx_uint16_t id;
upx_uint16_t value;
@ -765,8 +788,8 @@ TEST_CASE("libc qsort") {
assert_noexcept(a->id != b->id); // check not IDENTICAL
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) {
upx_uint32_t x = 5381 + n + ((upx_uintptr_t) e & 0xff);
static noinline bool check_sort(upx_sort_func_t sort, Elem *e, size_t n) {
upx_uint32_t x = 5381 + n + (upx_rand() & 0xff);
for (size_t i = 0; i < n; i++) {
e[i].id = (upx_uint16_t) i;
x = x * 33 + 1 + (i & 255);
@ -782,18 +805,19 @@ TEST_CASE("libc qsort") {
constexpr size_t N = 4096;
Elem e[N];
for (size_t n = 0; n <= N; n = 2 * n + 1) {
// CHECK(Elem::check_sort(qsort, e, n)); // libc qsort()
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));
// system sort functions
CHECK(Elem::check_sort(::qsort, e, n)); // libc qsort()
#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_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
// 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: */

View File

@ -27,24 +27,8 @@
// lots of tests (and probably quite a number of redundant tests)
// 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 <vector>
#include <vector> // std::vector
#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;
std::vector<int> v(N);
CHECK(v.end() - v.begin() == N);
@ -298,7 +282,7 @@ TEST_CASE("upx::ObjectDeleter 2") {
}
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;
void *vp = 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;
#undef off_t
#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
#else
#define off_t upx_off_t
@ -230,12 +230,6 @@ typedef upx_int64_t upx_off_t;
#undef sopen
#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
#define STDIN_FILENO (fileno(stdin))
#endif
@ -338,7 +332,7 @@ typedef upx_int64_t upx_off_t;
// TODO later: check __MINGW_PRINTF_FORMAT
#if defined(_WIN32) && defined(__MINGW32__) && defined(__GNUC__) && !defined(__clang__)
#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)))
#else
#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);
memset((void *) object, 0, size);
}
// disable some overloads
#if defined(__clang__) || __GNUC__ != 7
template <class T>
inline void mem_clear(T (&array)[]) noexcept DELETED_FUNCTION;

View File

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

View File

@ -40,6 +40,7 @@
#else
UNUSED(name);
UNUSED(mode);
// no error
#endif
}
@ -88,7 +89,7 @@ bool FileBase::do_sopen() {
else {
#if (ACC_OS_DOS32) && defined(__DJGPP__)
_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);
#elif defined(SH_DENYRW)
_fd = ::sopen(_name, _flags, _shflags, _mode);
@ -98,6 +99,7 @@ bool FileBase::do_sopen() {
}
if (_fd < 0)
return false;
st.st_size = 0;
if (::fstat(_fd, &st) != 0)
throwIOException(_name, errno);
_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; }
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
**************************************************************************/
@ -333,6 +349,7 @@ void OutputFile::set_extent(upx_off_t offset, upx_off_t length) {
super::set_extent(offset, length);
bytes_written = 0;
if (0 == offset && 0xffffffffLL == length) { // TODO: check all callers of this method
st.st_size = 0;
if (::fstat(_fd, &st) != 0)
throwIOException(_name, errno);
_length = st.st_size - offset;

View File

@ -88,6 +88,8 @@ public:
virtual upx_off_t seek(upx_off_t off, int whence) override;
upx_off_t st_size_orig() const;
noinline int dup() may_throw;
protected:
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 = strdup(n);
assert(name != nullptr);
input = malloc(s + 1);
input = ::malloc(s + 1);
assert(input != nullptr);
if (s != 0) {
assert(i != nullptr);
@ -70,8 +70,8 @@ ElfLinker::Section::Section(const char *n, const void *i, unsigned s, unsigned a
}
ElfLinker::Section::~Section() noexcept {
free(name);
free(input);
::free(name);
::free(input);
}
/*************************************************************************
@ -85,7 +85,7 @@ ElfLinker::Symbol::Symbol(const char *n, Section *s, upx_uint64_t o)
assert(section != nullptr);
}
ElfLinker::Symbol::~Symbol() noexcept { free(name); }
ElfLinker::Symbol::~Symbol() noexcept { ::free(name); }
/*************************************************************************
// Relocation
@ -110,13 +110,13 @@ ElfLinker::~ElfLinker() noexcept {
unsigned ic;
for (ic = 0; ic < nsections; ic++)
delete sections[ic];
free(sections);
::free(sections);
for (ic = 0; ic < nsymbols; ic++)
delete symbols[ic];
free(symbols);
::free(symbols);
for (ic = 0; ic < nrelocations; ic++)
delete relocations[ic];
free(relocations);
::free(relocations);
}
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;
}
free(begin);
::free(begin);
return outputlen;
}

View File

@ -923,7 +923,7 @@ int main_get_options(int argc, char **argv) {
// atari/tos
{"split-segments", 0x90, N, 650},
// 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
{"coff", 0x90, N, 610}, // produce COFF output
// dos/exe
@ -1355,9 +1355,9 @@ int __acc_cdecl_main main(int argc, char *argv[]) /*noexcept*/ {
#endif
acc_wildargv(&argc, &argv);
#if defined(__wasi__)
srand((int) time(nullptr));
::srand((unsigned) time(nullptr));
#else
srand((int) clock());
::srand((unsigned) clock());
#endif
// info: main() is implicitly "noexcept", so we need a try block

View File

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

View File

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

View File

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

View File

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

View File

@ -84,10 +84,14 @@ struct PackHeader final {
// info fields set by Packer::compressWithFilters()
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

View File

@ -59,6 +59,11 @@ private:
// setup local options for each file
Options local_options;
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: */

View File

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

View File

@ -104,6 +104,10 @@ protected:
static unsigned update_u_len;
static unsigned update_fc_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: */

View File

@ -427,7 +427,7 @@ template <class T>
inline void owner_free(OwningPointer(T)(&object)) noexcept {
static_assert(!std::is_class_v<T>); // UPX convention
if (object != nullptr) {
free((T *) object);
::free((T *) object);
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);
if (len >= 0) {
*ptr = (char *) malloc(len + 1);
*ptr = (char *) ::malloc(len + 1);
assert(*ptr != nullptr);
if (*ptr == nullptr)
return -1;

View File

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

View File

@ -254,17 +254,19 @@ TEST_CASE("ptr_check_no_overlap 3") {
// stdlib
**************************************************************************/
int upx_rand(void) noexcept { return ::rand(); }
void *upx_calloc(size_t n, size_t element_size) may_throw {
size_t bytes = mem_size(element_size, n); // assert size
void *p = malloc(bytes);
void *p = ::malloc(bytes);
if (p != nullptr)
memset(p, 0, bytes);
return p;
}
// simple unoptimized memswap()
void upx_memswap(void *a, void *b, size_t n) noexcept {
if (a != b && n != 0) {
void upx_memswap(void *a, void *b, size_t bytes) noexcept {
if (a != b && bytes != 0) {
byte *x = (byte *) a;
byte *y = (byte *) b;
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
*x++ = *y;
*y++ = tmp;
} while (--n != 0);
} while (--bytes != 0);
}
}
// 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
// work around a clang < 15 ICE (Internal Compiler Error)
// @COMPILER_BUG @CLANG_BUG
upx_memswap(a, b, n);
upx_memswap(a, b, bytes);
#else // clang bug
upx_alignas_max byte tmp_buf[16];
#define SWAP(x) \
@ -294,15 +296,15 @@ static void memswap_no_overlap(byte *a, byte *b, size_t n) noexcept {
b += x; \
} while (0)
for (; n >= 16; n -= 16)
for (; bytes >= 16; bytes -= 16)
SWAP(16);
if (n & 8)
if (bytes & 8)
SWAP(8);
if (n & 4)
if (bytes & 4)
SWAP(4);
if (n & 2)
if (bytes & 2)
SWAP(2);
if (n & 1) {
if (bytes & 1) {
byte tmp = *a;
*a = *b;
*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
byte *tmp = tmp_buf;
if (element_size > MAX_INLINE_ELEMENT_SIZE) {
tmp = (byte *) malloc(element_size);
tmp = (byte *) ::malloc(element_size);
assert(tmp != nullptr);
}
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)
free(tmp);
::free(tmp);
}
// 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
// instantiate function templates for all element sizes we need; efficient run time, but code size
// bloat (about 4KiB code size for each function with my current libstdc++); not really needed as
// libc qsort() is good enough for our use cases
// instantiate function templates for all element sizes we need; efficient
// run-time, but code size bloat (about 4KiB code size for each function
// 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<2>(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);
#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
namespace {
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;
const byte *b = (const byte *) buf;
byte first_byte = *(const byte *) what;
const byte first_byte = *(const byte *) what;
blen -= wlen;
for (int i = 0; i <= blen; i++, b++)
@ -769,8 +772,8 @@ int fn_strcmp(const char *n1, const char *n2) {
// 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 {
// UPX convention: any environment variable that is set and is not strictly equal to "0" is true
const char *e = getenv(envvar);
if (e != nullptr && e[0])
return strcmp(e, "0") != 0;

View File

@ -143,9 +143,11 @@ inline void ptr_invalidate_and_poison(T *(&ptr)) noexcept {
// 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 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))
#else
// use libc qsort(); good enough for our use cases
#define upx_qsort qsort
#define upx_qsort ::qsort
#endif
/*************************************************************************

View File

@ -30,7 +30,7 @@
// of class PackerBase which then does the actual work.
// 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.
#define WANT_WINDOWS_LEAN_H 1 // _get_osfhandle, GetFileTime, SetFileTime
@ -47,7 +47,7 @@
#include "util/membuffer.h"
#if USE_UTIMENSAT && defined(AT_FDCWD)
#elif (defined(_WIN32) || defined(__CYGWIN__)) && 1
#elif defined(_WIN32) || defined(__CYGWIN__)
#define USE_SETFILETIME 1
#elif (ACC_OS_DOS32) && defined(__DJGPP__)
#define USE_FTIME 1