all: assorted cleanups and updates

Changes include:
  - add a bunch of "noexcept", mostly to operators and forceinline
  - use "uchar"
  - use "charptr"
  - rename options_t to Options
  - add ptr_check_no_overlap()
  - rewrite p_exe.cpp, NFCI
  - clang-format help.cpp
  - spelling fixes
This commit is contained in:
Markus F.X.J. Oberhumer
2023-03-15 00:19:55 +01:00
parent 127fd095e7
commit a627648249
65 changed files with 1492 additions and 1138 deletions
+84 -60
View File
@@ -100,6 +100,7 @@ ACC_COMPILE_TIME_ASSERT_HEADER((char)(-1) == 255) // -funsigned-char
# pragma warning(error: 4805)
#endif
#endif // !UPX_CONFIG_DISABLE_WSTRICT && !UPX_CONFIG_DISABLE_WERROR
// disable some warnings
#if (ACC_CC_MSC)
# pragma warning(disable: 4244) // -Wconversion
@@ -124,22 +125,30 @@ ACC_COMPILE_TIME_ASSERT_HEADER((char)(-1) == 255) // -funsigned-char
#include <new>
#include <type_traits>
#include <typeinfo>
#if __STDC_NO_ATOMICS__ || 1
// UPX currently does not use multithreading
#define upx_std_atomic(Type) Type
//#define upx_std_atomic(Type) typename std::add_volatile<Type>::type
#define upx_std_once_flag upx_std_atomic(size_t)
template <class NoexceptCallable>
inline void upx_std_call_once(upx_std_once_flag &flag, NoexceptCallable &&f) {
if (__acc_unlikely(!flag)) { flag = 1; f(); }
}
#else
// multithreading (UPX currently does not use multithreading)
#ifndef WITH_THREADS
# define WITH_THREADS 0
#endif
#if __STDC_NO_ATOMICS__
# undef WITH_THREADS
#endif
#if (WITH_THREADS)
#define upx_thread_local thread_local
#include <atomic>
#define upx_std_atomic(Type) std::atomic<Type>
#include <mutex>
#define upx_std_once_flag std::once_flag
#define upx_std_call_once std::call_once
#endif
#else
#define upx_thread_local /*empty*/
#define upx_std_atomic(Type) Type
#define upx_std_once_flag upx_std_atomic(size_t)
template <class NoexceptCallable>
inline void upx_std_call_once(upx_std_once_flag &flag, NoexceptCallable &&f) {
if (__acc_unlikely(!flag)) { flag = 1; f(); }
}
#endif // WITH_THREADS
// C++ submodule headers
#include <doctest/doctest/parts/doctest_fwd.h>
@@ -166,16 +175,39 @@ inline void upx_std_call_once(upx_std_once_flag &flag, NoexceptCallable &&f) {
// <type_traits> C++20 std::is_bounded_array
template <class T>
struct std_is_bounded_array : public std::false_type {};
struct upx_std_is_bounded_array : public std::false_type {};
template <class T, size_t N>
struct std_is_bounded_array<T[N]> : public std::true_type {};
struct upx_std_is_bounded_array<T[N]> : public std::true_type {};
template <class T>
inline constexpr bool upx_std_is_bounded_array_v = upx_std_is_bounded_array<T>::value;
// see bele.h
template <class T>
struct upx_is_integral : public std::is_integral<T> {};
template <class T>
inline constexpr bool upx_is_integral_v = upx_is_integral<T>::value;
#if (ACC_ARCH_M68K && ACC_OS_TOS && ACC_CC_GNUC) && defined(__MINT__)
// horrible hack for broken compiler
#define upx_fake_alignas_1 __attribute__((__aligned__(1),__packed__))
#define upx_fake_alignas_16 __attribute__((__aligned__(2))) // object file maximum 2 ???
#define upx_fake_alignas__(a) upx_fake_alignas_ ## a
#define alignas(x) upx_fake_alignas__(x)
#endif
/*************************************************************************
// core
**************************************************************************/
// intergral types
// protect against integer overflows and malicious header fields
// see C 11 standard, Annex K
typedef size_t upx_rsize_t;
#define UPX_RSIZE_MAX UPX_RSIZE_MAX_MEM
#define UPX_RSIZE_MAX_MEM (768 * 1024 * 1024) // DO NOT CHANGE !!!
#define UPX_RSIZE_MAX_STR (256 * 1024)
// integral types
typedef acc_int8_t upx_int8_t;
typedef acc_uint8_t upx_uint8_t;
typedef acc_int16_t upx_int16_t;
@@ -186,16 +218,17 @@ typedef acc_int64_t upx_int64_t;
typedef acc_uint64_t upx_uint64_t;
typedef acc_uintptr_t upx_uintptr_t;
// convention: use "byte" when dealing with data; use "char/uchar" when dealing
// with strings; use "upx_uint8_t" when dealing with small integers
typedef unsigned char byte;
#define upx_byte byte
#define upx_bytep byte *
// protect against integer overflows and malicious header fields
// see C 11 standard, Annex K
typedef size_t upx_rsize_t;
#define UPX_RSIZE_MAX UPX_RSIZE_MAX_MEM
#define UPX_RSIZE_MAX_MEM (768 * 1024 * 1024) // DO NOT CHANGE !!!
#define UPX_RSIZE_MAX_STR (1024 * 1024)
typedef unsigned char uchar;
// use "charptr" when dealing with pointer arithmetics
#define charptr upx_charptr_unit_type *
// upx_charptr_unit_type is some opaque type with sizeof(type) == 1
struct alignas(1) upx_charptr_unit_type { char dummy; };
ACC_COMPILE_TIME_ASSERT_HEADER(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;
@@ -244,8 +277,8 @@ typedef upx_int64_t upx_off_t;
#endif
#if (ACC_OS_DOS32) && defined(__DJGPP__)
# undef sopen
# undef __unix__
# undef __unix
# undef __unix__
#endif
#ifndef STDIN_FILENO
@@ -304,7 +337,7 @@ typedef upx_int64_t upx_off_t;
# endif
#endif
// avoid warnings about shadowing global functions
// avoid warnings about shadowing global symbols
#undef _base
#undef basename
#undef index
@@ -391,14 +424,6 @@ inline void NO_fprintf(FILE *, const char *, ...) {}
#define __packed_struct(s) struct alignas(1) s {
#define __packed_struct_end() };
#if (ACC_ARCH_M68K && ACC_OS_TOS && ACC_CC_GNUC) && defined(__MINT__)
// horrible hack for broken compiler
#define upx_fake_alignas_1 __attribute__((__aligned__(1),__packed__))
#define upx_fake_alignas_16 __attribute__((__aligned__(2))) // object file maximum 2 ???
#define upx_fake_alignas__(a) upx_fake_alignas_ ## a
#define alignas(x) upx_fake_alignas__(x)
#endif
#define COMPILE_TIME_ASSERT_ALIGNOF_USING_SIZEOF__(a,b) { \
typedef a acc_tmp_a_t; typedef b acc_tmp_b_t; \
struct alignas(1) acc_tmp_t { acc_tmp_b_t x; acc_tmp_a_t y; acc_tmp_b_t z; }; \
@@ -426,15 +451,13 @@ inline const T& UPX_MAX(const T& a, const T& b) { if (a < b) return b; return a;
template <class T>
inline const T& UPX_MIN(const T& a, const T& b) { if (a < b) return a; return b; }
template <size_t TypeSize>
struct USizeOfTypeImpl {
static forceinline constexpr unsigned value() {
COMPILE_TIME_ASSERT(TypeSize >= 1 && TypeSize <= 64 * 1024) // arbitrary limit
return ACC_ICONV(unsigned, TypeSize);
}
template <size_t Size>
struct UnsignedSizeOf {
static_assert(Size >= 1 && Size <= UPX_RSIZE_MAX_MEM);
static constexpr unsigned value = unsigned(Size);
};
#define usizeof(type) (USizeOfTypeImpl<sizeof(type)>::value())
ACC_COMPILE_TIME_ASSERT_HEADER(usizeof(int) == 4)
#define usizeof(expr) (UnsignedSizeOf<sizeof(expr)>::value)
ACC_COMPILE_TIME_ASSERT_HEADER(usizeof(int) == sizeof(int))
// An Array allocates memory on the heap, and automatically
// gets destructed when leaving scope or on exceptions.
@@ -442,16 +465,16 @@ ACC_COMPILE_TIME_ASSERT_HEADER(usizeof(int) == 4)
MemBuffer var ## _membuf(mem_size(sizeof(type), size)); \
type * const var = ACC_STATIC_CAST(type *, var ## _membuf.getVoidPtr())
#define ByteArray(var, size) Array(unsigned char, var, size)
#define ByteArray(var, size) Array(byte, var, size)
class noncopyable
{
protected:
inline noncopyable() {}
inline ~noncopyable() {}
inline noncopyable() noexcept {}
inline ~noncopyable() noexcept {}
private:
noncopyable(const noncopyable &) DELETED_FUNCTION; // copy constuctor
noncopyable(const noncopyable &) DELETED_FUNCTION; // copy constructor
noncopyable& operator=(const noncopyable &) DELETED_FUNCTION; // copy assignment
noncopyable(noncopyable &&) DELETED_FUNCTION; // move constructor
noncopyable& operator=(noncopyable &&) DELETED_FUNCTION; // move assignment
@@ -466,7 +489,7 @@ constexpr bool string_eq(const char *a, const char *b) {
return *a == *b && (*a == '\0' || string_eq(a + 1, b + 1));
}
constexpr bool string_lt(const char *a, const char *b) {
return (unsigned char)*a < (unsigned char)*b || (*a != '\0' && *a == *b && string_lt(a + 1, b + 1));
return (uchar)*a < (uchar)*b || (*a != '\0' && *a == *b && string_lt(a + 1, b + 1));
}
constexpr bool string_ne(const char *a, const char *b) {
return !string_eq(a, b);
@@ -644,7 +667,7 @@ struct upx_callback_t
upx_progress_func_t nprogress;
void *user;
void reset() { memset(this, 0, sizeof(*this)); }
void reset() noexcept { memset(this, 0, sizeof(*this)); }
};
@@ -670,7 +693,7 @@ struct OptVar
assertValue(v);
}
OptVar() : v(default_value), is_set(false) { }
OptVar() noexcept : v(default_value), is_set(false) { }
OptVar& operator= (const T &other) {
assertValue(other);
v = other;
@@ -678,8 +701,8 @@ struct OptVar
return *this;
}
void reset() { v = default_value; is_set = false; }
operator T () const { return v; }
void reset() noexcept { v = default_value; is_set = false; }
operator T () const noexcept { return v; }
T v;
bool is_set;
@@ -818,26 +841,16 @@ struct upx_compress_result_t
// globals
**************************************************************************/
#include "util/snprintf.h" // must get included first!
#include "options.h"
#include "except.h"
#include "bele.h"
#include "console/console.h"
#include "util/util.h"
// classes
class ElfLinker;
typedef ElfLinker Linker;
class Throwable;
// util/membuffer.h
class MemBuffer;
void *membuffer_get_void_ptr(MemBuffer &mb);
unsigned membuffer_get_size(MemBuffer &mb);
// xspan
#include "util/raw_bytes.h"
#include "util/xspan.h"
// util/dt_check.cpp
void upx_compiler_sanity_check();
int upx_doctest_check();
@@ -870,7 +883,7 @@ int do_files(int i, int argc, char *argv[]);
// help.cpp
extern const char gitrev[];
void show_head();
void show_header();
void show_help(int verbose=0);
void show_license();
void show_usage();
@@ -898,6 +911,17 @@ int upx_test_overlap ( const upx_bytep buf,
const upx_compress_result_t *cresult );
#include "util/snprintf.h" // must get included first!
#include "options.h"
#include "except.h"
#include "bele.h"
#include "console/console.h"
#include "util/util.h"
// xspan
#include "util/raw_bytes.h"
#include "util/xspan.h"
#if (ACC_OS_CYGWIN || ACC_OS_DOS16 || ACC_OS_DOS32 || ACC_OS_EMX || ACC_OS_OS2 || ACC_OS_OS216 || ACC_OS_WIN16 || ACC_OS_WIN32 || ACC_OS_WIN64)
# if defined(INVALID_HANDLE_VALUE) || defined(MAKEWORD) || defined(RT_CURSOR)
# error "something pulled in <windows.h>"