src: portability updates
This commit is contained in:
parent
285472bc78
commit
16c8f6d160
2
.github/workflows/ci.yml
vendored
2
.github/workflows/ci.yml
vendored
@ -64,7 +64,7 @@ jobs:
|
||||
- run: bash ./misc/scripts/check_whitespace_git.sh
|
||||
- name: Check source code formatting
|
||||
run: |
|
||||
export UPX_CLANG_FORMAT="$(readlink -en "$PWD/../deps/bin-upx-20221212/clang-format-15.0.6")"
|
||||
export UPX_CLANG_FORMAT="$(readlink -en ../deps/bin-upx-20221212/clang-format-15.0.6)"
|
||||
make -C src clang-format
|
||||
if ! git diff --quiet; then git diff; exit 1; fi
|
||||
- name: Rebuild docs
|
||||
|
||||
@ -422,7 +422,7 @@ forceinline constexpr int sign_extend(unsigned v, unsigned bits) noexcept {
|
||||
|
||||
forceinline constexpr upx_int64_t sign_extend(upx_uint64_t v, unsigned bits) noexcept {
|
||||
#if (ACC_ARCH_M68K) // no barrel shifter
|
||||
const upx_uint64_t sign_bit = 1ull << (bits - 1);
|
||||
const upx_uint64_t sign_bit = upx_uint64_t(1) << (bits - 1);
|
||||
return ACC_ICAST(upx_int64_t, (v & (sign_bit - 1)) - (v & sign_bit));
|
||||
#else
|
||||
return ACC_ICAST(upx_int64_t, v << (64 - bits)) >> (64 - bits);
|
||||
|
||||
@ -93,20 +93,193 @@ int upx_doctest_check(int argc, char **argv) {
|
||||
int upx_doctest_check() { return upx_doctest_check(0, nullptr); }
|
||||
|
||||
/*************************************************************************
|
||||
// compile-time checks
|
||||
// check fundamental types
|
||||
**************************************************************************/
|
||||
|
||||
static_assert(std::is_same<short, upx_int16_t>::value);
|
||||
static_assert(std::is_same<unsigned short, upx_uint16_t>::value);
|
||||
static_assert(std::is_same<int, upx_int32_t>::value);
|
||||
static_assert(std::is_same<unsigned, upx_uint32_t>::value);
|
||||
static_assert(std::is_same<long long, upx_int64_t>::value);
|
||||
static_assert(std::is_same<unsigned long long, upx_uint64_t>::value);
|
||||
static_assert(std::is_integral<ptrdiff_t>::value, "");
|
||||
static_assert(std::is_integral<size_t>::value, "");
|
||||
static_assert(std::is_integral<intptr_t>::value, "");
|
||||
static_assert(std::is_integral<uintptr_t>::value, "");
|
||||
|
||||
static_assert(std::is_signed<ptrdiff_t>::value, "");
|
||||
static_assert(!std::is_signed<size_t>::value, "");
|
||||
static_assert(std::is_signed<intptr_t>::value, "");
|
||||
static_assert(!std::is_signed<uintptr_t>::value, "");
|
||||
|
||||
static_assert(!std::is_unsigned<ptrdiff_t>::value, "");
|
||||
static_assert(std::is_unsigned<size_t>::value, "");
|
||||
static_assert(!std::is_unsigned<intptr_t>::value, "");
|
||||
static_assert(std::is_unsigned<uintptr_t>::value, "");
|
||||
|
||||
#if defined(__SIZEOF_SHORT__)
|
||||
static_assert(sizeof(short) == __SIZEOF_SHORT__, "");
|
||||
#endif
|
||||
#if defined(__SIZEOF_INT__)
|
||||
static_assert(sizeof(int) == __SIZEOF_INT__, "");
|
||||
#endif
|
||||
#if defined(__SIZEOF_LONG__)
|
||||
static_assert(sizeof(long) == __SIZEOF_LONG__, "");
|
||||
#endif
|
||||
#if defined(__SIZEOF_LONG_LONG__)
|
||||
static_assert(sizeof(long long) == __SIZEOF_LONG_LONG__, "");
|
||||
#endif
|
||||
#if defined(__SIZEOF_INT128__)
|
||||
static_assert(16 == __SIZEOF_INT128__, "");
|
||||
static_assert(sizeof(__int128) == __SIZEOF_INT128__, "");
|
||||
static_assert(sizeof(unsigned __int128) == __SIZEOF_INT128__, "");
|
||||
static_assert(sizeof(upx_int128_t) == __SIZEOF_INT128__, "");
|
||||
static_assert(sizeof(upx_uint128_t) == __SIZEOF_INT128__, "");
|
||||
#endif
|
||||
#if defined(__SIZEOF_PTRDIFF_T__)
|
||||
static_assert(sizeof(ptrdiff_t) == __SIZEOF_PTRDIFF_T__, "");
|
||||
#endif
|
||||
#if defined(__SIZEOF_SIZE_T__)
|
||||
static_assert(sizeof(size_t) == __SIZEOF_SIZE_T__, "");
|
||||
#endif
|
||||
#if defined(__SIZEOF_POINTER__)
|
||||
static_assert(sizeof(void *) == __SIZEOF_POINTER__, "");
|
||||
static_assert(sizeof(intptr_t) == __SIZEOF_POINTER__, "");
|
||||
static_assert(sizeof(uintptr_t) == __SIZEOF_POINTER__, "");
|
||||
#endif
|
||||
#if defined(__SIZEOF_PTRADDR_T__)
|
||||
static_assert(sizeof(__PTRADDR_TYPE__) == __SIZEOF_PTRADDR_T__, "");
|
||||
static_assert(sizeof(upx_ptraddr_t) == __SIZEOF_PTRADDR_T__, "");
|
||||
#endif
|
||||
|
||||
#if defined(__SCHAR_WIDTH__)
|
||||
static_assert(8 * sizeof(signed char) == __SCHAR_WIDTH__, "");
|
||||
#endif
|
||||
#if defined(__SHRT_WIDTH__)
|
||||
static_assert(8 * sizeof(short) == __SHRT_WIDTH__, "");
|
||||
#endif
|
||||
#if defined(__INT_WIDTH__)
|
||||
static_assert(8 * sizeof(int) == __INT_WIDTH__, "");
|
||||
#endif
|
||||
#if defined(__LONG_WIDTH__)
|
||||
static_assert(8 * sizeof(long) == __LONG_WIDTH__, "");
|
||||
#endif
|
||||
#if defined(__LONG_LONG_WIDTH__)
|
||||
static_assert(8 * sizeof(long long) == __LONG_LONG_WIDTH__, "");
|
||||
#endif
|
||||
#if defined(__INTMAX_WIDTH__)
|
||||
static_assert(8 * sizeof(intmax_t) == __INTMAX_WIDTH__, "");
|
||||
static_assert(8 * sizeof(uintmax_t) == __INTMAX_WIDTH__, "");
|
||||
#endif
|
||||
#if defined(__PTRDIFF_WIDTH__)
|
||||
static_assert(8 * sizeof(ptrdiff_t) == __PTRDIFF_WIDTH__, "");
|
||||
#endif
|
||||
#if defined(__SIZE_WIDTH__)
|
||||
static_assert(8 * sizeof(size_t) == __SIZE_WIDTH__, "");
|
||||
#endif
|
||||
#if defined(__INTPTR_WIDTH__)
|
||||
static_assert(8 * sizeof(intptr_t) == __INTPTR_WIDTH__, "");
|
||||
static_assert(8 * sizeof(uintptr_t) == __INTPTR_WIDTH__, "");
|
||||
#endif
|
||||
#if defined(__UINTPTR_WIDTH__)
|
||||
static_assert(8 * sizeof(intptr_t) == __UINTPTR_WIDTH__, "");
|
||||
static_assert(8 * sizeof(uintptr_t) == __UINTPTR_WIDTH__, "");
|
||||
#endif
|
||||
#if defined(__PTRADDR_WIDTH__)
|
||||
static_assert(8 * sizeof(__PTRADDR_TYPE__) == __PTRADDR_WIDTH__, "");
|
||||
static_assert(8 * sizeof(upx_ptraddr_t) == __PTRADDR_WIDTH__, "");
|
||||
#endif
|
||||
|
||||
// true types from compiler
|
||||
typedef decltype((const char *) nullptr - (const char *) nullptr) true_ptrdiff_t;
|
||||
typedef decltype(sizeof(0)) true_size_t;
|
||||
|
||||
// expected types from pre-defined macros
|
||||
#if defined(__PTRDIFF_TYPE__)
|
||||
typedef __PTRDIFF_TYPE__ expected_ptrdiff_t;
|
||||
#endif
|
||||
#if defined(__SIZE_TYPE__)
|
||||
typedef __SIZE_TYPE__ expected_size_t;
|
||||
#endif
|
||||
#if defined(__INTPTR_TYPE__)
|
||||
typedef __INTPTR_TYPE__ expected_intptr_t;
|
||||
#endif
|
||||
#if defined(__UINTPTR_TYPE__)
|
||||
typedef __UINTPTR_TYPE__ expected_uintptr_t;
|
||||
#endif
|
||||
#if defined(__PTRADDR_TYPE__)
|
||||
typedef __PTRADDR_TYPE__ expected_ptraddr_t;
|
||||
#endif
|
||||
|
||||
#define ASSERT_COMPATIBLE_TYPE(A, B) \
|
||||
static_assert(std::is_integral<A>::value, ""); \
|
||||
static_assert(std::is_integral<B>::value, ""); \
|
||||
static_assert(std::is_signed<A>::value == std::is_signed<B>::value, ""); \
|
||||
static_assert(std::is_unsigned<A>::value == std::is_unsigned<B>::value, ""); \
|
||||
static_assert(sizeof(A) == sizeof(B), ""); \
|
||||
static_assert(alignof(A) == alignof(B), "")
|
||||
|
||||
#define ASSERT_SAME_TYPE(A, B) \
|
||||
ASSERT_COMPATIBLE_TYPE(A, B); \
|
||||
static_assert(std::is_same<A, B>::value, "")
|
||||
|
||||
// C vs C++ headers
|
||||
ASSERT_SAME_TYPE(ptrdiff_t, std::ptrdiff_t);
|
||||
ASSERT_SAME_TYPE(size_t, std::size_t);
|
||||
ASSERT_SAME_TYPE(intptr_t, std::intptr_t);
|
||||
ASSERT_SAME_TYPE(uintptr_t, std::uintptr_t);
|
||||
|
||||
// true types
|
||||
ASSERT_SAME_TYPE(ptrdiff_t, true_ptrdiff_t);
|
||||
ASSERT_SAME_TYPE(size_t, true_size_t);
|
||||
|
||||
// expected types
|
||||
#if defined(__PTRDIFF_TYPE__)
|
||||
static_assert(std::is_signed<expected_ptrdiff_t>::value, "");
|
||||
ASSERT_SAME_TYPE(ptrdiff_t, expected_ptrdiff_t);
|
||||
#endif
|
||||
#if defined(__SIZE_TYPE__)
|
||||
static_assert(std::is_unsigned<expected_size_t>::value, "");
|
||||
ASSERT_SAME_TYPE(size_t, expected_size_t);
|
||||
#endif
|
||||
#if defined(__INTPTR_TYPE__)
|
||||
static_assert(std::is_signed<expected_intptr_t>::value, "");
|
||||
ASSERT_COMPATIBLE_TYPE(intptr_t, expected_intptr_t); // some toolchains are buggy
|
||||
#endif
|
||||
#if defined(__UINTPTR_TYPE__)
|
||||
static_assert(std::is_unsigned<expected_uintptr_t>::value, "");
|
||||
ASSERT_COMPATIBLE_TYPE(uintptr_t, expected_uintptr_t); // some toolchains are buggy
|
||||
#endif
|
||||
#if defined(__PTRADDR_TYPE__)
|
||||
static_assert(std::is_unsigned<expected_ptraddr_t>::value, "");
|
||||
ASSERT_SAME_TYPE(upx_ptraddr_t, expected_ptraddr_t);
|
||||
#endif
|
||||
|
||||
#if defined(__INTPTR_TYPE__) && defined(__UINTPTR_TYPE__)
|
||||
#if defined(__m68k__) && defined(__atarist__) && defined(__GNUC__)
|
||||
// BUG: compiler/mintlib mismatch: int vs long
|
||||
#elif (defined(__arm__) || defined(__mips__)) && defined(__linux__) && defined(__clang__) && \
|
||||
(__SIZEOF_LONG__ == 4)
|
||||
// BUG: compiler/libc mismatch: int vs long
|
||||
// TODO later: check zig and clang for possible misconfiguration under 32-bit arm & mips
|
||||
#else
|
||||
ASSERT_SAME_TYPE(intptr_t, expected_intptr_t);
|
||||
ASSERT_SAME_TYPE(uintptr_t, expected_uintptr_t);
|
||||
#endif // BUG
|
||||
#endif
|
||||
|
||||
// UPX types
|
||||
ASSERT_SAME_TYPE(short, upx_int16_t);
|
||||
ASSERT_SAME_TYPE(unsigned short, upx_uint16_t);
|
||||
ASSERT_SAME_TYPE(int, upx_int32_t);
|
||||
ASSERT_SAME_TYPE(unsigned, upx_uint32_t);
|
||||
#if (__SIZEOF_LONG_LONG__ + 0 < 128)
|
||||
ASSERT_SAME_TYPE(long long, upx_int64_t);
|
||||
ASSERT_SAME_TYPE(unsigned long long, upx_uint64_t);
|
||||
#endif
|
||||
|
||||
/*************************************************************************
|
||||
// compile-time checks
|
||||
**************************************************************************/
|
||||
|
||||
static_assert(no_bswap16(0x04030201) == 0x0201);
|
||||
static_assert(no_bswap32(0x04030201) == 0x04030201);
|
||||
static_assert(no_bswap64(0x0807060504030201ull) == 0x0807060504030201ull);
|
||||
#if !(ACC_CC_MSC) // unfortunately *not* constexpr with current MSVC
|
||||
#if !(ACC_CC_MSC) || defined(upx_is_constant_evaluated)
|
||||
static_assert(bswap16(0x04030201) == 0x0102);
|
||||
static_assert(bswap32(0x04030201) == 0x01020304);
|
||||
static_assert(bswap64(0x0807060504030201ull) == 0x0102030405060708ull);
|
||||
@ -125,8 +298,8 @@ static_assert(sign_extend(0u + 257, 8) == 1);
|
||||
static_assert(sign_extend(0u + 383, 8) == 127);
|
||||
static_assert(sign_extend(0u + 384, 8) == -128);
|
||||
static_assert(sign_extend(0u + 511, 8) == -1);
|
||||
static_assert(sign_extend(0ull + 0, 1) == 0);
|
||||
static_assert(sign_extend(0ull + 1, 1) == -1);
|
||||
static_assert(sign_extend(upx_uint64_t(0) + 0, 1) == 0);
|
||||
static_assert(sign_extend(upx_uint64_t(0) + 1, 1) == -1);
|
||||
|
||||
static_assert(CHAR_BIT == 8);
|
||||
#if 0 // does not work with MSVC
|
||||
@ -152,6 +325,8 @@ namespace {
|
||||
|
||||
template <class T>
|
||||
struct CheckIntegral {
|
||||
static_assert(upx_is_integral<T>::value);
|
||||
static_assert(upx_is_integral_v<T>);
|
||||
struct TestT {
|
||||
T a;
|
||||
T x[2];
|
||||
@ -208,7 +383,7 @@ struct CheckIntegral {
|
||||
static_assert(upx_is_integral<U>::value);
|
||||
static_assert(upx_is_integral_v<U>);
|
||||
}
|
||||
static void check(void) noexcept {
|
||||
static void check_core(void) noexcept {
|
||||
{
|
||||
TestT t = {};
|
||||
assert_noexcept(t.a == 0);
|
||||
@ -238,14 +413,27 @@ struct CheckIntegral {
|
||||
one = 1;
|
||||
three = 3;
|
||||
four = 4;
|
||||
assert_noexcept(zero == 0);
|
||||
assert_noexcept(one == 1);
|
||||
assert_noexcept(three == 3);
|
||||
assert_noexcept(four == 4);
|
||||
// min / max
|
||||
assert_noexcept(upx::min(one, four) == 1);
|
||||
assert_noexcept(upx::min(one, four) == one);
|
||||
assert_noexcept(upx::max(one, four) == 4);
|
||||
assert_noexcept(upx::max(one, four) == four);
|
||||
// align
|
||||
}
|
||||
}
|
||||
static void check(void) noexcept {
|
||||
check_core();
|
||||
{
|
||||
T zero, one, three, four;
|
||||
zero = 0;
|
||||
one = 1;
|
||||
three = 3;
|
||||
four = 4;
|
||||
// align - needs binary expressions which do not work
|
||||
// on CHERI uintptr_t because of pointer provenance
|
||||
assert_noexcept(upx::align_down(zero, four) == 0);
|
||||
assert_noexcept(upx::align_down(zero, four) == zero);
|
||||
assert_noexcept(upx::align_down(one, four) == 0);
|
||||
@ -474,11 +662,18 @@ struct TestBELE {
|
||||
|
||||
template <class T, bool T_is_signed>
|
||||
struct CheckSignedness {
|
||||
static_assert(std::is_integral_v<T>);
|
||||
static_assert(std::is_signed_v<T> == T_is_signed);
|
||||
static_assert(std::is_unsigned_v<T> == !T_is_signed);
|
||||
template <class U, bool U_is_signed>
|
||||
static inline void checkU(void) noexcept {
|
||||
static_assert(std::is_integral_v<U>);
|
||||
static_assert(std::is_signed_v<U> == U_is_signed);
|
||||
static_assert(std::is_unsigned_v<U> == !U_is_signed);
|
||||
static_assert(sizeof(U) == sizeof(T));
|
||||
static_assert(alignof(U) == alignof(T));
|
||||
constexpr U all_bits = (U) (U(0) - U(1));
|
||||
constexpr U all_bits = U(U(0) - U(1));
|
||||
static_assert(all_bits == U(~U(0)));
|
||||
static_assert(U_is_signed ? (all_bits < 0) : (all_bits > 0));
|
||||
}
|
||||
static void check(void) noexcept {
|
||||
@ -490,6 +685,23 @@ struct CheckSignedness {
|
||||
}
|
||||
};
|
||||
|
||||
template <class A, class B>
|
||||
struct CheckTypePair {
|
||||
static_assert(std::is_integral_v<A>);
|
||||
static_assert(std::is_integral_v<B>);
|
||||
static_assert(std::is_signed_v<A>);
|
||||
static_assert(!std::is_unsigned_v<A>);
|
||||
static_assert(std::is_unsigned_v<B>);
|
||||
static_assert(!std::is_signed_v<B>);
|
||||
static_assert(std::is_same_v<A, std::make_signed_t<A> >);
|
||||
static_assert(std::is_same_v<A, std::make_signed_t<B> >);
|
||||
static_assert(std::is_same_v<B, std::make_unsigned_t<A> >);
|
||||
static_assert(std::is_same_v<B, std::make_unsigned_t<B> >);
|
||||
static_assert(sizeof(A) == sizeof(B));
|
||||
static_assert(alignof(A) == alignof(B));
|
||||
static inline void check(void) noexcept {}
|
||||
};
|
||||
|
||||
template <class A, class B>
|
||||
struct TestNoAliasingStruct { // check working -fno-strict-aliasing
|
||||
static noinline bool test(A *a, B *b) noexcept {
|
||||
@ -657,7 +869,10 @@ void upx_compiler_sanity_check(void) noexcept {
|
||||
static_assert(sizeof(short) == 2);
|
||||
static_assert(sizeof(int) == 4);
|
||||
static_assert(sizeof(long) >= 4);
|
||||
static_assert(sizeof(long long) >= 8);
|
||||
static_assert(sizeof(void *) >= 4);
|
||||
static_assert(sizeof(upx_off_t) >= 8);
|
||||
static_assert(sizeof(upx_off_t) >= sizeof(long long));
|
||||
|
||||
static_assert(sizeof(BE16) == 2);
|
||||
static_assert(sizeof(BE32) == 4);
|
||||
@ -673,36 +888,153 @@ void upx_compiler_sanity_check(void) noexcept {
|
||||
COMPILE_TIME_ASSERT_ALIGNED1(LE32)
|
||||
COMPILE_TIME_ASSERT_ALIGNED1(LE64)
|
||||
|
||||
// check that these types are not some multi-word macro
|
||||
#define CHECK_TYPE(T) (void) (T())
|
||||
CHECK_TYPE(int8_t);
|
||||
CHECK_TYPE(uint8_t);
|
||||
CHECK_TYPE(int16_t);
|
||||
CHECK_TYPE(uint16_t);
|
||||
CHECK_TYPE(int32_t);
|
||||
CHECK_TYPE(uint32_t);
|
||||
CHECK_TYPE(int64_t);
|
||||
CHECK_TYPE(uint64_t);
|
||||
CHECK_TYPE(intmax_t);
|
||||
CHECK_TYPE(uintmax_t);
|
||||
CHECK_TYPE(ptrdiff_t);
|
||||
CHECK_TYPE(size_t);
|
||||
CHECK_TYPE(intptr_t);
|
||||
CHECK_TYPE(uintptr_t);
|
||||
#if 0
|
||||
CHECK_TYPE(acc_int8_t);
|
||||
CHECK_TYPE(acc_uint8_t);
|
||||
CHECK_TYPE(acc_int16_t);
|
||||
CHECK_TYPE(acc_uint16_t);
|
||||
CHECK_TYPE(acc_int32_t);
|
||||
CHECK_TYPE(acc_uint32_t);
|
||||
CHECK_TYPE(acc_int64_t);
|
||||
CHECK_TYPE(acc_uint64_t);
|
||||
CHECK_TYPE(acc_intptr_t);
|
||||
CHECK_TYPE(acc_uintptr_t);
|
||||
#endif
|
||||
CHECK_TYPE(upx_int8_t);
|
||||
CHECK_TYPE(upx_uint8_t);
|
||||
CHECK_TYPE(upx_int16_t);
|
||||
CHECK_TYPE(upx_uint16_t);
|
||||
CHECK_TYPE(upx_int32_t);
|
||||
CHECK_TYPE(upx_uint32_t);
|
||||
CHECK_TYPE(upx_int64_t);
|
||||
CHECK_TYPE(upx_uint64_t);
|
||||
#if (__SIZEOF_INT128__ == 16)
|
||||
CHECK_TYPE(upx_int128_t);
|
||||
CHECK_TYPE(upx_uint128_t);
|
||||
#endif
|
||||
CHECK_TYPE(upx_ptraddr_t);
|
||||
CHECK_TYPE(upx_uintptr_t);
|
||||
CHECK_TYPE(upx_uptrdiff_t);
|
||||
CHECK_TYPE(upx_ssize_t);
|
||||
#undef CHECK_TYPE
|
||||
|
||||
CheckIntegral<char>::check();
|
||||
CheckIntegral<signed char>::check();
|
||||
CheckIntegral<unsigned char>::check();
|
||||
CheckIntegral<short>::check();
|
||||
CheckIntegral<unsigned short>::check();
|
||||
CheckIntegral<int>::check();
|
||||
CheckIntegral<unsigned>::check();
|
||||
CheckIntegral<long>::check();
|
||||
CheckIntegral<unsigned long>::check();
|
||||
CheckIntegral<long long>::check();
|
||||
CheckIntegral<unsigned long long>::check();
|
||||
CheckIntegral<intmax_t>::check();
|
||||
CheckIntegral<uintmax_t>::check();
|
||||
CheckIntegral<upx_int8_t>::check();
|
||||
CheckIntegral<upx_uint8_t>::check();
|
||||
CheckIntegral<upx_int16_t>::check();
|
||||
CheckIntegral<upx_uint16_t>::check();
|
||||
CheckIntegral<upx_int32_t>::check();
|
||||
CheckIntegral<upx_uint32_t>::check();
|
||||
CheckIntegral<upx_int64_t>::check();
|
||||
CheckIntegral<upx_uint64_t>::check();
|
||||
CheckIntegral<upx_off_t>::check();
|
||||
CheckIntegral<ptrdiff_t>::check();
|
||||
CheckIntegral<size_t>::check();
|
||||
CheckIntegral<upx_off_t>::check();
|
||||
CheckIntegral<upx_ptraddr_t>::check();
|
||||
CheckIntegral<upx_sptraddr_t>::check();
|
||||
#if defined(__CHERI__) && defined(__CHERI_PURE_CAPABILITY__)
|
||||
static_assert(sizeof(upx_ptraddr_t) == 8);
|
||||
static_assert(alignof(upx_ptraddr_t) == 8);
|
||||
static_assert(sizeof(void *) == 16);
|
||||
static_assert(alignof(void *) == 16);
|
||||
static_assert(sizeof(uintptr_t) == 16);
|
||||
static_assert(alignof(uintptr_t) == 16);
|
||||
// warning: binary expression on capability types 'unsigned __intcap' and 'unsigned __intcap'
|
||||
CheckIntegral<intptr_t>::check_core();
|
||||
CheckIntegral<uintptr_t>::check_core();
|
||||
CheckIntegral<upx_uintptr_t>::check_core();
|
||||
#else
|
||||
CheckIntegral<intptr_t>::check();
|
||||
CheckIntegral<uintptr_t>::check();
|
||||
CheckIntegral<upx_uintptr_t>::check();
|
||||
#endif
|
||||
#if (__SIZEOF_INT128__ == 16)
|
||||
CheckIntegral<upx_int128_t>::check();
|
||||
CheckIntegral<upx_uint128_t>::check();
|
||||
#endif
|
||||
|
||||
CheckSignedness<char, false>::check(); // -funsigned-char
|
||||
CheckSignedness<signed char, true>::check();
|
||||
CheckSignedness<unsigned char, false>::check();
|
||||
CheckSignedness<short, true>::check();
|
||||
CheckSignedness<unsigned short, false>::check();
|
||||
CheckSignedness<int, true>::check();
|
||||
CheckSignedness<unsigned, false>::check();
|
||||
CheckSignedness<long, true>::check();
|
||||
CheckSignedness<unsigned long, false>::check();
|
||||
CheckSignedness<long long, true>::check();
|
||||
CheckSignedness<ptrdiff_t, true>::check();
|
||||
CheckSignedness<intptr_t, true>::check();
|
||||
CheckSignedness<unsigned long long, false>::check();
|
||||
CheckSignedness<size_t, false>::check();
|
||||
CheckSignedness<uintptr_t, false>::check();
|
||||
CheckSignedness<intmax_t, true>::check();
|
||||
CheckSignedness<uintmax_t, false>::check();
|
||||
CheckSignedness<upx_int8_t, true>::check();
|
||||
CheckSignedness<upx_uint8_t, false>::check();
|
||||
CheckSignedness<upx_int16_t, true>::check();
|
||||
CheckSignedness<upx_uint16_t, false>::check();
|
||||
CheckSignedness<upx_int32_t, true>::check();
|
||||
CheckSignedness<upx_uint32_t, false>::check();
|
||||
CheckSignedness<upx_int64_t, true>::check();
|
||||
CheckSignedness<upx_uint64_t, false>::check();
|
||||
#if (__SIZEOF_INT128__ == 16)
|
||||
CheckSignedness<upx_int128_t, true>::check();
|
||||
CheckSignedness<upx_uint128_t, false>::check();
|
||||
#endif
|
||||
CheckSignedness<upx_off_t, true>::check();
|
||||
CheckSignedness<ptrdiff_t, true>::check();
|
||||
CheckSignedness<size_t, false>::check();
|
||||
CheckSignedness<upx_ptraddr_t, false>::check();
|
||||
CheckSignedness<upx_sptraddr_t, true>::check();
|
||||
CheckSignedness<intptr_t, true>::check();
|
||||
CheckSignedness<uintptr_t, false>::check();
|
||||
CheckSignedness<upx_uintptr_t, false>::check();
|
||||
|
||||
#define CHECK_TYPE_PAIR(A, B) \
|
||||
CheckTypePair<A, B>::check(); \
|
||||
static_assert(alignof(A) == alignof(B))
|
||||
CHECK_TYPE_PAIR(signed char, unsigned char);
|
||||
CHECK_TYPE_PAIR(short, unsigned short);
|
||||
CHECK_TYPE_PAIR(int, unsigned);
|
||||
CHECK_TYPE_PAIR(long, unsigned long);
|
||||
CHECK_TYPE_PAIR(long long, unsigned long long);
|
||||
CHECK_TYPE_PAIR(intmax_t, uintmax_t);
|
||||
CHECK_TYPE_PAIR(upx_int16_t, upx_uint16_t);
|
||||
CHECK_TYPE_PAIR(upx_int32_t, upx_uint32_t);
|
||||
CHECK_TYPE_PAIR(upx_int64_t, upx_uint64_t);
|
||||
#if (__SIZEOF_INT128__ == 16)
|
||||
CHECK_TYPE_PAIR(upx_int128_t, upx_uint128_t);
|
||||
#endif
|
||||
CHECK_TYPE_PAIR(ptrdiff_t, upx_uptrdiff_t);
|
||||
CHECK_TYPE_PAIR(upx_ssize_t, size_t);
|
||||
CHECK_TYPE_PAIR(upx_sptraddr_t, upx_ptraddr_t);
|
||||
CHECK_TYPE_PAIR(intptr_t, uintptr_t);
|
||||
CHECK_TYPE_PAIR(acc_intptr_t, acc_uintptr_t);
|
||||
#undef CHECK_TYPE_PAIR
|
||||
|
||||
static_assert(sizeof(upx_charptr_unit_type) == 1);
|
||||
COMPILE_TIME_ASSERT_ALIGNED1(upx_charptr_unit_type)
|
||||
static_assert(sizeof(*((charptr) nullptr)) == 1);
|
||||
@ -751,6 +1083,7 @@ void upx_compiler_sanity_check(void) noexcept {
|
||||
0, 0, 0, 0, 0, 0, 0, 0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, 0,
|
||||
0, 0, 0, 0x7f, 0x7e, 0x7d, 0x7c, 0x7b, 0x7a, 0x79, 0x78, 0, 0, 0, 0, 0};
|
||||
constexpr const byte *d = dd + 7;
|
||||
assert_noexcept(ptr_is_aligned<16>(dd));
|
||||
static_assert(upx::compile_time::get_be16(d) == 0xfffe);
|
||||
static_assert(upx::compile_time::get_be24(d) == 0xfffefd);
|
||||
static_assert(upx::compile_time::get_be32(d) == 0xfffefdfc);
|
||||
@ -874,7 +1207,7 @@ void upx_compiler_sanity_check(void) noexcept {
|
||||
assert_noexcept(sign_extend(u, 7) == ((i & 64) ? -64 + (i & 63) : (i & 63)));
|
||||
assert_noexcept(sign_extend(u, 8) == ((i & 128) ? -128 + (i & 127) : (i & 127)));
|
||||
assert_noexcept(sign_extend(u, 64) == i);
|
||||
assert_noexcept(sign_extend(0ull - u, 64) == -i);
|
||||
assert_noexcept(sign_extend(upx_uint64_t(0) - u, 64) == -i);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1041,7 +1374,7 @@ TEST_CASE("libc snprintf") {
|
||||
// runtime check that Windows/MinGW <stdio.h> works as expected
|
||||
char buf[64];
|
||||
long long ll = acc_vget_int(-1, 0);
|
||||
unsigned long long llu = (unsigned long long) ll;
|
||||
unsigned long long llu = (upx_uint64_t) (upx_int64_t) ll;
|
||||
snprintf(buf, sizeof(buf), "%d.%ld.%lld.%u.%lu.%llu", -3, -2L, ll, 3U, 2LU, llu);
|
||||
CHECK_EQ(strcmp(buf, "-3.-2.-1.3.2.18446744073709551615"), 0);
|
||||
intmax_t im = ll;
|
||||
@ -1078,7 +1411,7 @@ TEST_CASE("libc qsort") {
|
||||
const Elem *a = (const Elem *) aa;
|
||||
const Elem *b = (const Elem *) bb;
|
||||
assert_noexcept(a->id != b->id); // check not IDENTICAL
|
||||
return a->value < b->value ? -1 : (a->value == b->value ? 0 : 1);
|
||||
return a->value == b->value ? 0 : (a->value < b->value ? -1 : 1);
|
||||
}
|
||||
static noinline bool check_sort(upx_sort_func_t sort, Elem *e, size_t n, bool is_stable) {
|
||||
upx_uint32_t x = 5381 + (upx_rand() & 255);
|
||||
|
||||
@ -204,8 +204,11 @@ static_assert(!upx::is_same_any_v<int, char, long>);
|
||||
|
||||
static_assert(upx::is_same_any_v<ptrdiff_t, int, long, long long>);
|
||||
static_assert(upx::is_same_any_v<size_t, unsigned, unsigned long, unsigned long long>);
|
||||
// TODO later: CHERI
|
||||
#if defined(__CHERI__) && defined(__CHERI_PURE_CAPABILITY__)
|
||||
static_assert(!upx::is_same_any_v<upx_uintptr_t, unsigned, unsigned long, unsigned long long>);
|
||||
#else
|
||||
static_assert(upx::is_same_any_v<upx_uintptr_t, unsigned, unsigned long, unsigned long long>);
|
||||
#endif
|
||||
|
||||
/*************************************************************************
|
||||
// <bit>
|
||||
@ -241,10 +244,12 @@ static_assert(upx::min<upx_int8_t>(1, 2) == 1);
|
||||
static_assert(upx::min<upx_int16_t>(1, 2) == 1);
|
||||
static_assert(upx::min<upx_int32_t>(1, 2) == 1);
|
||||
static_assert(upx::min<upx_int64_t>(1, 2) == 1);
|
||||
static_assert(upx::min<intmax_t>(1, 2) == 1);
|
||||
static_assert(upx::max<upx_int8_t>(1, 2) == 2);
|
||||
static_assert(upx::max<upx_int16_t>(1, 2) == 2);
|
||||
static_assert(upx::max<upx_int32_t>(1, 2) == 2);
|
||||
static_assert(upx::max<upx_int64_t>(1, 2) == 2);
|
||||
static_assert(upx::max<intmax_t>(1, 2) == 2);
|
||||
|
||||
static_assert(upx::min(1, 2) == 1);
|
||||
static_assert(upx::min(1l, 2l) == 1);
|
||||
@ -257,10 +262,12 @@ static_assert(upx::umin<upx_uint8_t>(1, 2) == 1);
|
||||
static_assert(upx::umin<upx_uint16_t>(1, 2) == 1);
|
||||
static_assert(upx::umin<upx_uint32_t>(1, 2) == 1);
|
||||
static_assert(upx::umin<upx_uint64_t>(1, 2) == 1);
|
||||
static_assert(upx::umin<uintmax_t>(1, 2) == 1);
|
||||
static_assert(upx::umax<upx_uint8_t>(1, 2) == 2);
|
||||
static_assert(upx::umax<upx_uint16_t>(1, 2) == 2);
|
||||
static_assert(upx::umax<upx_uint32_t>(1, 2) == 2);
|
||||
static_assert(upx::umax<upx_uint64_t>(1, 2) == 2);
|
||||
static_assert(upx::umax<uintmax_t>(1, 2) == 2);
|
||||
|
||||
static_assert(upx::umin(1u, 2u) == 1);
|
||||
static_assert(upx::umin(1ul, 2ul) == 1);
|
||||
|
||||
23
src/conf.h
23
src/conf.h
@ -153,10 +153,19 @@ typedef acc_int32_t upx_int32_t;
|
||||
typedef acc_uint32_t upx_uint32_t;
|
||||
typedef acc_int64_t upx_int64_t;
|
||||
typedef acc_uint64_t upx_uint64_t;
|
||||
#if (__SIZEOF_INT128__ == 16)
|
||||
typedef __int128 upx_int128_t;
|
||||
typedef unsigned __int128 upx_uint128_t;
|
||||
#endif
|
||||
typedef acc_uintptr_t upx_uintptr_t;
|
||||
// see CHERI ptraddr_t / vaddr_t
|
||||
typedef acc_uintptr_t upx_ptraddr_t;
|
||||
typedef acc_intptr_t upx_sptraddr_t;
|
||||
#if defined(__PTRADDR_TYPE__) // CHERI
|
||||
typedef __PTRADDR_TYPE__ upx_ptraddr_t;
|
||||
#else
|
||||
typedef upx_uintptr_t upx_ptraddr_t;
|
||||
#endif
|
||||
typedef std::make_signed_t<upx_ptraddr_t> upx_sptraddr_t; // signed ptraddr_t
|
||||
typedef std::make_unsigned_t<ptrdiff_t> upx_uptrdiff_t; // unsigned ptrdiff_t
|
||||
typedef std::make_signed_t<size_t> upx_ssize_t; // signed size_t
|
||||
|
||||
// UPX convention: use "byte" when dealing with data; use "char/uchar" when dealing
|
||||
// with strings; use "upx_uint8_t" when dealing with small integers
|
||||
@ -172,7 +181,11 @@ struct alignas(1) upx_charptr_unit_type final { char hidden__; };
|
||||
static_assert(sizeof(upx_charptr_unit_type) == 1);
|
||||
|
||||
// using the system off_t was a bad idea even back in 199x...
|
||||
typedef upx_int64_t upx_off_t;
|
||||
#if (__SIZEOF_INT128__ == 16) && 0
|
||||
typedef upx_int128_t upx_off_t;
|
||||
#else
|
||||
typedef long long upx_off_t;
|
||||
#endif
|
||||
#undef off_t
|
||||
#if 0
|
||||
// TODO later cleanup: at some future point we can do this:
|
||||
@ -845,5 +858,7 @@ int upx_test_overlap ( const upx_bytep buf,
|
||||
// xspan
|
||||
#include "util/raw_bytes.h"
|
||||
#include "util/xspan.h"
|
||||
//
|
||||
#include "util/system_check_predefs.h"
|
||||
|
||||
/* vim:set ts=4 sw=4 et: */
|
||||
|
||||
14
src/file.cpp
14
src/file.cpp
@ -321,23 +321,21 @@ upx_off_t OutputFile::seek(upx_off_t off, int whence) {
|
||||
mem_size_assert(1, off >= 0 ? off : -off); // sanity check
|
||||
assert(!opt->to_stdout);
|
||||
switch (whence) {
|
||||
case SEEK_SET: {
|
||||
if (bytes_written < off) {
|
||||
case SEEK_SET:
|
||||
if (bytes_written < off)
|
||||
bytes_written = off;
|
||||
}
|
||||
_length = bytes_written; // cheap, lazy update; needed?
|
||||
} break;
|
||||
case SEEK_END: {
|
||||
break;
|
||||
case SEEK_END:
|
||||
_length = bytes_written; // necessary
|
||||
} break;
|
||||
break;
|
||||
}
|
||||
return super::seek(off, whence);
|
||||
}
|
||||
|
||||
// WARNING: fsync() does not exist in some Windows environments.
|
||||
// This trick works only on UNIX-like systems.
|
||||
// int OutputFile::read(void *buf, int len)
|
||||
//{
|
||||
// int OutputFile::read(void *buf, int len) {
|
||||
// fsync(_fd);
|
||||
// InputFile infile;
|
||||
// infile.open(this->getName(), O_RDONLY | O_BINARY);
|
||||
|
||||
@ -355,6 +355,7 @@ static int s_ct24arm_be(Filter *f) {
|
||||
**************************************************************************/
|
||||
|
||||
#if 1 //{ old reliable
|
||||
|
||||
#define CT26ARM_LE(f, cond, addvalue, get, set) \
|
||||
byte *b = f->buf; \
|
||||
byte *b_end = b + f->buf_len - 4; \
|
||||
@ -387,10 +388,9 @@ static int s_ct26arm_le(Filter *f) {
|
||||
|
||||
#else //}{ new enhanced but DIFFERENT; need new filter type!
|
||||
|
||||
static int CTarm64(Filter *f, int dir) // dir: 1, 0, -1
|
||||
{
|
||||
upx_byte *b = f->buf; // will be incremented
|
||||
upx_byte *const b_end = b + f->buf_len - 4;
|
||||
static int CTarm64(Filter *f, int dir) { // dir: 1, 0, -1
|
||||
byte *b = f->buf; // will be incremented
|
||||
byte *const b_end = b + f->buf_len - 4;
|
||||
do {
|
||||
unsigned const a = b - f->buf;
|
||||
int const d = dir * (f->addvalue + (a >> 2));
|
||||
|
||||
34
src/help.cpp
34
src/help.cpp
@ -114,13 +114,15 @@ struct PackerNames final {
|
||||
unsigned methods[PackerBase::MAX_METHODS];
|
||||
unsigned filters[PackerBase::MAX_FILTERS];
|
||||
};
|
||||
Entry names[MAX_NAMES];
|
||||
Entry names_array[MAX_NAMES];
|
||||
Entry *names[MAX_NAMES];
|
||||
unsigned names_count = 0;
|
||||
const Options *o = nullptr;
|
||||
|
||||
void add(const PackerBase *pb) {
|
||||
assert_noexcept(names_count < MAX_NAMES);
|
||||
Entry &e = names[names_count++];
|
||||
Entry &e = names_array[names_count];
|
||||
names[names_count++] = &e;
|
||||
e.fname = pb->getFullName(o);
|
||||
e.sname = pb->getName();
|
||||
e.methods_count = e.filters_count = 0;
|
||||
@ -147,11 +149,10 @@ struct PackerNames final {
|
||||
self->add(pb);
|
||||
return false;
|
||||
}
|
||||
static int __acc_cdecl_qsort compare_fname(const void *a, const void *b) {
|
||||
return strcmp(((const Entry *) a)->fname, ((const Entry *) b)->fname);
|
||||
}
|
||||
static int __acc_cdecl_qsort compare_sname(const void *a, const void *b) {
|
||||
return strcmp(((const Entry *) a)->sname, ((const Entry *) b)->sname);
|
||||
static int __acc_cdecl_qsort compare_fname(const void *aa, const void *bb) {
|
||||
const Entry *a = *(const Entry *const *) aa;
|
||||
const Entry *b = *(const Entry *const *) bb;
|
||||
return strcmp(a->fname, b->fname);
|
||||
}
|
||||
};
|
||||
} // namespace
|
||||
@ -162,10 +163,10 @@ static noinline void list_all_packers(FILE *f, int verbose) {
|
||||
PackerNames pn;
|
||||
pn.o = &o;
|
||||
(void) PackMaster::visitAllPackers(PackerNames::visit, nullptr, &o, &pn);
|
||||
upx_gnomesort(pn.names, pn.names_count, sizeof(PackerNames::Entry), PackerNames::compare_fname);
|
||||
upx_gnomesort(pn.names, pn.names_count, sizeof(pn.names[0]), PackerNames::compare_fname);
|
||||
size_t pos = 0;
|
||||
for (size_t i = 0; i < pn.names_count; i++) {
|
||||
const PackerNames::Entry &e = pn.names[i];
|
||||
const PackerNames::Entry &e = *pn.names[i];
|
||||
const char *const fn = e.fname;
|
||||
const char *const sn = e.sname;
|
||||
if (verbose >= 3) {
|
||||
@ -570,6 +571,12 @@ void show_sysinfo(const char *options_var) {
|
||||
#endif
|
||||
|
||||
// architecture
|
||||
#if defined(__CHERI__)
|
||||
cf_print("__CHERI__", "%lld", __CHERI__ + 0, 3);
|
||||
#endif
|
||||
#if defined(__CHERI_PURE_CAPABILITY__)
|
||||
cf_print("__CHERI_PURE_CAPABILITY__", "%lld", __CHERI_PURE_CAPABILITY__ + 0, 3);
|
||||
#endif
|
||||
#if defined(__mips_hard_float)
|
||||
cf_print("__mips_hard_float", "%lld", __mips_hard_float + 0);
|
||||
#endif
|
||||
@ -628,6 +635,15 @@ void show_sysinfo(const char *options_var) {
|
||||
#elif defined(__pie__)
|
||||
cf_print("__pie__", "%lld", __pie__ + 0, 3);
|
||||
#endif
|
||||
#if defined(__SIZEOF_INT128__)
|
||||
cf_print("__SIZEOF_INT128__", "%lld", __SIZEOF_INT128__ + 0, 3);
|
||||
#endif
|
||||
#if defined(__SIZEOF_LONG_LONG__) && (__SIZEOF_LONG_LONG__ + 0 > 8)
|
||||
cf_print("__SIZEOF_LONG_LONG__", "%lld", __SIZEOF_LONG_LONG__ + 0, 3);
|
||||
#endif
|
||||
#if defined(__SIZEOF_POINTER__) && (__SIZEOF_POINTER__ + 0 > 8)
|
||||
cf_print("__SIZEOF_POINTER__", "%lld", __SIZEOF_POINTER__ + 0, 3);
|
||||
#endif
|
||||
#if defined(UPX_CONFIG_DISABLE_WSTRICT)
|
||||
cf_print("UPX_CONFIG_DISABLE_WSTRICT", "%lld", UPX_CONFIG_DISABLE_WSTRICT + 0, 3);
|
||||
#endif
|
||||
|
||||
@ -43,6 +43,11 @@
|
||||
#include "p_lx_elf.h"
|
||||
#include "ui.h"
|
||||
|
||||
#if defined(__CHERI__) && defined(__CHERI_PURE_CAPABILITY__)
|
||||
# pragma clang diagnostic ignored "-Wcheri-capability-misuse" // TODO later
|
||||
# pragma clang diagnostic ignored "-Wcheri-provenance" // TODO later
|
||||
#endif
|
||||
|
||||
using upx::umin;
|
||||
|
||||
#define PT_LOAD32 Elf32_Phdr::PT_LOAD
|
||||
@ -5068,7 +5073,7 @@ int PackLinuxElf32::pack2(OutputFile *fo, Filter &ft)
|
||||
asl_pack2_Shdrs(fo, pre_xct_top);
|
||||
}
|
||||
else { // Just copy up to xct_off
|
||||
x.size = umin(0ull + x.size, 0ull + xct_off - x.offset);
|
||||
x.size = umin(uintmax_t(x.size), uintmax_t(0ull + xct_off - x.offset));
|
||||
if (0) { // DEBUG paranoia
|
||||
fi->seek(x.offset, SEEK_SET);
|
||||
fi->readx(ibuf, x.size);
|
||||
@ -5328,7 +5333,7 @@ int PackLinuxElf64::pack2(OutputFile *fo, Filter &ft)
|
||||
asl_pack2_Shdrs(fo, pre_xct_top);
|
||||
}
|
||||
else { // Just copy up to xct_off
|
||||
x.size = umin(0ull + x.size, 0ull + xct_off - x.offset);
|
||||
x.size = umin(uintmax_t(x.size), uintmax_t(0ull + xct_off - x.offset));
|
||||
if (0) { // DEBUG paranoia
|
||||
fi->seek(x.offset, SEEK_SET);
|
||||
fi->readx(ibuf, x.size);
|
||||
|
||||
@ -44,6 +44,9 @@
|
||||
#if (ACC_CC_GNUC >= 0x040200)
|
||||
# pragma GCC diagnostic ignored "-Wcast-align"
|
||||
#endif
|
||||
#if defined(__CHERI__) && defined(__CHERI_PURE_CAPABILITY__)
|
||||
# pragma clang diagnostic ignored "-Wcheri-capability-misuse" // TODO later
|
||||
#endif
|
||||
|
||||
static const CLANG_FORMAT_DUMMY_STATEMENT
|
||||
#include "stub/i386-darwin.macho-entry.h"
|
||||
|
||||
@ -346,7 +346,7 @@ int PackVmlinuzI386::decompressKernel()
|
||||
// some checks
|
||||
if (fd_pos != file_size)
|
||||
{
|
||||
NO_printf("fd_pos: %lld, file_size: %lld\n", fd_pos, file_size);
|
||||
NO_printf("fd_pos: %jd, file_size: %lld\n", (intmax_t) fd_pos, file_size);
|
||||
|
||||
// linux-2.6.21.5/arch/i386/boot/compressed/vmlinux.lds
|
||||
// puts .data.compressed ahead of .text, .rodata, etc;
|
||||
|
||||
@ -258,7 +258,7 @@ void PeFile::Interval::add_interval(const Interval *other) {
|
||||
void PeFile::Interval::flatten() {
|
||||
if (!ivnum)
|
||||
return;
|
||||
upx_qsort(ivarr, ivnum, sizeof(interval), Interval::compare);
|
||||
upx_qsort(ivarr, ivnum, sizeof(ivarr[0]), Interval::compare);
|
||||
for (unsigned ic = 0; ic < ivnum - 1; ic++) {
|
||||
unsigned jc;
|
||||
for (jc = ic + 1; jc < ivnum && ivarr[ic].start + ivarr[ic].len >= ivarr[jc].start; jc++)
|
||||
@ -878,7 +878,7 @@ public:
|
||||
|
||||
// sort the sections by name before adding them all
|
||||
// NOLINTNEXTLINE(bugprone-multi-level-implicit-pointer-conversion)
|
||||
upx_qsort(sections, nsections, sizeof(Section *), ImportLinker::compare);
|
||||
upx_qsort(sections, nsections, sizeof(sections[0]), ImportLinker::compare);
|
||||
|
||||
for (unsigned ic = 0; ic < nsections; ic++)
|
||||
addLoader(sections[ic]->name);
|
||||
@ -1063,7 +1063,7 @@ unsigned PeFile::processImports0(ord_mask_t ord_mask) { // pass 1
|
||||
oimport = mb_oimport;
|
||||
|
||||
// NOLINTNEXTLINE(bugprone-multi-level-implicit-pointer-conversion)
|
||||
upx_qsort(idlls, dllnum, sizeof(*idlls), UDll::compare);
|
||||
upx_qsort(idlls, dllnum, sizeof(idlls[0]), UDll::compare);
|
||||
|
||||
info("Processing imports: %d DLLs", dllnum);
|
||||
for (unsigned ic = 0; ic < dllnum; ic++) {
|
||||
|
||||
@ -219,8 +219,7 @@ forceinline constexpr T max(const T &a, const T &b) noexcept {
|
||||
}
|
||||
|
||||
template <class T>
|
||||
inline constexpr bool is_uminmax_type =
|
||||
is_same_any_v<T, upx_uint8_t, upx_uint16_t, upx_uint32_t, upx_uint64_t, unsigned long, size_t>;
|
||||
inline constexpr bool is_uminmax_type = std::is_integral_v<T> && std::is_unsigned_v<T>;
|
||||
|
||||
template <class T, class = std::enable_if_t<is_uminmax_type<T>, T> >
|
||||
forceinline constexpr T umin(const T &a, const T &b) noexcept {
|
||||
|
||||
@ -49,6 +49,8 @@ unsigned membuffer_get_size(MemBuffer &mb) noexcept { return mb.getSize(); }
|
||||
|
||||
#if defined(__SANITIZE_ADDRESS__) || defined(__SANITIZE_MEMORY__)
|
||||
static forceinline constexpr bool use_simple_mcheck() noexcept { return false; }
|
||||
#elif defined(__CHERI__) && defined(__CHERI_PURE_CAPABILITY__)
|
||||
static forceinline constexpr bool use_simple_mcheck() noexcept { return false; }
|
||||
#elif (WITH_VALGRIND) && defined(RUNNING_ON_VALGRIND)
|
||||
static bool use_simple_mcheck_flag;
|
||||
static noinline void init_use_simple_mcheck() noexcept {
|
||||
|
||||
158
src/util/system_check_predefs.h
Normal file
158
src/util/system_check_predefs.h
Normal file
@ -0,0 +1,158 @@
|
||||
/* system_check_predefs.h -- check pre-defined macros
|
||||
|
||||
This file is part of the UPX executable compressor.
|
||||
|
||||
Copyright (C) 1996-2024 Markus Franz Xaver Johannes Oberhumer
|
||||
All Rights Reserved.
|
||||
|
||||
UPX and the UCL library are free software; you can redistribute them
|
||||
and/or modify them under the terms of the GNU General Public License as
|
||||
published by the Free Software Foundation; either version 2 of
|
||||
the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; see the file COPYING.
|
||||
If not, write to the Free Software Foundation, Inc.,
|
||||
59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
Markus F.X.J. Oberhumer
|
||||
<markus@oberhumer.com>
|
||||
*/
|
||||
|
||||
// windows defines
|
||||
#if defined(__CYGWIN32__) && !defined(__CYGWIN__)
|
||||
#error "missing __CYGWIN__"
|
||||
#endif
|
||||
#if defined(__CYGWIN64__) && !defined(__CYGWIN__)
|
||||
#error "missing __CYGWIN__"
|
||||
#endif
|
||||
#if defined(__CYGWIN__) && defined(_WIN32)
|
||||
#error "unexpected _WIN32"
|
||||
#endif
|
||||
#if defined(__CYGWIN__) && defined(_WIN64)
|
||||
#error "unexpected _WIN64"
|
||||
#endif
|
||||
#if defined(__MINGW64__) && !defined(__MINGW32__)
|
||||
#error "missing __MINGW32__"
|
||||
#endif
|
||||
#if defined(__MINGW32__) && !defined(_WIN32)
|
||||
#error "missing _WIN32"
|
||||
#endif
|
||||
#if defined(__MINGW64__) && !defined(_WIN64)
|
||||
#error "missing _WIN64"
|
||||
#endif
|
||||
#if defined(_WIN64) && !defined(_WIN32)
|
||||
#error "missing _WIN32"
|
||||
#endif
|
||||
|
||||
// available since gcc-4.3 (2008), clang-2.7 (2010) and msvc-20XX
|
||||
#if !defined(__COUNTER__)
|
||||
#error "missing __COUNTER__"
|
||||
#endif
|
||||
|
||||
// fundamental type sizes - these are pre-defined since gcc-4.3 (2008) and clang-2.8 (2010)
|
||||
#if defined(__clang__) || defined(__GNUC__)
|
||||
#if !defined(__SIZEOF_SHORT__)
|
||||
#error "missing __SIZEOF_SHORT__"
|
||||
#endif
|
||||
#if !defined(__SIZEOF_INT__)
|
||||
#error "missing __SIZEOF_INT__"
|
||||
#endif
|
||||
#if !defined(__SIZEOF_LONG__)
|
||||
#error "missing __SIZEOF_LONG__"
|
||||
#endif
|
||||
#if !defined(__SIZEOF_LONG_LONG__)
|
||||
#error "missing __SIZEOF_LONG_LONG__"
|
||||
#endif
|
||||
#if !defined(__SIZEOF_PTRDIFF_T__)
|
||||
#error "missing __SIZEOF_PTRDIFF_T__"
|
||||
#endif
|
||||
#if !defined(__SIZEOF_SIZE_T__)
|
||||
#error "missing __SIZEOF_SIZE_T__"
|
||||
#endif
|
||||
#if !defined(__SIZEOF_POINTER__)
|
||||
#error "missing __SIZEOF_POINTER__"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// fundamental types - these are pre-defined since gcc-4.5 (2010) and clang-3.5 (2014)
|
||||
#if defined(__clang__) || defined(__GNUC__)
|
||||
#if !defined(__PTRDIFF_TYPE__)
|
||||
#error "missing __PTRDIFF_TYPE__"
|
||||
#endif
|
||||
#if !defined(__SIZE_TYPE__)
|
||||
#error "missing __SIZE_TYPE__"
|
||||
#endif
|
||||
#if !defined(__INTPTR_TYPE__)
|
||||
#error "missing __INTPTR_TYPE__"
|
||||
#endif
|
||||
#if !defined(__UINTPTR_TYPE__)
|
||||
#error "missing __UINTPTR_TYPE__"
|
||||
#endif
|
||||
#endif
|
||||
#if defined(__PTRADDR_TYPE__) && !defined(__PTRADDR_WIDTH__)
|
||||
#error "missing __PTRADDR_WIDTH__"
|
||||
#elif defined(__PTRADDR_WIDTH__) && !defined(__PTRADDR_TYPE__)
|
||||
#error "missing __PTRADDR_TYPE__"
|
||||
#endif
|
||||
|
||||
// byte order - these are pre-defined since gcc-4.6 (2011) and clang-3.2 (2012)
|
||||
#if defined(__clang__) || defined(__GNUC__)
|
||||
#if !defined(__ORDER_BIG_ENDIAN__) || (__ORDER_BIG_ENDIAN__ + 0 == 0)
|
||||
#error "missing __ORDER_BIG_ENDIAN__"
|
||||
#endif
|
||||
#if !defined(__ORDER_LITTLE_ENDIAN__) || (__ORDER_LITTLE_ENDIAN__ + 0 == 0)
|
||||
#error "missing __ORDER_LITTLE_ENDIAN__"
|
||||
#endif
|
||||
#if !defined(__BYTE_ORDER__) || (__BYTE_ORDER__ + 0 == 0)
|
||||
#error "missing __BYTE_ORDER__"
|
||||
#endif
|
||||
#if !defined(__ORDER_BIG_ENDIAN__) || (__ORDER_BIG_ENDIAN__ + 0 != 4321)
|
||||
#error "unexpected __ORDER_BIG_ENDIAN__"
|
||||
#endif
|
||||
#if !defined(__ORDER_BIG_ENDIAN__) || (__ORDER_LITTLE_ENDIAN__ + 0 != 1234)
|
||||
#error "unexpected __ORDER_BIG_ENDIAN__"
|
||||
#endif
|
||||
#if (__BYTE_ORDER__ != __ORDER_BIG_ENDIAN__) && (__BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__)
|
||||
#error "unexpected __BYTE_ORDER__"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// pic and pie
|
||||
#if defined(__PIC__) && defined(__pic__)
|
||||
#if (__PIC__ + 0) != (__pic__ + 0)
|
||||
#error "unexpected __PIC__ vs __pic__ mismatch"
|
||||
#endif
|
||||
#endif
|
||||
#if defined(__PIC__)
|
||||
#if (__PIC__ != 1) && (__PIC__ != 2)
|
||||
#error "unexpected __PIC__ value"
|
||||
#endif
|
||||
#endif
|
||||
#if defined(__pic__)
|
||||
#if (__pic__ != 1) && (__pic__ != 2)
|
||||
#error "unexpected __pic__ value"
|
||||
#endif
|
||||
#endif
|
||||
#if defined(__PIE__) && defined(__pie__)
|
||||
#if (__PIE__ + 0) != (__pie__ + 0)
|
||||
#error "unexpected __PIE__ vs __pie__ mismatch"
|
||||
#endif
|
||||
#endif
|
||||
#if defined(__PIE__)
|
||||
#if (__PIE__ != 1) && (__PIE__ != 2)
|
||||
#error "unexpected __PIE__ value"
|
||||
#endif
|
||||
#endif
|
||||
#if defined(__pie__)
|
||||
#if (__pie__ != 1) && (__pie__ != 2)
|
||||
#error "unexpected __pie__ value"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* vim:set ts=4 sw=4 et: */
|
||||
@ -26,6 +26,8 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "system_check_predefs.h"
|
||||
|
||||
#if !defined(_FILE_OFFSET_BITS)
|
||||
#define _FILE_OFFSET_BITS 64
|
||||
#endif
|
||||
@ -41,6 +43,13 @@
|
||||
#define __STDC_LIMIT_MACROS 1
|
||||
#endif
|
||||
|
||||
#if defined(__PTRADDR_TYPE__) && !defined(__SIZEOF_PTRADDR_T__)
|
||||
#if !defined(__PTRADDR_WIDTH__)
|
||||
#error "missing __PTRADDR_WIDTH__"
|
||||
#endif
|
||||
#define __SIZEOF_PTRADDR_T__ (__PTRADDR_WIDTH__ / 8)
|
||||
#endif
|
||||
|
||||
#if !defined(__USE_MINGW_ANSI_STDIO)
|
||||
#if defined(_WIN32) && defined(__MINGW32__) && (defined(__clang__) || defined(__GNUC__))
|
||||
#define __USE_MINGW_ANSI_STDIO 1
|
||||
|
||||
@ -33,62 +33,6 @@
|
||||
#error "FATAL ERROR: C++17 is required"
|
||||
#endif
|
||||
|
||||
// check expected defines
|
||||
#if defined(__CYGWIN32__) && !defined(__CYGWIN__)
|
||||
#error "missing __CYGWIN__"
|
||||
#endif
|
||||
#if defined(__CYGWIN64__) && !defined(__CYGWIN__)
|
||||
#error "missing __CYGWIN__"
|
||||
#endif
|
||||
#if defined(__MINGW64__) && !defined(__MINGW32__)
|
||||
#error "missing __MINGW32__"
|
||||
#endif
|
||||
#if defined(_WIN64) && !defined(_WIN32)
|
||||
#error "missing _WIN32"
|
||||
#endif
|
||||
|
||||
// byte order - these are pre-defined since gcc-4.6 (2011) and clang-3.2 (2012)
|
||||
#if defined(__clang__) || defined(__GNUC__)
|
||||
#if !defined(__ORDER_BIG_ENDIAN__) || (__ORDER_BIG_ENDIAN__ + 0 == 0)
|
||||
#error "missing __ORDER_BIG_ENDIAN__"
|
||||
#endif
|
||||
#if !defined(__ORDER_LITTLE_ENDIAN__) || (__ORDER_LITTLE_ENDIAN__ + 0 == 0)
|
||||
#error "missing __ORDER_LITTLE_ENDIAN__"
|
||||
#endif
|
||||
#if !defined(__BYTE_ORDER__) || (__BYTE_ORDER__ + 0 == 0)
|
||||
#error "missing __BYTE_ORDER__"
|
||||
#endif
|
||||
#if !defined(__ORDER_BIG_ENDIAN__) || (__ORDER_BIG_ENDIAN__ + 0 != 4321)
|
||||
#error "unexpected __ORDER_BIG_ENDIAN__"
|
||||
#endif
|
||||
#if !defined(__ORDER_BIG_ENDIAN__) || (__ORDER_LITTLE_ENDIAN__ + 0 != 1234)
|
||||
#error "unexpected __ORDER_BIG_ENDIAN__"
|
||||
#endif
|
||||
#if (__BYTE_ORDER__ != __ORDER_BIG_ENDIAN__) && (__BYTE_ORDER__ != __ORDER_LITTLE_ENDIAN__)
|
||||
#error "unexpected __BYTE_ORDER__"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// pic and pie
|
||||
#if defined(__PIC__) && defined(__pic__)
|
||||
static_assert((__PIC__) == (__pic__));
|
||||
#endif
|
||||
#if defined(__PIC__)
|
||||
static_assert(__PIC__ == 1 || __PIC__ == 2);
|
||||
#endif
|
||||
#if defined(__pic__)
|
||||
static_assert(__pic__ == 1 || __pic__ == 2);
|
||||
#endif
|
||||
#if defined(__PIE__) && defined(__pie__)
|
||||
static_assert((__PIE__) == (__pie__));
|
||||
#endif
|
||||
#if defined(__PIE__)
|
||||
static_assert(__PIE__ == 1 || __PIE__ == 2);
|
||||
#endif
|
||||
#if defined(__pie__)
|
||||
static_assert(__pie__ == 1 || __pie__ == 2);
|
||||
#endif
|
||||
|
||||
// sanity checks
|
||||
#if defined(_ILP32) || defined(__ILP32) || defined(__ILP32__)
|
||||
static_assert(sizeof(int) == 4);
|
||||
@ -98,8 +42,14 @@ static_assert(sizeof(void *) == 4);
|
||||
#if defined(_LP64) || defined(__LP64) || defined(__LP64__)
|
||||
static_assert(sizeof(int) == 4);
|
||||
static_assert(sizeof(long) == 8);
|
||||
#if defined(__CHERI__) && defined(__CHERI_PURE_CAPABILITY__) && (__SIZEOF_POINTER__ == 16)
|
||||
// CHERI BUG/FEATURE: obviously CHERI should *NOT* pre-define __LP64__ on P128, but
|
||||
// maybe they do this for porting/compatibility reasons...
|
||||
static_assert(sizeof(void *) == 16);
|
||||
#else
|
||||
static_assert(sizeof(void *) == 8);
|
||||
#endif
|
||||
#endif
|
||||
#if defined(_WIN32)
|
||||
static_assert(sizeof(int) == 4);
|
||||
static_assert(sizeof(long) == 4);
|
||||
@ -151,6 +101,7 @@ static_assert(sizeof(void *) == sizeof(long));
|
||||
#include <bit>
|
||||
#endif
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <exception>
|
||||
#include <new>
|
||||
#include <type_traits>
|
||||
@ -193,6 +144,9 @@ static_assert(sizeof(void *) == sizeof(long));
|
||||
!defined(__GNUC__)
|
||||
#undef WITH_VALGRIND
|
||||
#endif
|
||||
#if defined(__CHERI__) && defined(__CHERI_PURE_CAPABILITY__)
|
||||
#undef WITH_VALGRIND
|
||||
#endif
|
||||
#if WITH_VALGRIND
|
||||
#include <valgrind/include/valgrind/memcheck.h>
|
||||
#endif
|
||||
|
||||
@ -25,6 +25,7 @@
|
||||
<markus@oberhumer.com> <ezerotven+github@gmail.com>
|
||||
*/
|
||||
|
||||
#define WANT_WINDOWS_LEAN_H 1
|
||||
#include "system_headers.h"
|
||||
#define ACC_WANT_ACC_INCI_H 1
|
||||
#include "miniacc.h"
|
||||
@ -291,23 +292,24 @@ void *upx_calloc(size_t n, size_t element_size) may_throw {
|
||||
}
|
||||
|
||||
// simple unoptimized memswap()
|
||||
void upx_memswap(void *a, void *b, size_t bytes) noexcept {
|
||||
if (a != b && bytes != 0) {
|
||||
byte *x = (byte *) a;
|
||||
byte *y = (byte *) b;
|
||||
// TODO later: CHERI clang bug/miscompilation with upx_memswap() ???
|
||||
void upx_memswap(void *aa, void *bb, size_t bytes) noexcept {
|
||||
if (aa != bb && bytes != 0) {
|
||||
byte *a = (byte *) aa;
|
||||
byte *b = (byte *) bb;
|
||||
do {
|
||||
// strange clang-analyzer-15 false positive when compiling in Debug mode
|
||||
// clang-analyzer-core.uninitialized.Assign
|
||||
byte tmp = *x; // NOLINT(*core.uninitialized.Assign) // bogus clang-analyzer warning
|
||||
*x++ = *y;
|
||||
*y++ = tmp;
|
||||
byte tmp = *a; // NOLINT(*core.uninitialized.Assign) // bogus clang-analyzer warning
|
||||
*a++ = *b;
|
||||
*b++ = tmp;
|
||||
} while (--bytes != 0);
|
||||
}
|
||||
}
|
||||
|
||||
// much better memswap(), optimized for our use case in sort functions below
|
||||
static inline void memswap_no_overlap(byte *a, byte *b, size_t bytes) noexcept {
|
||||
#if defined(__clang__) && __clang_major__ < 15
|
||||
#if defined(__clang__) && (__clang_major__ < 15) && !defined(__CHERI__)
|
||||
// work around a clang < 15 ICE (Internal Compiler Error)
|
||||
// @COMPILER_BUG @CLANG_BUG
|
||||
upx_memswap(a, b, bytes);
|
||||
@ -418,6 +420,42 @@ void upx_std_stable_sort(void *array, size_t n, upx_compare_func_t compare) {
|
||||
#endif
|
||||
}
|
||||
|
||||
TEST_CASE("upx_memswap") {
|
||||
auto check4 = [](int off1, int off2, int len, int a, int b, int c, int d) {
|
||||
byte p[4] = {0, 1, 2, 3};
|
||||
assert_noexcept(a + b + c + d == 0 + 1 + 2 + 3);
|
||||
upx_memswap(p + off1, p + off2, len);
|
||||
CHECK((p[0] == a && p[1] == b && p[2] == c && p[3] == d));
|
||||
};
|
||||
// identical
|
||||
check4(0, 0, 4, 0, 1, 2, 3);
|
||||
// non-overlapping
|
||||
check4(0, 1, 1, 1, 0, 2, 3);
|
||||
check4(1, 0, 1, 1, 0, 2, 3);
|
||||
check4(0, 2, 2, 2, 3, 0, 1);
|
||||
check4(2, 0, 2, 2, 3, 0, 1);
|
||||
// overlapping
|
||||
check4(0, 1, 2, 1, 2, 0, 3);
|
||||
check4(1, 0, 2, 1, 2, 0, 3);
|
||||
check4(0, 1, 3, 1, 2, 3, 0);
|
||||
check4(1, 0, 3, 1, 2, 3, 0);
|
||||
|
||||
// pointer array
|
||||
{
|
||||
typedef byte element_type;
|
||||
element_type a = 11, b = 22;
|
||||
element_type *array[4];
|
||||
memset(array, 0xfb, sizeof(array));
|
||||
array[1] = &a;
|
||||
array[3] = &b;
|
||||
upx_memswap(array, array + 2, 2 * sizeof(array[0]));
|
||||
assert(array[1] == &b);
|
||||
assert(array[3] == &a);
|
||||
assert(*array[1] == 22);
|
||||
assert(*array[3] == 11);
|
||||
}
|
||||
}
|
||||
|
||||
#if UPX_CONFIG_USE_STABLE_SORT
|
||||
// instantiate function templates for all element sizes we need; efficient
|
||||
// run-time, but code size bloat (about 4KiB code size for each function
|
||||
|
||||
@ -93,9 +93,23 @@ T *NewArray(upx_uint64_t n) may_throw {
|
||||
// ptr util
|
||||
**************************************************************************/
|
||||
|
||||
// TODO later: CHERI; see cheri_address_get()
|
||||
#if defined(__CHERI__) && defined(__CHERI_PURE_CAPABILITY__)
|
||||
forceinline upx_ptraddr_t ptr_get_address(const void *p) noexcept {
|
||||
return __builtin_cheri_address_get(p);
|
||||
}
|
||||
forceinline upx_ptraddr_t ptr_get_address(upx_uintptr_t p) noexcept {
|
||||
return __builtin_cheri_address_get(p);
|
||||
}
|
||||
#else
|
||||
forceinline upx_ptraddr_t ptr_get_address(const void *p) noexcept { return (upx_uintptr_t) p; }
|
||||
forceinline upx_ptraddr_t ptr_get_address(upx_uintptr_t p) noexcept { return p; }
|
||||
#endif
|
||||
|
||||
template <size_t Alignment>
|
||||
forceinline bool ptr_is_aligned(const void *p) noexcept {
|
||||
static_assert(upx::has_single_bit(Alignment));
|
||||
return (ptr_get_address(p) & (Alignment - 1)) == 0;
|
||||
}
|
||||
|
||||
// ptrdiff_t with nullptr checks and asserted size; will throw on failure
|
||||
// NOTE: returns size_in_bytes, not number of elements!
|
||||
@ -138,10 +152,15 @@ forceinline void ptr_check_no_overlap(const void *a, size_t a_size, const void *
|
||||
// - this should play nice with static analyzers like clang-tidy etc.
|
||||
// NOTE: this is clearly UB (Undefined Behaviour), and stricter compilers or
|
||||
// architectures may need a more advanced/costly implementation in the future
|
||||
// TODO later: CHERI
|
||||
template <class T>
|
||||
inline void ptr_invalidate_and_poison(T *(&ptr)) noexcept {
|
||||
ptr = (T *) (void *) 251; // 0x000000fb // NOLINT(performance-no-int-to-ptr)
|
||||
#if defined(__CHERI__) && defined(__CHERI_PURE_CAPABILITY__)
|
||||
// TODO later: examine __builtin_cheri_bounds_set()
|
||||
ptr = upx::ptr_static_cast<T *>(&ptr); // FIXME: HACK: point to address of self
|
||||
#else
|
||||
// pretend there is some memory-mapped I/O at address 0x00000200
|
||||
ptr = (T *) (void *) 512; // NOLINT(performance-no-int-to-ptr)
|
||||
#endif
|
||||
}
|
||||
|
||||
/*************************************************************************
|
||||
@ -152,7 +171,7 @@ noinline void *upx_calloc(size_t n, size_t element_size) may_throw;
|
||||
|
||||
noinline const char *upx_getenv(const char *envvar) noexcept;
|
||||
|
||||
void upx_memswap(void *a, void *b, size_t bytes) noexcept;
|
||||
noinline void upx_memswap(void *a, void *b, size_t bytes) noexcept;
|
||||
|
||||
noinline void upx_rand_init(void) noexcept;
|
||||
noinline int upx_rand(void) noexcept;
|
||||
@ -174,7 +193,7 @@ void upx_std_stable_sort(void *array, size_t n, upx_compare_func_t compare);
|
||||
#define upx_qsort(a, n, element_size, compare) \
|
||||
upx_std_stable_sort<(element_size)>((a), (n), (compare))
|
||||
#else
|
||||
// use libc qsort(); good enough for our use cases
|
||||
// use libc qsort(); good enough for our use cases
|
||||
#define upx_qsort ::qsort
|
||||
#endif
|
||||
|
||||
|
||||
@ -49,4 +49,19 @@
|
||||
#define timeval win32_timeval /* struct timeval already in <sys/time.h> */
|
||||
#endif
|
||||
|
||||
#if defined(__CYGWIN__) && defined(_WIN32)
|
||||
#error "unexpected _WIN32"
|
||||
#endif
|
||||
#if defined(__CYGWIN__) && defined(_WIN64)
|
||||
#error "unexpected _WIN64"
|
||||
#endif
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
#if defined(__CYGWIN__) && defined(_WIN32)
|
||||
#error "unexpected _WIN32"
|
||||
#endif
|
||||
#if defined(__CYGWIN__) && defined(_WIN64)
|
||||
// #error "unexpected _WIN64"
|
||||
#undef _WIN64
|
||||
#endif
|
||||
|
||||
@ -207,7 +207,7 @@ public: // raw access
|
||||
pointer raw_bytes(size_t bytes) const {
|
||||
assertInvariants();
|
||||
if (bytes > 0) {
|
||||
if __acc_cte (ptr == nullptr)
|
||||
if very_unlikely (ptr == nullptr)
|
||||
xspan_fail_nullptr();
|
||||
}
|
||||
return ptr;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user