src: add assert_noexcept()

This commit is contained in:
Markus F.X.J. Oberhumer 2023-07-08 12:06:27 +02:00
parent 1d71dd3851
commit 682a1e97e4
12 changed files with 248 additions and 167 deletions

View File

@ -196,7 +196,7 @@ struct CheckIntegral {
static constexpr U z[2] = {};
};
template <class U>
static void checkU(void) {
static void checkU(void) noexcept {
{
U a = {};
const U b = {};
@ -204,21 +204,21 @@ struct CheckIntegral {
U x[2] = {};
const U y[2] = {};
constexpr U z[2] = {};
assert(a == 0);
assert(b == 0);
assert(c == 0);
assert(x[0] == 0 && x[1] == 0);
assert(y[0] == 0 && y[1] == 0);
assert(z[0] == 0 && z[1] == 0);
assert_noexcept(a == 0);
assert_noexcept(b == 0);
assert_noexcept(c == 0);
assert_noexcept(x[0] == 0 && x[1] == 0);
assert_noexcept(y[0] == 0 && y[1] == 0);
assert_noexcept(z[0] == 0 && z[1] == 0);
}
{
TestU<U> t;
assert(t.a == 0);
assert(t.b == 0);
assert(t.c == 0);
assert(t.x[0] == 0 && t.x[1] == 0);
assert(t.y[0] == 0 && t.y[1] == 0);
assert(t.z[0] == 0 && t.z[1] == 0);
assert_noexcept(t.a == 0);
assert_noexcept(t.b == 0);
assert_noexcept(t.c == 0);
assert_noexcept(t.x[0] == 0 && t.x[1] == 0);
assert_noexcept(t.y[0] == 0 && t.y[1] == 0);
assert_noexcept(t.z[0] == 0 && t.z[1] == 0);
}
#if __cplusplus < 202002L
COMPILE_TIME_ASSERT(std::is_pod<U>::value) // std::is_pod is deprecated in C++20
@ -233,27 +233,27 @@ struct CheckIntegral {
COMPILE_TIME_ASSERT(upx_is_integral<U>::value)
COMPILE_TIME_ASSERT(upx_is_integral_v<U>)
}
static void check(void) {
static void check(void) noexcept {
{
TestT t = {};
assert(t.a == 0);
assert(t.x[0] == 0 && t.x[1] == 0);
assert_noexcept(t.a == 0);
assert_noexcept(t.x[0] == 0 && t.x[1] == 0);
}
{
const TestT t = {};
assert(t.a == 0);
assert(t.x[0] == 0 && t.x[1] == 0);
assert_noexcept(t.a == 0);
assert_noexcept(t.x[0] == 0 && t.x[1] == 0);
}
{
constexpr TestT t = {};
assert(t.a == 0);
assert(t.x[0] == 0 && t.x[1] == 0);
assert_noexcept(t.a == 0);
assert_noexcept(t.x[0] == 0 && t.x[1] == 0);
}
{
TestT t;
mem_clear(&t);
assert(t.a == 0);
assert(t.x[0] == 0 && t.x[1] == 0);
assert_noexcept(t.a == 0);
assert_noexcept(t.x[0] == 0 && t.x[1] == 0);
}
checkU<T>();
checkU<typename std::add_const<T>::type>();
@ -261,7 +261,7 @@ struct CheckIntegral {
};
template <class T>
struct CheckAlignment {
static void check(void) {
static void check(void) noexcept {
COMPILE_TIME_ASSERT_ALIGNED1(T)
struct alignas(1) Test1 {
char a;
@ -285,12 +285,12 @@ struct CheckAlignment {
};
template <class T>
struct TestBELE {
static noinline bool test(void) {
static noinline bool test(void) noexcept {
CheckIntegral<T>::check();
CheckAlignment<T>::check();
// arithmetic checks
T allbits = {};
assert(allbits == 0);
assert_noexcept(allbits == 0);
allbits += 1;
allbits -= 2;
T v1;
@ -300,22 +300,22 @@ struct TestBELE {
v1 -= 1;
T v2;
v2 = 1;
assert((v1 == v2));
assert(!(v1 != v2));
assert((v1 <= v2));
assert((v1 >= v2));
assert(!(v1 < v2));
assert(!(v1 > v2));
assert_noexcept((v1 == v2));
assert_noexcept(!(v1 != v2));
assert_noexcept((v1 <= v2));
assert_noexcept((v1 >= v2));
assert_noexcept(!(v1 < v2));
assert_noexcept(!(v1 > v2));
v2 ^= allbits;
assert(!(v1 == v2));
assert((v1 != v2));
assert((v1 <= v2));
assert(!(v1 >= v2));
assert((v1 < v2));
assert(!(v1 > v2));
assert_noexcept(!(v1 == v2));
assert_noexcept((v1 != v2));
assert_noexcept((v1 <= v2));
assert_noexcept(!(v1 >= v2));
assert_noexcept((v1 < v2));
assert_noexcept(!(v1 > v2));
v2 += 2;
assert(v1 == 1);
assert(v2 == 0);
assert_noexcept(v1 == 1);
assert_noexcept(v2 == 0);
v1 <<= 1;
v1 |= v2;
v1 >>= 1;
@ -324,8 +324,8 @@ struct TestBELE {
v2 *= v1;
v1 += v2;
v1 -= v2;
assert(v1 == 1);
assert(v2 == 0);
assert_noexcept(v1 == 1);
assert_noexcept(v2 == 0);
if ((v1 ^ v2) != 1)
return false;
return true;
@ -358,7 +358,7 @@ struct TestIntegerWrap {
#undef ACCCHK_ASSERT
#include "../miniacc.h"
void upx_compiler_sanity_check(void) {
void upx_compiler_sanity_check(void) noexcept {
#define ACC_WANT_ACC_CHK_CH 1
#undef ACCCHK_ASSERT
#define ACCCHK_ASSERT(expr) ACC_COMPILE_TIME_ASSERT(expr)
@ -402,31 +402,32 @@ void upx_compiler_sanity_check(void) {
COMPILE_TIME_ASSERT(sizeof(*((charptr) nullptr)) == 1)
COMPILE_TIME_ASSERT(sizeof(UPX_VERSION_STRING4) == 4 + 1)
assert(strlen(UPX_VERSION_STRING4) == 4);
assert_noexcept(strlen(UPX_VERSION_STRING4) == 4);
COMPILE_TIME_ASSERT(sizeof(UPX_VERSION_YEAR) == 4 + 1)
assert(strlen(UPX_VERSION_YEAR) == 4);
assert(memcmp(UPX_VERSION_DATE_ISO, UPX_VERSION_YEAR, 4) == 0);
assert(memcmp(&UPX_VERSION_DATE[sizeof(UPX_VERSION_DATE) - 1 - 4], UPX_VERSION_YEAR, 4) == 0);
assert_noexcept(strlen(UPX_VERSION_YEAR) == 4);
assert_noexcept(memcmp(UPX_VERSION_DATE_ISO, UPX_VERSION_YEAR, 4) == 0);
assert_noexcept(
memcmp(&UPX_VERSION_DATE[sizeof(UPX_VERSION_DATE) - 1 - 4], UPX_VERSION_YEAR, 4) == 0);
if (gitrev[0]) {
size_t revlen = strlen(gitrev);
if (strncmp(gitrev, "ERROR", 5) == 0) {
assert(revlen == 5 || revlen == 6);
assert_noexcept(revlen == 5 || revlen == 6);
} else {
assert(revlen == 12 || revlen == 13);
assert_noexcept(revlen == 12 || revlen == 13);
}
if (revlen == 6 || revlen == 13) {
assert(gitrev[revlen - 1] == '+');
assert_noexcept(gitrev[revlen - 1] == '+');
}
}
assert(UPX_RSIZE_MAX_MEM == 805306368);
assert_noexcept(UPX_RSIZE_MAX_MEM == 805306368);
#if DEBUG || 1
assert(TestBELE<LE16>::test());
assert(TestBELE<LE32>::test());
assert(TestBELE<LE64>::test());
assert(TestBELE<BE16>::test());
assert(TestBELE<BE32>::test());
assert(TestBELE<BE64>::test());
assert_noexcept(TestBELE<LE16>::test());
assert_noexcept(TestBELE<LE32>::test());
assert_noexcept(TestBELE<LE64>::test());
assert_noexcept(TestBELE<BE16>::test());
assert_noexcept(TestBELE<BE32>::test());
assert_noexcept(TestBELE<BE64>::test());
{
alignas(16) static const byte dd[32] = {
0, 0, 0, 0, 0, 0, 0, 0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, 0,
@ -434,51 +435,51 @@ void upx_compiler_sanity_check(void) {
const byte *d;
const N_BELE_RTP::AbstractPolicy *bele;
d = dd + 7;
assert(upx_adler32(d, 4) == 0x09f003f7);
assert(upx_adler32(d, 4, 0) == 0x09ec03f6);
assert(upx_adler32(d, 4, 1) == 0x09f003f7);
assert_noexcept(upx_adler32(d, 4) == 0x09f003f7);
assert_noexcept(upx_adler32(d, 4, 0) == 0x09ec03f6);
assert_noexcept(upx_adler32(d, 4, 1) == 0x09f003f7);
bele = &N_BELE_RTP::be_policy;
assert(get_be16(d) == 0xfffe);
assert(bele->get16(d) == 0xfffe);
assert(get_be16_signed(d) == -2);
assert(get_be24(d) == 0xfffefd);
assert(bele->get24(d) == 0xfffefd);
assert(get_be24_signed(d) == -259);
assert(get_be32(d) == 0xfffefdfc);
assert(bele->get32(d) == 0xfffefdfc);
assert(get_be32_signed(d) == -66052);
assert_noexcept(get_be16(d) == 0xfffe);
assert_noexcept(bele->get16(d) == 0xfffe);
assert_noexcept(get_be16_signed(d) == -2);
assert_noexcept(get_be24(d) == 0xfffefd);
assert_noexcept(bele->get24(d) == 0xfffefd);
assert_noexcept(get_be24_signed(d) == -259);
assert_noexcept(get_be32(d) == 0xfffefdfc);
assert_noexcept(bele->get32(d) == 0xfffefdfc);
assert_noexcept(get_be32_signed(d) == -66052);
bele = &N_BELE_RTP::le_policy;
assert(get_le16(d) == 0xfeff);
assert(bele->get16(d) == 0xfeff);
assert(get_le16_signed(d) == -257);
assert(get_le24(d) == 0xfdfeff);
assert(bele->get24(d) == 0xfdfeff);
assert(get_le24_signed(d) == -131329);
assert(get_le32(d) == 0xfcfdfeff);
assert(bele->get32(d) == 0xfcfdfeff);
assert(get_le32_signed(d) == -50462977);
assert(get_le64_signed(d) == -506097522914230529LL);
assert(find_be16(d, 2, 0xfffe) == 0);
assert(find_le16(d, 2, 0xfeff) == 0);
assert(find_be32(d, 4, 0xfffefdfc) == 0);
assert(find_le32(d, 4, 0xfcfdfeff) == 0);
assert_noexcept(get_le16(d) == 0xfeff);
assert_noexcept(bele->get16(d) == 0xfeff);
assert_noexcept(get_le16_signed(d) == -257);
assert_noexcept(get_le24(d) == 0xfdfeff);
assert_noexcept(bele->get24(d) == 0xfdfeff);
assert_noexcept(get_le24_signed(d) == -131329);
assert_noexcept(get_le32(d) == 0xfcfdfeff);
assert_noexcept(bele->get32(d) == 0xfcfdfeff);
assert_noexcept(get_le32_signed(d) == -50462977);
assert_noexcept(get_le64_signed(d) == -506097522914230529LL);
assert_noexcept(find_be16(d, 2, 0xfffe) == 0);
assert_noexcept(find_le16(d, 2, 0xfeff) == 0);
assert_noexcept(find_be32(d, 4, 0xfffefdfc) == 0);
assert_noexcept(find_le32(d, 4, 0xfcfdfeff) == 0);
d += 12;
assert(get_be16_signed(d) == 32638);
assert(get_be24_signed(d) == 8355453);
assert(get_be32_signed(d) == 2138996092);
assert(get_be64_signed(d) == 9186918263483431288LL);
assert_noexcept(get_be16_signed(d) == 32638);
assert_noexcept(get_be24_signed(d) == 8355453);
assert_noexcept(get_be32_signed(d) == 2138996092);
assert_noexcept(get_be64_signed(d) == 9186918263483431288LL);
}
{
unsigned dd;
void *const d = &dd;
dd = ne32_to_le32(0xf7f6f5f4);
assert(get_le26(d) == 0x03f6f5f4);
assert_noexcept(get_le26(d) == 0x03f6f5f4);
set_le26(d, 0);
assert(get_le26(d) == 0);
assert(dd == ne32_to_le32(0xf4000000));
assert_noexcept(get_le26(d) == 0);
assert_noexcept(dd == ne32_to_le32(0xf4000000));
set_le26(d, 0xff020304);
assert(get_le26(d) == 0x03020304);
assert(dd == ne32_to_le32(0xf7020304));
assert_noexcept(get_le26(d) == 0x03020304);
assert_noexcept(dd == ne32_to_le32(0xf7020304));
}
{
upx_uint16_t a = 0;
@ -487,12 +488,12 @@ void upx_compiler_sanity_check(void) {
set_ne16(&a, 0x04030201); // ignore upper bits
set_ne32(&b, 0x04030201);
set_ne64(&c, 0x0807060504030201ull);
assert(a == 0x0201);
assert(b == 0x04030201);
assert(c == 0x0807060504030201ull);
assert(get_ne16(&a) == 0x0201);
assert(get_ne32(&b) == 0x04030201);
assert(get_ne64(&c) == 0x0807060504030201ull);
assert_noexcept(a == 0x0201);
assert_noexcept(b == 0x04030201);
assert_noexcept(c == 0x0807060504030201ull);
assert_noexcept(get_ne16(&a) == 0x0201);
assert_noexcept(get_ne32(&b) == 0x04030201);
assert_noexcept(get_ne64(&c) == 0x0807060504030201ull);
}
#endif // DEBUG
union {
@ -507,38 +508,53 @@ void upx_compiler_sanity_check(void) {
LE32 l32;
LE64 l64;
} u;
assert(testNoAliasing(&u.v_short, &u.b32));
assert(testNoAliasing(&u.v_short, &u.l32));
assert(testNoAliasing(&u.v_int, &u.b64));
assert(testNoAliasing(&u.v_int, &u.l64));
assert_noexcept(testNoAliasing(&u.v_short, &u.b32));
assert_noexcept(testNoAliasing(&u.v_short, &u.l32));
assert_noexcept(testNoAliasing(&u.v_int, &u.b64));
assert_noexcept(testNoAliasing(&u.v_int, &u.l64));
// check working -fno-strict-aliasing
assert(testNoAliasing(&u.v_short, &u.v_int));
assert(testNoAliasing(&u.v_int, &u.v_long));
assert(testNoAliasing(&u.v_int, &u.v_llong));
assert(testNoAliasing(&u.v_long, &u.v_llong));
assert_noexcept(testNoAliasing(&u.v_short, &u.v_int));
assert_noexcept(testNoAliasing(&u.v_int, &u.v_long));
assert_noexcept(testNoAliasing(&u.v_int, &u.v_llong));
assert_noexcept(testNoAliasing(&u.v_long, &u.v_llong));
assert(TestIntegerWrap<unsigned>::inc_gt(0));
assert(!TestIntegerWrap<unsigned>::inc_gt(UINT_MAX));
assert(TestIntegerWrap<unsigned>::dec_lt(1));
assert(!TestIntegerWrap<unsigned>::dec_lt(0));
assert(TestIntegerWrap<unsigned>::neg_eq(0));
assert(!TestIntegerWrap<unsigned>::neg_eq(1));
assert(!TestIntegerWrap<unsigned>::neg_eq(UINT_MAX));
assert_noexcept(TestIntegerWrap<unsigned>::inc_gt(0));
assert_noexcept(!TestIntegerWrap<unsigned>::inc_gt(UINT_MAX));
assert_noexcept(TestIntegerWrap<unsigned>::dec_lt(1));
assert_noexcept(!TestIntegerWrap<unsigned>::dec_lt(0));
assert_noexcept(TestIntegerWrap<unsigned>::neg_eq(0));
assert_noexcept(!TestIntegerWrap<unsigned>::neg_eq(1));
assert_noexcept(!TestIntegerWrap<unsigned>::neg_eq(UINT_MAX));
// check working -fno-strict-overflow
assert(TestIntegerWrap<int>::inc_gt(0));
assert(!TestIntegerWrap<int>::inc_gt(INT_MAX));
assert(TestIntegerWrap<int>::dec_lt(0));
assert(!TestIntegerWrap<int>::dec_lt(INT_MIN));
assert(TestIntegerWrap<int>::neg_eq(0));
assert(!TestIntegerWrap<int>::neg_eq(1));
assert(!TestIntegerWrap<int>::neg_eq(INT_MAX));
assert(TestIntegerWrap<int>::neg_eq(INT_MIN)); // !!
assert_noexcept(TestIntegerWrap<int>::inc_gt(0));
assert_noexcept(!TestIntegerWrap<int>::inc_gt(INT_MAX));
assert_noexcept(TestIntegerWrap<int>::dec_lt(0));
assert_noexcept(!TestIntegerWrap<int>::dec_lt(INT_MIN));
assert_noexcept(TestIntegerWrap<int>::neg_eq(0));
assert_noexcept(!TestIntegerWrap<int>::neg_eq(1));
assert_noexcept(!TestIntegerWrap<int>::neg_eq(INT_MAX));
assert_noexcept(TestIntegerWrap<int>::neg_eq(INT_MIN)); // !!
}
/*************************************************************************
// some doctest test cases
**************************************************************************/
TEST_CASE("assert_noexcept") {
// just to make sure that our assert macros don't generate any warnings
byte dummy = 0;
byte *ptr1 = &dummy;
const byte *const ptr2 = &dummy;
assert(true);
assert(1);
assert(ptr1);
assert(ptr2);
assert_noexcept(true);
assert_noexcept(1);
assert_noexcept(ptr1);
assert_noexcept(ptr2);
}
TEST_CASE("noncopyable") {
struct Test : private noncopyable {
int v = 1;

View File

@ -406,6 +406,22 @@ inline void mem_clear(T (&array)[N]) noexcept = delete;
#define ByteArray(var, n) Array(byte, var, (n))
// assert_noexcept()
noinline void assertFailed(const char *expr, const char *file, int line, const char *func) noexcept;
noinline void throwAssertFailed(const char *expr, const char *file, int line, const char *func);
#if defined(__GNUC__)
#undef assert
#if DEBUG || 0
// generate a warning if assert() is used inside a "noexcept" function
#define assert(e) ((void)(__acc_cte(e) || (assertFailed(#e, __FILE__, __LINE__, __func__), throw 1, 0)))
#else
// turn assertion failures into exceptions
#define assert(e) ((void)(__acc_cte(e) || (throwAssertFailed(#e, __FILE__, __LINE__, __func__), throw 1, 0)))
#endif
#define assert_noexcept(e) ((void)(__acc_cte(e) || (assertFailed(#e, __FILE__, __LINE__, __func__), 0)))
#else
#define assert_noexcept assert
#endif
class noncopyable {
protected:
@ -614,24 +630,25 @@ struct upx_callback_t {
template <class T, T default_value_, T min_value_, T max_value_>
struct OptVar {
static_assert(std::is_integral_v<T>);
typedef T value_type;
static constexpr T default_value = default_value_;
static constexpr T min_value = min_value_;
static constexpr T max_value = max_value_;
static_assert(min_value <= default_value && default_value <= max_value);
static void assertValue(const T &v) {
static void assertValue(const T &v) noexcept {
// info: this generates annoying warnings "unsigned >= 0 is always true"
//assert(v >= min_value);
assert(v == min_value || v >= min_value + 1);
assert(v <= max_value);
//assert_noexcept(v >= min_value);
assert_noexcept(v == min_value || v >= min_value + 1);
assert_noexcept(v <= max_value);
}
void assertValue() const {
void assertValue() const noexcept {
assertValue(v);
}
OptVar() noexcept : v(default_value), is_set(false) { }
OptVar& operator= (const T &other) {
OptVar& operator= (const T &other) noexcept {
assertValue(other);
v = other;
is_set = true;
@ -648,11 +665,11 @@ struct OptVar {
// optional assignments
template <class T, T a, T b, T c>
inline void oassign(OptVar<T,a,b,c> &self, const OptVar<T,a,b,c> &other) {
inline void oassign(OptVar<T,a,b,c> &self, const OptVar<T,a,b,c> &other) noexcept {
if (other.is_set) { self.v = other.v; self.is_set = true; }
}
template <class T, T a, T b, T c>
inline void oassign(T &v, const OptVar<T,a,b,c> &other) {
inline void oassign(T &v, const OptVar<T,a,b,c> &other) noexcept {
if (other.is_set) { v = other.v; }
}
@ -782,7 +799,7 @@ void *membuffer_get_void_ptr(MemBuffer &mb) noexcept;
unsigned membuffer_get_size(MemBuffer &mb) noexcept;
// util/dt_check.cpp
void upx_compiler_sanity_check();
void upx_compiler_sanity_check() noexcept;
int upx_doctest_check();
int upx_doctest_check(int argc, char **argv);
@ -794,12 +811,12 @@ void main_get_envoptions();
int upx_main(int argc, char *argv[]);
// msg.cpp
void printSetNl(int need_nl);
void printClearLine(FILE *f = nullptr);
void printErr(const char *iname, const Throwable *e);
void printUnhandledException(const char *iname, const std::exception *e);
void printErr(const char *iname, const char *format, ...) attribute_format(2, 3);
void printWarn(const char *iname, const char *format, ...) attribute_format(2, 3);
void printSetNl(int need_nl) noexcept;
void printClearLine(FILE *f = nullptr) noexcept;
void printErr(const char *iname, const Throwable &e) noexcept;
void printUnhandledException(const char *iname, const std::exception *e) noexcept;
void printErr(const char *iname, const char *format, ...) noexcept attribute_format(2, 3);
void printWarn(const char *iname, const char *format, ...) noexcept attribute_format(2, 3);
void infoWarning(const char *format, ...) attribute_format(1, 2);
void infoHeader(const char *format, ...) attribute_format(1, 2);

View File

@ -72,7 +72,9 @@ Throwable::~Throwable() noexcept {
void throwCantPack(const char *msg) {
// UGLY, but makes things easier
if (opt->cmd == CMD_COMPRESS)
if (opt->cmd == CMD_NONE)
throw CantPackException(msg);
else if (opt->cmd == CMD_COMPRESS)
throw CantPackException(msg);
else if (opt->cmd == CMD_FILEINFO)
throw CantPackException(msg);
@ -167,6 +169,20 @@ void throwCantUnpack(const char *format, ...) {
//
**************************************************************************/
void assertFailed(const char *expr, const char *file, int line, const char *func) noexcept {
fflush(stdout);
fprintf(stderr, "Assertion failed: %s (%s: %s: %d)\n", expr, file, func, line);
std::terminate();
}
void throwAssertFailed(const char *expr, const char *file, int line, const char *func) {
if (opt->debug.debug_level >= 1) {
throwCantPack("corrupted file; details: %s (%s: %s: %d)", expr, file, func, line);
} else {
throwCantPack("corrupted file; try '--debug' for more details");
}
}
const char *prettyName(const char *n) noexcept {
if (n == nullptr)
return "(null)";

View File

@ -29,6 +29,9 @@
const char *prettyName(const char *n) noexcept;
noinline void assertFailed(const char *expr, const char *file, int line, const char *func) noexcept;
noinline void throwAssertFailed(const char *expr, const char *file, int line, const char *func);
/*************************************************************************
// exceptions
**************************************************************************/
@ -57,6 +60,9 @@ private:
Throwable &operator=(const Throwable &) = delete;
// disable dynamic allocation => force throwing by value
ACC_CXX_DISABLE_NEW_DELETE
// disable taking the address => force passing by reference
// [I'm not too sure about this design decision, but we can always allow it if needed]
Throwable *operator&() const noexcept = delete;
private:
static upx_std_atomic(size_t) debug_counter; // for debugging
@ -173,9 +179,9 @@ public:
#undef NORET
#if 1 && defined(__GNUC__)
#define NORET __acc_noinline __attribute__((__noreturn__))
#define NORET noinline __attribute__((__noreturn__))
#else
#define NORET __acc_noinline
#define NORET noinline
#endif
NORET void throwCantPack(const char *msg);

View File

@ -50,12 +50,12 @@ static void initFilter(Filter *f, byte *buf, unsigned buf_len) {
upx_std_call_once(init_done, []() noexcept {
// init the filter_map[] (using a lambda function)
assert(n_filters <= 254); // as 0xff means "empty slot"
assert_noexcept(n_filters <= 254); // as 0xff means "empty slot"
memset(filter_map, 0xff, sizeof(filter_map));
for (int i = 0; i < n_filters; i++) {
int filter_id = filters[i].id;
assert(filter_id >= 0 && filter_id <= 255);
assert(filter_map[filter_id] == 0xff);
assert_noexcept(filter_id >= 0 && filter_id <= 255);
assert_noexcept(filter_map[filter_id] == 0xff);
filter_map[filter_id] = (upx_uint8_t) i;
}
});

View File

@ -217,6 +217,9 @@ bool LeFile::readFileHeader() {
return false;
fif->seek(le_offset, SEEK_SET);
fif->readx(&ih, sizeof(ih));
if (mps < 512 || mps > 2097152 || (mps & (mps - 1)) != 0 || ih.bytes_on_last_page > mps)
throwCantPack("bad file header");
(void) mem_size(mps, pages); // assert size
return true;
#undef H
}
@ -224,7 +227,7 @@ bool LeFile::readFileHeader() {
void LeFile::writeFile(OutputFile *f, bool le) {
fof = f;
memcpy(&oh, &ih,
(char *) &oh.memory_pages - (char *) &oh); // copy some members of the orig. header
(charptr) &oh.memory_pages - (charptr) &oh); // copy some members of the orig. header
oh.memory_page_size = mps;
oh.object_table_offset = sizeof(oh);
oh.object_table_entries = soobject_table;

View File

@ -41,7 +41,7 @@
#endif
static const char *argv0 = "";
const char *progname = "";
const char *progname = "upx";
static acc_getopt_t mfx_getopt;
#define mfx_optarg mfx_getopt.optarg
@ -1317,7 +1317,20 @@ int __acc_cdecl_main main(int argc, char *argv[]) {
// srand((int) time(nullptr));
srand((int) clock());
// info: calling upx_main() here violates implicit "noexcept", so we need a try block
#if 0
int r = upx_main(argc, argv);
#else
int r = EXIT_INTERNAL;
try {
r = upx_main(argc, argv);
} catch (const Throwable &e) {
printErr("unknown", e);
std::terminate();
} catch (...) {
std::terminate();
}
#endif
#if 0 && defined(__GLIBC__)
// malloc_stats();

View File

@ -35,9 +35,9 @@
static int pr_need_nl = 0;
void printSetNl(int need_nl) { pr_need_nl = need_nl; }
void printSetNl(int need_nl) noexcept { pr_need_nl = need_nl; }
void printClearLine(FILE *f) {
void printClearLine(FILE *f) noexcept {
static char clear_line_msg[1 + 79 + 1 + 1];
if (!clear_line_msg[0]) {
char *msg = clear_line_msg;
@ -56,14 +56,14 @@ void printClearLine(FILE *f) {
printSetNl(0);
}
static void pr_print(bool c, const char *msg) {
static void pr_print(bool c, const char *msg) noexcept {
if (c && !opt->to_stdout)
con_fprintf(stderr, "%s", msg);
else
fprintf(stderr, "%s", msg);
}
static void pr_error(const char *iname, const char *msg, bool is_warning) {
static void pr_error(const char *iname, const char *msg, bool is_warning) noexcept {
fflush(stdout);
fflush(stderr);
char buf[1024];
@ -98,17 +98,17 @@ static void pr_error(const char *iname, const char *msg, bool is_warning) {
UNUSED(fg);
}
void printErr(const char *iname, const Throwable *e) {
void printErr(const char *iname, const Throwable &e) noexcept {
char buf[1024];
size_t l;
snprintf(buf, sizeof(buf), "%s", prettyName(typeid(*e).name()));
snprintf(buf, sizeof(buf), "%s", prettyName(typeid(e).name()));
l = strlen(buf);
if (l < sizeof(buf) && e->getMsg())
snprintf(buf + l, sizeof(buf) - l, ": %s", e->getMsg());
if (l < sizeof(buf) && e.getMsg())
snprintf(buf + l, sizeof(buf) - l, ": %s", e.getMsg());
l = strlen(buf);
if (l < sizeof(buf) && e->getErrno()) {
snprintf(buf + l, sizeof(buf) - l, ": %s", strerror(e->getErrno()));
if (l < sizeof(buf) && e.getErrno()) {
snprintf(buf + l, sizeof(buf) - l, ": %s", strerror(e.getErrno()));
#if 1
// some compilers (e.g. Borland C++) put a trailing '\n'
// into the strerror() result
@ -117,10 +117,10 @@ void printErr(const char *iname, const Throwable *e) {
buf[l] = 0;
#endif
}
pr_error(iname, buf, e->isWarning());
pr_error(iname, buf, e.isWarning());
}
void printErr(const char *iname, const char *format, ...) {
void printErr(const char *iname, const char *format, ...) noexcept {
va_list args;
char buf[1024];
@ -131,7 +131,7 @@ void printErr(const char *iname, const char *format, ...) {
pr_error(iname, buf, false);
}
void printWarn(const char *iname, const char *format, ...) {
void printWarn(const char *iname, const char *format, ...) noexcept {
va_list args;
char buf[1024];
@ -142,7 +142,7 @@ void printWarn(const char *iname, const char *format, ...) {
pr_error(iname, buf, true);
}
void printUnhandledException(const char *iname, const std::exception *e) {
void printUnhandledException(const char *iname, const std::exception *e) noexcept {
if (e)
printErr(iname, "unhandled exception: %s\n", prettyName(e->what()));
else

View File

@ -172,7 +172,7 @@ int forced_method(int method) noexcept // extract the forced method
{
if (is_forced_method(method))
method &= ~(0x80ul << 24);
assert(method > 0);
assert_noexcept(method > 0);
return method;
}

View File

@ -233,7 +233,17 @@ void MemBuffer::alloc(upx_uint64_t bytes) {
void MemBuffer::dealloc() noexcept {
if (ptr != nullptr) {
debug_set(debug.last_return_address_dealloc, upx_return_address());
#if DEBUG || 1
// info: calling checkState() here violates "noexcept", so we need a try block
try {
checkState();
} catch (const Throwable &e) {
printErr("unknown", e);
std::terminate();
} catch (...) {
std::terminate();
}
#endif
stats.global_dealloc_counter += 1;
stats.global_total_active_bytes -= size_in_bytes;
if (use_simple_mcheck()) {
@ -251,7 +261,7 @@ void MemBuffer::dealloc() noexcept {
ptr = nullptr;
size_in_bytes = 0;
} else {
assert(size_in_bytes == 0);
assert_noexcept(size_in_bytes == 0);
}
}

View File

@ -56,7 +56,7 @@ ACC_COMPILE_TIME_ASSERT_HEADER(UPX_RSIZE_MAX_STR >= 1024)
upx_rsize_t mem_size(upx_uint64_t element_size, upx_uint64_t n, upx_uint64_t extra1,
upx_uint64_t extra2) {
assert(element_size > 0);
if very_unlikely (element_size > UPX_RSIZE_MAX)
if very_unlikely (element_size == 0 || element_size > UPX_RSIZE_MAX)
throwCantPack("mem_size 1; take care");
if very_unlikely (n > UPX_RSIZE_MAX)
throwCantPack("mem_size 2; take care");
@ -72,8 +72,8 @@ upx_rsize_t mem_size(upx_uint64_t element_size, upx_uint64_t n, upx_uint64_t ext
bool mem_size_valid(upx_uint64_t element_size, upx_uint64_t n, upx_uint64_t extra1,
upx_uint64_t extra2) noexcept {
assert(element_size > 0);
if very_unlikely (element_size > UPX_RSIZE_MAX)
assert_noexcept(element_size > 0);
if very_unlikely (element_size == 0 || element_size > UPX_RSIZE_MAX)
return false;
if very_unlikely (n > UPX_RSIZE_MAX)
return false;

View File

@ -250,7 +250,7 @@ void do_one_file(const char *iname, char *oname) {
// process all files from the commandline
**************************************************************************/
static void unlink_ofile(char *oname) {
static void unlink_ofile(char *oname) noexcept {
if (oname && oname[0]) {
#if HAVE_CHMOD
int r;
@ -281,12 +281,12 @@ int do_files(int i, int argc, char *argv[]) {
} catch (const Exception &e) {
unlink_ofile(oname);
if (opt->verbose >= 1 || (opt->verbose >= 0 && !e.isWarning()))
printErr(iname, &e);
printErr(iname, e);
main_set_exit_code(e.isWarning() ? EXIT_WARN : EXIT_ERROR);
// this is not fatal, continue processing more files
} catch (const Error &e) {
unlink_ofile(oname);
printErr(iname, &e);
printErr(iname, e);
main_set_exit_code(EXIT_ERROR);
return -1; // fatal error
} catch (std::bad_alloc *e) {