CI updates

This commit is contained in:
Markus F.X.J. Oberhumer 2025-12-10 10:15:51 +01:00
parent 8622e22be0
commit 190fd76583
12 changed files with 126 additions and 45 deletions

View File

@ -633,9 +633,9 @@ jobs:
- { zig_target: x86_64-windows-gnu }
name: ${{ format('zigcc {0} {1}', matrix.zig_target, matrix.zig_pic) }}
runs-on: ubuntu-latest
container: ${{ matrix.container || 'alpine:3.22' }}
container: ${{ matrix.container || 'alpine:3.23' }}
env:
container: ${{ matrix.container || 'alpine:3.22' }}
container: ${{ matrix.container || 'alpine:3.23' }}
UPX_CONFIG_HAVE_WORKING_BUILD_RPATH: ''
# for zig-cc wrapper scripts (see below):
ZIG_CPPFLAGS: -DUPX_DOCTEST_CONFIG_MULTITHREADING

View File

@ -878,7 +878,7 @@ TEST_CASE("PtrOrSpan int") {
namespace {
template <class T>
static noinline void check_bele(const T &mb, size_t i) {
static noinline void check_bele_a(const T &mb, size_t i) {
if (i < 2) {
CHECK_THROWS(get_ne16(mb));
CHECK_THROWS(get_be16(mb));
@ -940,32 +940,95 @@ static noinline void check_bele(const T &mb, size_t i) {
CHECK_NOTHROW(set_le64(mb, 0));
}
}
template <class T>
static noinline void check_bele_c(const T &mb, size_t i) {
if (i < 2) {
CHECK_THROWS(get_ne16(mb));
CHECK_THROWS(get_be16(mb));
CHECK_THROWS(get_le16(mb));
} else {
CHECK_NOTHROW(get_ne16(mb));
CHECK_NOTHROW(get_be16(mb));
CHECK_NOTHROW(get_le16(mb));
}
if (i < 3) {
CHECK_THROWS(get_ne24(mb));
CHECK_THROWS(get_be24(mb));
CHECK_THROWS(get_le24(mb));
} else {
CHECK_NOTHROW(get_ne24(mb));
CHECK_NOTHROW(get_be24(mb));
CHECK_NOTHROW(get_le24(mb));
}
if (i < 4) {
CHECK_THROWS(get_ne32(mb));
CHECK_THROWS(get_be32(mb));
CHECK_THROWS(get_le32(mb));
} else {
CHECK_NOTHROW(get_ne32(mb));
CHECK_NOTHROW(get_be32(mb));
CHECK_NOTHROW(get_le32(mb));
}
if (i < 8) {
CHECK_THROWS(get_ne64(mb));
CHECK_THROWS(get_be64(mb));
CHECK_THROWS(get_le64(mb));
} else {
CHECK_NOTHROW(get_ne64(mb));
CHECK_NOTHROW(get_be64(mb));
CHECK_NOTHROW(get_le64(mb));
}
}
} // namespace
#endif // UPX_VERSION_HEX
TEST_CASE("xspan global overloads") {
byte buf[16] = {};
byte buf_a[16] = {};
const byte buf_c[16] = {};
for (size_t i = 0; i < 16; i++) {
XSPAN_0_VAR(byte, a0, buf, i);
XSPAN_P_VAR(byte, ap, buf, i);
XSPAN_S_VAR(byte, as, buf, i);
XSPAN_0_VAR(byte, a0, buf_a, i);
XSPAN_P_VAR(byte, ap, buf_a, i);
XSPAN_S_VAR(byte, as, buf_a, i);
XSPAN_0_VAR(const byte, c0, buf_c, i);
XSPAN_P_VAR(const byte, cp, buf_c, i);
XSPAN_S_VAR(const byte, cs, buf_c, i);
#ifdef UPX_VERSION_HEX
check_bele(a0, i);
check_bele(ap, i);
check_bele(as, i);
check_bele_a(a0, i);
check_bele_a(ap, i);
check_bele_a(as, i);
check_bele_c(c0, i);
check_bele_c(cp, i);
check_bele_c(cs, i);
CHECK_THROWS(upx_adler32(a0, i + 1));
CHECK_THROWS(upx_adler32(ap, i + 1));
CHECK_THROWS(upx_adler32(as, i + 1));
CHECK_THROWS(upx_adler32(c0, i + 1));
CHECK_THROWS(upx_adler32(cp, i + 1));
CHECK_THROWS(upx_adler32(cs, i + 1));
if (i == 0) {
CHECK_THROWS(upx_safe_strlen(a0));
CHECK_THROWS(upx_safe_strlen(ap));
CHECK_THROWS(upx_safe_strlen(as));
CHECK_THROWS(upx_safe_strlen(c0));
CHECK_THROWS(upx_safe_strlen(cp));
CHECK_THROWS(upx_safe_strlen(cs));
}
#endif
CHECK_THROWS(memchr(a0, 0, i + 1)); // NOLINT(bugprone-unused-return-value)
CHECK_THROWS(memchr(ap, 0, i + 1)); // NOLINT(bugprone-unused-return-value)
CHECK_THROWS(memchr(as, 0, i + 1)); // NOLINT(bugprone-unused-return-value)
CHECK_THROWS(memchr(c0, 0, i + 1)); // NOLINT(bugprone-unused-return-value)
CHECK_THROWS(memchr(cp, 0, i + 1)); // NOLINT(bugprone-unused-return-value)
CHECK_THROWS(memchr(cs, 0, i + 1)); // NOLINT(bugprone-unused-return-value)
CHECK(memcmp(a0, a0, i) == 0);
CHECK(memcmp(ap, a0, i) == 0);
CHECK(memcmp(as, a0, i) == 0);
@ -973,6 +1036,20 @@ TEST_CASE("xspan global overloads") {
CHECK_THROWS(memcmp(ap, a0, i + 1)); // NOLINT(bugprone-unused-return-value)
CHECK_THROWS(memcmp(as, a0, i + 1)); // NOLINT(bugprone-unused-return-value)
CHECK_NOTHROW(memcpy(a0, c0, i));
CHECK_NOTHROW(memcpy(ap, cp, i));
CHECK_NOTHROW(memcpy(as, cs, i));
CHECK_THROWS(memcpy(a0, c0, i + 1));
CHECK_THROWS(memcpy(ap, cp, i + 1));
CHECK_THROWS(memcpy(as, cs, i + 1));
CHECK_NOTHROW(memmove(a0, c0, i));
CHECK_NOTHROW(memmove(ap, cp, i));
CHECK_NOTHROW(memmove(as, cs, i));
CHECK_THROWS(memmove(a0, c0, i + 1));
CHECK_THROWS(memmove(ap, cp, i + 1));
CHECK_THROWS(memmove(as, cs, i + 1));
CHECK_NOTHROW(memset(a0, 255, i));
CHECK_NOTHROW(memset(ap, 255, i));
CHECK_NOTHROW(memset(as, 255, i));

View File

@ -377,6 +377,7 @@ inline void NO_printf(const char *, ...) noexcept {}
inline void NO_fprintf(FILE *, const char *, ...) noexcept attribute_format(2, 3);
inline void NO_fprintf(FILE *, const char *, ...) noexcept {}
// upx_memcmp_inline
#if __has_builtin(__builtin_memcmp)
#define upx_memcmp_inline __builtin_memcmp
#elif defined(__clang__) || defined(__GNUC__)
@ -384,6 +385,8 @@ inline void NO_fprintf(FILE *, const char *, ...) noexcept {}
#else
#define upx_memcmp_inline memcmp
#endif
// upx_memcpy_inline
#if __has_builtin(__builtin_memcpy_inline) && 0 // TODO later: clang constexpr limitation?
#define upx_memcpy_inline __builtin_memcpy_inline
#elif __has_builtin(__builtin_memcpy)
@ -394,6 +397,7 @@ inline void NO_fprintf(FILE *, const char *, ...) noexcept {}
#define upx_memcpy_inline memcpy
#endif
// upx_return_address()
#if defined(__wasi__)
#define upx_return_address() nullptr
#elif __has_builtin(__builtin_return_address)
@ -803,7 +807,8 @@ int upx_doctest_check();
// util/membuffer.h
class MemBuffer;
void *membuffer_get_void_ptr(MemBuffer &mb) noexcept;
unsigned membuffer_get_size_in_bytes(MemBuffer &mb) noexcept;
const void *membuffer_get_void_ptr(const MemBuffer &mb) noexcept;
unsigned membuffer_get_size_in_bytes(const MemBuffer &mb) noexcept;
// main.cpp
extern const char *progname;

View File

@ -49,7 +49,7 @@ const char gitrev[] = UPX_VERSION_GITREV;
const char gitrev[1] = {0};
#endif
void show_header(void) {
void show_header() {
FILE *f = con_term;
int fg;
@ -85,7 +85,7 @@ void show_header(void) {
// usage
**************************************************************************/
void show_usage(void) {
void show_usage() {
FILE *f = con_term;
con_fprintf(f, "Usage: %s [-123456789dlthVL] [-qvfk] [-o file] %sfile..\n", progname,
@ -381,7 +381,7 @@ void show_help(int verbose) {
// license
**************************************************************************/
void show_license(void) {
void show_license() {
FILE *f = con_term;
show_header();

View File

@ -367,6 +367,8 @@ int ElfLinker::addLoader(const char *sname) {
return outputlen;
char *begin = strdup(sname);
assert(begin != nullptr);
auto begin_deleter = upx::MallocDeleter(&begin, 1);
char *end = begin + strlen(begin);
for (char *sect = begin; sect < end;) {
for (char *tokend = sect; *tokend; tokend++)
@ -418,7 +420,6 @@ int ElfLinker::addLoader(const char *sname) {
}
sect += strlen(sect) + 1;
}
::free(begin);
return outputlen;
}

View File

@ -67,12 +67,9 @@ static void handle_opterr(acc_getopt_p g, const char *f, void *v) {
static int exit_code = EXIT_OK;
#if (WITH_GUI)
static noinline void do_exit(void) { throw exit_code; }
static noreturn void do_exit() { throw exit_code; }
#else
#if defined(__GNUC__)
static void do_exit(void) __attribute__((__noreturn__));
#endif
static void do_exit(void) {
static noreturn void do_exit() {
static bool in_exit = false;
if (in_exit)
@ -115,7 +112,7 @@ static noinline void e_exit(int ec) {
do_exit();
}
static noinline void e_usage(void) {
static noinline void e_usage() {
if (opt->debug.getopt_throw_instead_of_exit)
throw EXIT_USAGE;
show_usage();
@ -217,7 +214,7 @@ static void check_and_update_options(int i, int argc) {
// misc
**************************************************************************/
static void e_help(void) {
static void e_help() {
show_help(0);
e_exit(EXIT_USAGE);
}

View File

@ -260,7 +260,7 @@ protected:
// permissive version using "void *"
inline unsigned get_te16(const void *p) const noexcept { return bele->get16(p); }
inline unsigned get_te32(const void *p) const noexcept { return bele->get32(p); }
inline unsigned get_te64_32(const void *p) const { return (unsigned) bele->get64(p); }
inline unsigned get_te64_32(const void *p) const may_throw { return (unsigned) bele->get64(p); }
inline upx_uint64_t get_te64(const void *p) const noexcept { return bele->get64(p); }
inline void set_te16(void *p, unsigned v) noexcept { bele->set16(p, v); }
inline void set_te32(void *p, unsigned v) noexcept { bele->set32(p, v); }
@ -293,7 +293,7 @@ protected:
return bele->get32(p);
}
template <class T, class = enable_if_te64<T> >
inline unsigned get_te64_32(const T *p) const {
inline unsigned get_te64_32(const T *p) const may_throw {
upx_uint64_t v = bele->get64(p);
if ((v >> 32) != 0)
throwCantPack("64-bit value too big %#llx", v);

View File

@ -33,7 +33,8 @@
// extra functions to reduce dependency on membuffer.h
void *membuffer_get_void_ptr(MemBuffer &mb) noexcept { return mb.getVoidPtr(); }
unsigned membuffer_get_size_in_bytes(MemBuffer &mb) noexcept { return mb.getSizeInBytes(); }
const void *membuffer_get_void_ptr(const MemBuffer &mb) noexcept { return mb.getVoidPtr(); }
unsigned membuffer_get_size_in_bytes(const MemBuffer &mb) noexcept { return mb.getSizeInBytes(); }
/*static*/ MemBuffer::Stats MemBuffer::stats;
@ -169,7 +170,7 @@ void MemBuffer::checkState() const may_throw {
}
}
void MemBuffer::alloc(upx_uint64_t bytes) may_throw {
void MemBuffer::alloc(const upx_uint64_t bytes) may_throw {
// INFO: we don't automatically free a used buffer
assert(ptr == nullptr);
assert(size_in_bytes == 0);
@ -185,7 +186,7 @@ void MemBuffer::alloc(upx_uint64_t bytes) may_throw {
NO_printf("MemBuffer::alloc %llu: %p\n", bytes, p);
if (!p)
throwOutOfMemoryException();
size_in_bytes = ACC_ICONV(unsigned, bytes);
size_in_bytes = size_type(bytes);
if (use_simple_mcheck()) {
p += 16;
// store magic constants to detect buffer overruns
@ -323,6 +324,7 @@ TEST_CASE("MemBuffer global overloads") {
for (size_t i = 1; i <= 16; i++) {
MemBuffer mb(i);
mb.clear();
if (i < 2) {
CHECK_THROWS(get_ne16(mb));
CHECK_THROWS(get_be16(mb));

View File

@ -62,7 +62,7 @@ public:
// array access
reference operator[](ptrdiff_t i) const may_throw {
// NOTE: &array[SIZE] is *not* legal for containers like std::vector and MemBuffer !
if very_unlikely (i < 0 || mem_size(element_size, i) + element_size > size_in_bytes)
if very_unlikely (i < 0 || mem_size(element_size, i) >= size_in_bytes)
throwCantPack("MemBuffer invalid array index %td (%zu bytes)", i, size_in_bytes);
return ptr[i];
}
@ -169,8 +169,8 @@ inline typename MemBufferBase<T>::pointer raw_index_bytes(const MemBufferBase<T>
#define XSPAN_REQUIRES_CONVERTIBLE_ANY_DIRECTION(A, B, RType) \
typename std::enable_if<std::is_same<A, B>::value, RType>::type
#endif
#define C MemBufferBase
#define XSPAN_FWD_C_IS_MEMBUFFER 1
#define C MemBufferBase
#if WITH_XSPAN >= 1
#define D XSPAN_NS(Ptr)
#endif
@ -198,8 +198,8 @@ public:
void allocForCompression(unsigned uncompressed_size, unsigned extra = 0) may_throw;
void allocForDecompression(unsigned uncompressed_size, unsigned extra = 0) may_throw;
noinline void dealloc() noexcept;
noinline void checkState() const may_throw;
noinline void dealloc() noexcept;
// explicit conversion
void *getVoidPtr() noexcept { return (void *) ptr; }

View File

@ -121,18 +121,17 @@ forceinline bool ptr_is_aligned(const void *p, size_t alignment) noexcept {
// ptrdiff_t with nullptr checks and asserted size; will throw on failure
// NOTE: returns size_in_bytes, not number of elements!
int ptr_diff_bytes(const void *a, const void *b) may_throw;
unsigned ptr_udiff_bytes(const void *a, const void *b) may_throw; // asserts a >= b
noinline int ptr_diff_bytes(const void *a, const void *b) may_throw;
noinline unsigned ptr_udiff_bytes(const void *a, const void *b) may_throw; // asserts a >= b
// short names "ptr_diff" and "ptr_udiff" for types with sizeof(X) == 1
template <class T, class U>
inline typename std::enable_if<sizeof(T) == 1 && sizeof(U) == 1, int>::type ptr_diff(const T *a,
const U *b)
may_throw {
forceinline typename std::enable_if<sizeof(T) == 1 && sizeof(U) == 1, int>::type
ptr_diff(const T *a, const U *b) may_throw {
return ptr_diff_bytes(a, b);
}
template <class T, class U>
inline typename std::enable_if<sizeof(T) == 1 && sizeof(U) == 1, unsigned>::type
forceinline typename std::enable_if<sizeof(T) == 1 && sizeof(U) == 1, unsigned>::type
ptr_udiff(const T *a, const U *b) may_throw {
return ptr_udiff_bytes(a, b);
}
@ -229,7 +228,7 @@ bool maketempname(char *ofilename, size_t size, const char *ifilename, const cha
bool force = true);
bool makebakname(char *ofilename, size_t size, const char *ifilename, bool force = true);
bool is_envvar_true(const char *envvar, const char *alternate_name = nullptr) noexcept;
noinline bool is_envvar_true(const char *envvar, const char *alternate_name = nullptr) noexcept;
unsigned get_ratio(upx_uint64_t u_len, upx_uint64_t c_len);
bool set_method_name(char *buf, size_t size, int method, int level);

View File

@ -44,33 +44,33 @@ struct XSpanStats {
static XSpanStats xspan_stats;
// HINT: set env-var "UPX_DEBUG_DOCTEST_DISABLE=1" for improved debugging experience
void xspan_fail_nullptr() {
void xspan_fail_nullptr() may_throw {
xspan_stats.fail_nullptr += 1;
throwCantPack("xspan unexpected NULL pointer; take care!");
}
void xspan_fail_nullbase() {
void xspan_fail_nullbase() may_throw {
xspan_stats.fail_nullbase += 1;
throwCantPack("xspan unexpected NULL base; take care!");
}
void xspan_fail_not_same_base() {
void xspan_fail_not_same_base() may_throw {
xspan_stats.fail_not_same_base += 1;
throwCantPack("xspan unexpected base pointer; take care!");
}
void xspan_fail_range_nullptr() {
void xspan_fail_range_nullptr() may_throw {
xspan_stats.fail_range_nullptr += 1;
throwCantPack("xspan_check_range: unexpected NULL pointer; take care!");
}
void xspan_fail_range_nullbase() {
void xspan_fail_range_nullbase() may_throw {
xspan_stats.fail_range_nullbase += 1;
throwCantPack("xspan_check_range: unexpected NULL base; take care!");
}
void xspan_fail_range_range() {
void xspan_fail_range_range() may_throw {
xspan_stats.fail_range_range += 1;
throwCantPack("xspan_check_range: pointer out of range; take care!");
}
void xspan_check_range(const void *ptr, const void *base, ptrdiff_t size_in_bytes) {
void xspan_check_range(const void *ptr, const void *base, ptrdiff_t size_in_bytes) may_throw {
xspan_stats.check_range_counter += 1;
if very_unlikely (ptr == nullptr)
xspan_fail_range_nullptr();