src: add assert_noexcept()
This commit is contained in:
parent
1d71dd3851
commit
682a1e97e4
@ -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 = 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;
|
||||
|
||||
47
src/conf.h
47
src/conf.h
@ -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);
|
||||
|
||||
@ -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)";
|
||||
|
||||
10
src/except.h
10
src/except.h
@ -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);
|
||||
|
||||
@ -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;
|
||||
}
|
||||
});
|
||||
|
||||
@ -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;
|
||||
|
||||
17
src/main.cpp
17
src/main.cpp
@ -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,10 +1317,23 @@ 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();
|
||||
// malloc_stats();
|
||||
#endif
|
||||
return r;
|
||||
}
|
||||
|
||||
28
src/msg.cpp
28
src/msg.cpp
@ -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
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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());
|
||||
checkState();
|
||||
#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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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) {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user