src: more upx::max cleanups

This commit is contained in:
Markus F.X.J. Oberhumer 2024-05-22 09:49:20 +02:00
parent 57763ca1e2
commit 344246725b
5 changed files with 198 additions and 79 deletions

View File

@ -42,6 +42,14 @@
#define bswap64 upx_bswap64
#endif
// forward declarations
struct BE16;
struct BE32;
struct BE64;
struct LE16;
struct LE32;
struct LE64;
/*************************************************************************
// XE - eXtended Endian compatibility
// try to detect XX16 vs XX32 vs XX64 size mismatches
@ -61,14 +69,6 @@ typedef void XE64;
#else // permissive version
// forward declarations
struct BE16;
struct BE32;
struct BE64;
struct LE16;
struct LE32;
struct LE64;
namespace bele_detail {
// Note:
@ -755,35 +755,81 @@ T *operator+(const LE64 &v, T *ptr) noexcept DELETED_FUNCTION;
namespace upx {
inline unsigned align_down(unsigned a, const BE32 &b) { return align_down(a, unsigned(b)); }
inline unsigned align_down(const BE32 &a, unsigned b) { return align_down(unsigned(a), b); }
inline unsigned align_up(unsigned a, const BE32 &b) { return align_up(a, unsigned(b)); }
inline unsigned align_up(const BE32 &a, unsigned b) { return align_up(unsigned(a), b); }
#define REQUIRE_UINT32 \
template <class T, class = std::enable_if_t<std::is_same_v<T, upx_uint32_t>, T> >
#define REQUIRE_UINT64 \
template <class T, class = std::enable_if_t<std::is_same_v<T, upx_uint64_t>, T> >
inline unsigned align_down(unsigned a, const LE32 &b) { return align_down(a, unsigned(b)); }
inline unsigned align_down(const LE32 &a, unsigned b) { return align_down(unsigned(a), b); }
inline unsigned align_up(unsigned a, const LE32 &b) { return align_up(a, unsigned(b)); }
inline unsigned align_up(const LE32 &a, unsigned b) { return align_up(unsigned(a), b); }
REQUIRE_UINT32
inline T align_down(const T &a, const BE32 &b) noexcept { return align_down(a, T(b)); }
REQUIRE_UINT32
inline T align_down(const BE32 &a, const T &b) noexcept { return align_down(T(a), b); }
REQUIRE_UINT32
inline T align_down(const T &a, const LE32 &b) noexcept { return align_down(a, T(b)); }
REQUIRE_UINT32
inline T align_down(const LE32 &a, const T &b) noexcept { return align_down(T(a), b); }
inline unsigned max(unsigned a, const BE16 &b) { return max(a, unsigned(b)); }
inline unsigned max(const BE16 &a, unsigned b) { return max(unsigned(a), b); }
inline unsigned min(unsigned a, const BE16 &b) { return min(a, unsigned(b)); }
inline unsigned min(const BE16 &a, unsigned b) { return min(unsigned(a), b); }
REQUIRE_UINT32
inline T align_up(const T &a, const LE32 &b) noexcept { return align_up(a, T(b)); }
REQUIRE_UINT32
inline T align_up(const LE32 &a, const T &b) noexcept { return align_up(T(a), b); }
REQUIRE_UINT32
inline T align_up(const T &a, const BE32 &b) noexcept { return align_up(a, T(b)); }
REQUIRE_UINT32
inline T align_up(const BE32 &a, const T &b) noexcept { return align_up(T(a), b); }
inline unsigned max(unsigned a, const BE32 &b) { return max(a, unsigned(b)); }
inline unsigned max(const BE32 &a, unsigned b) { return max(unsigned(a), b); }
inline unsigned min(unsigned a, const BE32 &b) { return min(a, unsigned(b)); }
inline unsigned min(const BE32 &a, unsigned b) { return min(unsigned(a), b); }
REQUIRE_UINT32
inline T min(const T &a, const BE16 &b) noexcept { return min(a, T(b)); }
REQUIRE_UINT32
inline T min(const BE16 &a, const T &b) noexcept { return min(T(a), b); }
REQUIRE_UINT32
inline T min(const T &a, const BE32 &b) noexcept { return min(a, T(b)); }
REQUIRE_UINT32
inline T min(const BE32 &a, const T &b) noexcept { return min(T(a), b); }
REQUIRE_UINT64
inline T min(const T &a, const BE64 &b) noexcept { return min(a, T(b)); }
REQUIRE_UINT64
inline T min(const BE64 &a, const T &b) noexcept { return min(T(a), b); }
REQUIRE_UINT32
inline T min(const T &a, const LE16 &b) noexcept { return min(a, T(b)); }
REQUIRE_UINT32
inline T min(const LE16 &a, const T &b) noexcept { return min(T(a), b); }
REQUIRE_UINT32
inline T min(const T &a, const LE32 &b) noexcept { return min(a, T(b)); }
REQUIRE_UINT32
inline T min(const LE32 &a, const T &b) noexcept { return min(T(a), b); }
REQUIRE_UINT64
inline T min(const T &a, const LE64 &b) noexcept { return min(a, T(b)); }
REQUIRE_UINT64
inline T min(const LE64 &a, const T &b) noexcept { return min(T(a), b); }
inline unsigned max(unsigned a, const LE16 &b) { return max(a, unsigned(b)); }
inline unsigned max(const LE16 &a, unsigned b) { return max(unsigned(a), b); }
inline unsigned min(unsigned a, const LE16 &b) { return min(a, unsigned(b)); }
inline unsigned min(const LE16 &a, unsigned b) { return min(unsigned(a), b); }
REQUIRE_UINT32
inline T max(const T &a, const BE16 &b) noexcept { return max(a, T(b)); }
REQUIRE_UINT32
inline T max(const BE16 &a, const T &b) noexcept { return max(T(a), b); }
REQUIRE_UINT32
inline T max(const T &a, const BE32 &b) noexcept { return max(a, T(b)); }
REQUIRE_UINT32
inline T max(const BE32 &a, const T &b) noexcept { return max(T(a), b); }
REQUIRE_UINT64
inline T max(const T &a, const BE64 &b) noexcept { return max(a, T(b)); }
REQUIRE_UINT64
inline T max(const BE64 &a, const T &b) noexcept { return max(T(a), b); }
REQUIRE_UINT32
inline T max(const T &a, const LE16 &b) noexcept { return max(a, T(b)); }
REQUIRE_UINT32
inline T max(const LE16 &a, const T &b) noexcept { return max(T(a), b); }
REQUIRE_UINT32
inline T max(const T &a, const LE32 &b) noexcept { return max(a, T(b)); }
REQUIRE_UINT32
inline T max(const LE32 &a, const T &b) noexcept { return max(T(a), b); }
REQUIRE_UINT64
inline T max(const T &a, const LE64 &b) noexcept { return max(a, T(b)); }
REQUIRE_UINT64
inline T max(const LE64 &a, const T &b) noexcept { return max(T(a), b); }
inline unsigned max(unsigned a, const LE32 &b) { return max(a, unsigned(b)); }
inline unsigned max(const LE32 &a, unsigned b) { return max(unsigned(a), b); }
inline unsigned min(unsigned a, const LE32 &b) { return min(a, unsigned(b)); }
inline unsigned min(const LE32 &a, unsigned b) { return min(unsigned(a), b); }
#undef REQUIRE_UINT32
#undef REQUIRE_UINT64
} // namespace upx

View File

@ -298,48 +298,119 @@ struct CheckAlignment {
template <class T>
struct TestBELE {
static noinline bool test(void) noexcept {
static_assert(upx::is_same_any_v<T, BE16, BE32, BE64, LE16, LE32, LE64>);
static_assert(
upx::is_same_any_v<typename T::integral_conversion_type, upx_uint32_t, upx_uint64_t>);
CheckIntegral<T>::check();
CheckAlignment<T>::check();
// arithmetic checks
T all_bits = {};
assert_noexcept(all_bits == 0);
all_bits += 1;
all_bits -= 2;
T v1;
v1 = 1;
v1 *= 4;
v1 /= 2;
v1 -= 1;
T v2;
v2 = 1;
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 ^= all_bits;
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_noexcept(v1 == 1);
assert_noexcept(v2 == 0);
v1 <<= 1;
v1 |= v2;
v1 >>= 1;
v2 &= v1;
v2 /= v1;
v2 *= v1;
v1 += v2;
v1 -= v2;
assert_noexcept(v1 == 1);
assert_noexcept(v2 == 0);
if ((v1 ^ v2) != 1)
return false;
{
T all_bits = {}; // == zero
assert_noexcept(all_bits == 0);
assert_noexcept(!upx::has_single_bit(all_bits));
all_bits += 1;
assert_noexcept(upx::has_single_bit(all_bits));
all_bits -= 2;
assert_noexcept(!upx::has_single_bit(all_bits));
T v1;
v1 = 1;
v1 *= 4;
v1 /= 2;
v1 -= 1;
T v2;
v2 = 1;
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 ^= all_bits;
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_noexcept(v1 == 1);
assert_noexcept(v2 == 0);
v1 <<= 1;
v1 |= v2;
v1 >>= 1;
v2 &= v1;
v2 /= v1;
v2 *= v1;
v1 += v2;
v1 -= v2;
assert_noexcept(v1 == 1);
assert_noexcept(v2 == 0);
if ((v1 ^ v2) != 1)
return false;
}
// min/max
{
constexpr T a = {}; // == zero
typedef typename T::integral_conversion_type U;
constexpr U b = 1;
assert_noexcept(upx::min(a, a) == 0);
assert_noexcept(upx::min(a, a) == a);
assert_noexcept(upx::min(a, b) == 0);
assert_noexcept(upx::min(a, b) == a);
assert_noexcept(upx::min(b, a) == 0);
assert_noexcept(upx::min(b, a) == a);
assert_noexcept(upx::min(b, b) == 1);
assert_noexcept(upx::min(b, b) == b);
assert_noexcept(upx::max(a, a) == 0);
assert_noexcept(upx::max(a, a) == a);
assert_noexcept(upx::max(a, b) == 1);
assert_noexcept(upx::max(a, b) == b);
assert_noexcept(upx::max(b, a) == 1);
assert_noexcept(upx::max(b, a) == b);
assert_noexcept(upx::max(b, b) == 1);
assert_noexcept(upx::max(b, b) == b);
T minus_one_t = {}, minus_two_t = {};
minus_one_t -= 1;
minus_two_t -= 2;
const U minus_one_u = minus_one_t;
const U minus_two_u = minus_two_t;
assert_noexcept(upx::min(minus_one_t, minus_one_t) == minus_one_t);
assert_noexcept(upx::min(minus_one_t, minus_one_t) == minus_one_u);
assert_noexcept(upx::min(minus_one_u, minus_one_t) == minus_one_t);
assert_noexcept(upx::min(minus_one_u, minus_one_t) == minus_one_u);
assert_noexcept(upx::min(minus_one_t, minus_one_u) == minus_one_t);
assert_noexcept(upx::min(minus_one_t, minus_one_u) == minus_one_u);
assert_noexcept(upx::min(minus_two_t, minus_one_t) == minus_two_t);
assert_noexcept(upx::min(minus_two_t, minus_one_t) == minus_two_u);
assert_noexcept(upx::min(minus_two_u, minus_one_t) == minus_two_t);
assert_noexcept(upx::min(minus_two_u, minus_one_t) == minus_two_u);
assert_noexcept(upx::min(minus_two_t, minus_one_u) == minus_two_t);
assert_noexcept(upx::min(minus_two_t, minus_one_u) == minus_two_u);
assert_noexcept(upx::min(minus_one_t, minus_two_t) == minus_two_t);
assert_noexcept(upx::min(minus_one_t, minus_two_t) == minus_two_u);
assert_noexcept(upx::min(minus_one_u, minus_two_t) == minus_two_t);
assert_noexcept(upx::min(minus_one_u, minus_two_t) == minus_two_u);
assert_noexcept(upx::min(minus_one_t, minus_two_u) == minus_two_t);
assert_noexcept(upx::min(minus_one_t, minus_two_u) == minus_two_u);
assert_noexcept(upx::max(minus_one_t, minus_one_t) == minus_one_t);
assert_noexcept(upx::max(minus_one_t, minus_one_t) == minus_one_u);
assert_noexcept(upx::max(minus_one_u, minus_one_t) == minus_one_t);
assert_noexcept(upx::max(minus_one_u, minus_one_t) == minus_one_u);
assert_noexcept(upx::max(minus_one_t, minus_one_u) == minus_one_t);
assert_noexcept(upx::max(minus_one_t, minus_one_u) == minus_one_u);
assert_noexcept(upx::max(minus_two_t, minus_one_t) == minus_one_t);
assert_noexcept(upx::max(minus_two_t, minus_one_t) == minus_one_u);
assert_noexcept(upx::max(minus_two_u, minus_one_t) == minus_one_t);
assert_noexcept(upx::max(minus_two_u, minus_one_t) == minus_one_u);
assert_noexcept(upx::max(minus_two_t, minus_one_u) == minus_one_t);
assert_noexcept(upx::max(minus_two_t, minus_one_u) == minus_one_u);
assert_noexcept(upx::max(minus_one_t, minus_two_t) == minus_one_t);
assert_noexcept(upx::max(minus_one_t, minus_two_t) == minus_one_u);
assert_noexcept(upx::max(minus_one_u, minus_two_t) == minus_one_t);
assert_noexcept(upx::max(minus_one_u, minus_two_t) == minus_one_u);
assert_noexcept(upx::max(minus_one_t, minus_two_u) == minus_one_t);
assert_noexcept(upx::max(minus_one_t, minus_two_u) == minus_one_u);
}
return true;
}
};

View File

@ -243,7 +243,8 @@ void PackW32PeI386::setOhDataBase(const pe_section_t *osection) { oh.database =
void PackW32PeI386::setOhHeaderSize(const pe_section_t *osection) {
// SizeOfHeaders
oh.headersize = ALIGN_UP(pe_offset + sizeof(oh) + sizeof(*osection) * oh.objects, oh.filealign);
oh.headersize =
ALIGN_UP(pe_offset + usizeof(oh) + usizeof(*osection) * oh.objects, oh.filealign);
}
void PackW32PeI386::pack(OutputFile *fo) {

View File

@ -236,7 +236,8 @@ void PackW64PeAmd64::defineSymbols(unsigned ncsection, unsigned upxsection, unsi
void PackW64PeAmd64::setOhHeaderSize(const pe_section_t *osection) {
// SizeOfHeaders
oh.headersize = ALIGN_UP(pe_offset + sizeof(oh) + sizeof(*osection) * oh.objects, oh.filealign);
oh.headersize =
ALIGN_UP(pe_offset + usizeof(oh) + usizeof(*osection) * oh.objects, oh.filealign);
}
void PackW64PeAmd64::pack(OutputFile *fo) {

View File

@ -1417,7 +1417,7 @@ void PeFile::processTls1(Interval *iv, typename tls_traits<LEXX>::cb_value_t ima
// ... and those dwords should be correctly aligned
if (use_tls_callbacks)
sotls = ALIGN_UP(sotls, cb_size) + 2 * cb_size;
const unsigned aligned_sotls = ALIGN_UP(sotls, (unsigned) sizeof(LEXX));
const unsigned aligned_sotls = ALIGN_UP(sotls, usizeof(LEXX));
// the PE loader wants this stuff uncompressed
mb_otls.alloc(aligned_sotls);
@ -2140,7 +2140,7 @@ void PeFile::checkHeaderValues(unsigned subsystem, unsigned mask, unsigned ih_en
throwCantPack("run a virus scanner on this file!");
const unsigned fam1 = ih_filealign - 1;
if (!(1 + fam1) || (1 + fam1) & fam1) { // ih_filealign is not a power of 2
if (!upx::has_single_bit(ih_filealign)) { // ih_filealign is not a power of 2
char buf[32];
snprintf(buf, sizeof(buf), "bad file alignment %#x", 1 + fam1);
throwCantPack(buf);
@ -2338,7 +2338,7 @@ void PeFile::pack0(OutputFile *fo, ht &ih, ht &oh, unsigned subsystem_mask,
allow_filter = false;
const unsigned oam1 = ih.objectalign - 1;
if (!(1 + oam1) || (1 + oam1) & oam1) { // ih.objectalign is not a power of 2
if (!upx::has_single_bit(ih.objectalign)) { // ih.objectalign is not a power of 2
char buf[32];
snprintf(buf, sizeof(buf), "bad object alignment %#x", 1 + oam1);
throwCantPack(buf);
@ -2414,7 +2414,7 @@ void PeFile::pack0(OutputFile *fo, ht &ih, ht &oh, unsigned subsystem_mask,
if (tlsindex && ((newvsize - ph.c_len - 1024 + oam1) & ~oam1) > tlsindex + 4)
tlsindex = 0;
const int oh_filealign = UPX_MIN(ih.filealign, 0x200);
const int oh_filealign = UPX_MIN(ih.filealign, 0x200u);
const unsigned fam1 = oh_filealign - 1;
int identsize = 0;
@ -2456,9 +2456,9 @@ void PeFile::pack0(OutputFile *fo, ht &ih, ht &oh, unsigned subsystem_mask,
((ph.c_len + ic) & 15) == 0 ? ph.c_len : ph.c_len + 16 - ((ph.c_len + ic) & 15);
obuf.clear(ph.c_len, c_len - ph.c_len);
const unsigned aligned_sotls = ALIGN_UP(sotls, (unsigned) sizeof(LEXX));
const unsigned aligned_sotls = ALIGN_UP(sotls, usizeof(LEXX));
const unsigned s1size =
ALIGN_UP(ic + c_len + codesize, (unsigned) sizeof(LEXX)) + aligned_sotls + soloadconf;
ALIGN_UP(ic + c_len + codesize, usizeof(LEXX)) + aligned_sotls + soloadconf;
const unsigned s1addr = (newvsize - (ic + c_len) + oam1) & ~oam1;
const unsigned ncsection = (s1addr + s1size + oam1) & ~oam1;