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 } - { zig_target: x86_64-windows-gnu }
name: ${{ format('zigcc {0} {1}', matrix.zig_target, matrix.zig_pic) }} name: ${{ format('zigcc {0} {1}', matrix.zig_target, matrix.zig_pic) }}
runs-on: ubuntu-latest runs-on: ubuntu-latest
container: ${{ matrix.container || 'alpine:3.22' }} container: ${{ matrix.container || 'alpine:3.23' }}
env: env:
container: ${{ matrix.container || 'alpine:3.22' }} container: ${{ matrix.container || 'alpine:3.23' }}
UPX_CONFIG_HAVE_WORKING_BUILD_RPATH: '' UPX_CONFIG_HAVE_WORKING_BUILD_RPATH: ''
# for zig-cc wrapper scripts (see below): # for zig-cc wrapper scripts (see below):
ZIG_CPPFLAGS: -DUPX_DOCTEST_CONFIG_MULTITHREADING ZIG_CPPFLAGS: -DUPX_DOCTEST_CONFIG_MULTITHREADING

View File

@ -878,7 +878,7 @@ TEST_CASE("PtrOrSpan int") {
namespace { namespace {
template <class T> 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) { if (i < 2) {
CHECK_THROWS(get_ne16(mb)); CHECK_THROWS(get_ne16(mb));
CHECK_THROWS(get_be16(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)); 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 } // namespace
#endif // UPX_VERSION_HEX #endif // UPX_VERSION_HEX
TEST_CASE("xspan global overloads") { 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++) { for (size_t i = 0; i < 16; i++) {
XSPAN_0_VAR(byte, a0, buf, i); XSPAN_0_VAR(byte, a0, buf_a, i);
XSPAN_P_VAR(byte, ap, buf, i); XSPAN_P_VAR(byte, ap, buf_a, i);
XSPAN_S_VAR(byte, as, buf, 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 #ifdef UPX_VERSION_HEX
check_bele(a0, i); check_bele_a(a0, i);
check_bele(ap, i); check_bele_a(ap, i);
check_bele(as, 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(a0, i + 1));
CHECK_THROWS(upx_adler32(ap, i + 1)); CHECK_THROWS(upx_adler32(ap, i + 1));
CHECK_THROWS(upx_adler32(as, 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) { if (i == 0) {
CHECK_THROWS(upx_safe_strlen(a0)); CHECK_THROWS(upx_safe_strlen(a0));
CHECK_THROWS(upx_safe_strlen(ap)); CHECK_THROWS(upx_safe_strlen(ap));
CHECK_THROWS(upx_safe_strlen(as)); 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 #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(a0, a0, i) == 0);
CHECK(memcmp(ap, a0, i) == 0); CHECK(memcmp(ap, a0, i) == 0);
CHECK(memcmp(as, 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(ap, a0, i + 1)); // NOLINT(bugprone-unused-return-value)
CHECK_THROWS(memcmp(as, 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(a0, 255, i));
CHECK_NOTHROW(memset(ap, 255, i)); CHECK_NOTHROW(memset(ap, 255, i));
CHECK_NOTHROW(memset(as, 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 attribute_format(2, 3);
inline void NO_fprintf(FILE *, const char *, ...) noexcept {} inline void NO_fprintf(FILE *, const char *, ...) noexcept {}
// upx_memcmp_inline
#if __has_builtin(__builtin_memcmp) #if __has_builtin(__builtin_memcmp)
#define upx_memcmp_inline __builtin_memcmp #define upx_memcmp_inline __builtin_memcmp
#elif defined(__clang__) || defined(__GNUC__) #elif defined(__clang__) || defined(__GNUC__)
@ -384,6 +385,8 @@ inline void NO_fprintf(FILE *, const char *, ...) noexcept {}
#else #else
#define upx_memcmp_inline memcmp #define upx_memcmp_inline memcmp
#endif #endif
// upx_memcpy_inline
#if __has_builtin(__builtin_memcpy_inline) && 0 // TODO later: clang constexpr limitation? #if __has_builtin(__builtin_memcpy_inline) && 0 // TODO later: clang constexpr limitation?
#define upx_memcpy_inline __builtin_memcpy_inline #define upx_memcpy_inline __builtin_memcpy_inline
#elif __has_builtin(__builtin_memcpy) #elif __has_builtin(__builtin_memcpy)
@ -394,6 +397,7 @@ inline void NO_fprintf(FILE *, const char *, ...) noexcept {}
#define upx_memcpy_inline memcpy #define upx_memcpy_inline memcpy
#endif #endif
// upx_return_address()
#if defined(__wasi__) #if defined(__wasi__)
#define upx_return_address() nullptr #define upx_return_address() nullptr
#elif __has_builtin(__builtin_return_address) #elif __has_builtin(__builtin_return_address)
@ -803,7 +807,8 @@ int upx_doctest_check();
// util/membuffer.h // util/membuffer.h
class MemBuffer; class MemBuffer;
void *membuffer_get_void_ptr(MemBuffer &mb) noexcept; 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 // main.cpp
extern const char *progname; extern const char *progname;

View File

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

View File

@ -367,6 +367,8 @@ int ElfLinker::addLoader(const char *sname) {
return outputlen; return outputlen;
char *begin = strdup(sname); char *begin = strdup(sname);
assert(begin != nullptr);
auto begin_deleter = upx::MallocDeleter(&begin, 1);
char *end = begin + strlen(begin); char *end = begin + strlen(begin);
for (char *sect = begin; sect < end;) { for (char *sect = begin; sect < end;) {
for (char *tokend = sect; *tokend; tokend++) for (char *tokend = sect; *tokend; tokend++)
@ -418,7 +420,6 @@ int ElfLinker::addLoader(const char *sname) {
} }
sect += strlen(sect) + 1; sect += strlen(sect) + 1;
} }
::free(begin);
return outputlen; 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; static int exit_code = EXIT_OK;
#if (WITH_GUI) #if (WITH_GUI)
static noinline void do_exit(void) { throw exit_code; } static noreturn void do_exit() { throw exit_code; }
#else #else
#if defined(__GNUC__) static noreturn void do_exit() {
static void do_exit(void) __attribute__((__noreturn__));
#endif
static void do_exit(void) {
static bool in_exit = false; static bool in_exit = false;
if (in_exit) if (in_exit)
@ -115,7 +112,7 @@ static noinline void e_exit(int ec) {
do_exit(); do_exit();
} }
static noinline void e_usage(void) { static noinline void e_usage() {
if (opt->debug.getopt_throw_instead_of_exit) if (opt->debug.getopt_throw_instead_of_exit)
throw EXIT_USAGE; throw EXIT_USAGE;
show_usage(); show_usage();
@ -217,7 +214,7 @@ static void check_and_update_options(int i, int argc) {
// misc // misc
**************************************************************************/ **************************************************************************/
static void e_help(void) { static void e_help() {
show_help(0); show_help(0);
e_exit(EXIT_USAGE); e_exit(EXIT_USAGE);
} }

View File

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

View File

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

View File

@ -62,7 +62,7 @@ public:
// array access // array access
reference operator[](ptrdiff_t i) const may_throw { reference operator[](ptrdiff_t i) const may_throw {
// NOTE: &array[SIZE] is *not* legal for containers like std::vector and MemBuffer ! // 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); throwCantPack("MemBuffer invalid array index %td (%zu bytes)", i, size_in_bytes);
return ptr[i]; 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) \ #define XSPAN_REQUIRES_CONVERTIBLE_ANY_DIRECTION(A, B, RType) \
typename std::enable_if<std::is_same<A, B>::value, RType>::type typename std::enable_if<std::is_same<A, B>::value, RType>::type
#endif #endif
#define C MemBufferBase
#define XSPAN_FWD_C_IS_MEMBUFFER 1 #define XSPAN_FWD_C_IS_MEMBUFFER 1
#define C MemBufferBase
#if WITH_XSPAN >= 1 #if WITH_XSPAN >= 1
#define D XSPAN_NS(Ptr) #define D XSPAN_NS(Ptr)
#endif #endif
@ -198,8 +198,8 @@ public:
void allocForCompression(unsigned uncompressed_size, unsigned extra = 0) may_throw; void allocForCompression(unsigned uncompressed_size, unsigned extra = 0) may_throw;
void allocForDecompression(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 checkState() const may_throw;
noinline void dealloc() noexcept;
// explicit conversion // explicit conversion
void *getVoidPtr() noexcept { return (void *) ptr; } 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 // ptrdiff_t with nullptr checks and asserted size; will throw on failure
// NOTE: returns size_in_bytes, not number of elements! // NOTE: returns size_in_bytes, not number of elements!
int ptr_diff_bytes(const void *a, const void *b) may_throw; noinline 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 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 // short names "ptr_diff" and "ptr_udiff" for types with sizeof(X) == 1
template <class T, class U> template <class T, class U>
inline typename std::enable_if<sizeof(T) == 1 && sizeof(U) == 1, int>::type ptr_diff(const T *a, forceinline typename std::enable_if<sizeof(T) == 1 && sizeof(U) == 1, int>::type
const U *b) ptr_diff(const T *a, const U *b) may_throw {
may_throw {
return ptr_diff_bytes(a, b); return ptr_diff_bytes(a, b);
} }
template <class T, class U> 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 { ptr_udiff(const T *a, const U *b) may_throw {
return ptr_udiff_bytes(a, b); 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 force = true);
bool makebakname(char *ofilename, size_t size, const char *ifilename, 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); 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); 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; static XSpanStats xspan_stats;
// HINT: set env-var "UPX_DEBUG_DOCTEST_DISABLE=1" for improved debugging experience // 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; xspan_stats.fail_nullptr += 1;
throwCantPack("xspan unexpected NULL pointer; take care!"); throwCantPack("xspan unexpected NULL pointer; take care!");
} }
void xspan_fail_nullbase() { void xspan_fail_nullbase() may_throw {
xspan_stats.fail_nullbase += 1; xspan_stats.fail_nullbase += 1;
throwCantPack("xspan unexpected NULL base; take care!"); 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; xspan_stats.fail_not_same_base += 1;
throwCantPack("xspan unexpected base pointer; take care!"); 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; xspan_stats.fail_range_nullptr += 1;
throwCantPack("xspan_check_range: unexpected NULL pointer; take care!"); 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; xspan_stats.fail_range_nullbase += 1;
throwCantPack("xspan_check_range: unexpected NULL base; take care!"); 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; xspan_stats.fail_range_range += 1;
throwCantPack("xspan_check_range: pointer out of range; take care!"); 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; xspan_stats.check_range_counter += 1;
if very_unlikely (ptr == nullptr) if very_unlikely (ptr == nullptr)
xspan_fail_range_nullptr(); xspan_fail_range_nullptr();