mirror of
https://github.com/upx/upx.git
synced 2024-11-27 06:30:23 +00:00
CI updates; cxxlib.h cleanups
This commit is contained in:
parent
778663ae69
commit
0500e7d016
2
.github/workflows/misc-spell-check.yml
vendored
2
.github/workflows/misc-spell-check.yml
vendored
@ -17,5 +17,5 @@ jobs:
|
||||
uses: actions/checkout@v4
|
||||
with: { submodules: false }
|
||||
- name: 'Spell check with crate-ci/typos'
|
||||
uses: crate-ci/typos@5bd389de715c63ba86568420809e324fcea78660 # v1.16.25
|
||||
uses: crate-ci/typos@45a880d9f898547e8bfe6525b6059d4b3dea4d71 # v1.16.26
|
||||
with: { config: ./.github/typos_config.toml }
|
||||
|
4
.github/workflows/weekly-ci-rt-checkers.yml
vendored
4
.github/workflows/weekly-ci-rt-checkers.yml
vendored
@ -24,6 +24,7 @@ jobs:
|
||||
- { container: 'alpine:3.19', release: debug, qemu: 'qemu-x86_64 -cpu Nehalem' }
|
||||
- { container: 'alpine:3.19', release: release, qemu: 'qemu-x86_64 -cpu Nehalem' }
|
||||
- { container: 'alpine:edge', release: release, qemu: 'qemu-x86_64 -cpu Nehalem' }
|
||||
- { container: 'i386/alpine:3.19', release: release, qemu: 'qemu-i386' }
|
||||
- { container: 'i386/alpine:edge', release: release, qemu: 'qemu-i386' }
|
||||
name: ${{ format('{0} {1}', matrix.container, matrix.release) }}
|
||||
runs-on: ubuntu-latest
|
||||
@ -45,7 +46,8 @@ jobs:
|
||||
|
||||
- name: 'Build clang-static'
|
||||
run: |
|
||||
export CC="clang -static" CXX="clang++ -static"
|
||||
flags="-static -fno-omit-frame-pointer"
|
||||
export CC="clang $flags" CXX="clang++ $flags"
|
||||
make UPX_XTARGET=clang-static xtarget/$release
|
||||
- name: 'Build clang-asan'
|
||||
if: ${{ !startsWith(matrix.container, 'i386/') }} # i386: ASAN not supported
|
||||
|
@ -72,7 +72,7 @@ function(upx_print_var) # ARGV
|
||||
endforeach()
|
||||
endfunction()
|
||||
|
||||
function(upx_print_have_symbol) # ARGV
|
||||
function(upx_print_have_symbol) # ARGV; needs include(CheckSymbolExists)
|
||||
foreach(symbol ${ARGV})
|
||||
set(cache_var_name "HAVE_symbol_${symbol}")
|
||||
check_symbol_exists(${symbol} "limits.h;stddef.h;stdint.h" ${cache_var_name})
|
||||
@ -147,7 +147,7 @@ endfunction()
|
||||
# compilation flags
|
||||
#***********************************************************************
|
||||
|
||||
function(upx_internal_add_definitions_with_prefix) # ARGV
|
||||
function(upx_internal_add_definitions_with_prefix) # ARGV; needs include(CheckCCompilerFlag)
|
||||
set(flag_prefix "${ARGV0}")
|
||||
if(flag_prefix MATCHES "^empty$") # need "empty" to work around bug in old CMake versions
|
||||
set(flag_prefix "")
|
||||
@ -168,7 +168,7 @@ function(upx_internal_add_definitions_with_prefix) # ARGV
|
||||
set(failed_flags "${failed}" PARENT_SCOPE) # return value
|
||||
endfunction()
|
||||
|
||||
function(upx_add_definitions) # ARGV
|
||||
function(upx_add_definitions) # ARGV; needs include(CheckCCompilerFlag)
|
||||
set(failed_flags "")
|
||||
if(MSVC_FRONTEND AND CMAKE_C_COMPILER_ID MATCHES "Clang")
|
||||
# for clang-cl try "-clang:" flag prefix first
|
||||
|
@ -79,12 +79,9 @@ struct AbstractPolicy {
|
||||
|
||||
private:
|
||||
// disable copy and move
|
||||
AbstractPolicy(const AbstractPolicy &) DELETED_FUNCTION;
|
||||
AbstractPolicy &operator=(const AbstractPolicy &) DELETED_FUNCTION;
|
||||
AbstractPolicy(AbstractPolicy &&) noexcept DELETED_FUNCTION;
|
||||
AbstractPolicy &operator=(AbstractPolicy &&) noexcept DELETED_FUNCTION;
|
||||
UPX_CXX_DISABLE_COPY_MOVE(AbstractPolicy)
|
||||
// disable dynamic allocation
|
||||
UPX_CXX_DISABLE_NEW_DELETE
|
||||
UPX_CXX_DISABLE_NEW_DELETE(AbstractPolicy)
|
||||
};
|
||||
#endif
|
||||
|
||||
@ -147,12 +144,9 @@ struct BEPolicy
|
||||
|
||||
private:
|
||||
// disable copy and move
|
||||
BEPolicy(const BEPolicy &) DELETED_FUNCTION;
|
||||
BEPolicy &operator=(const BEPolicy &) DELETED_FUNCTION;
|
||||
BEPolicy(BEPolicy &&) noexcept DELETED_FUNCTION;
|
||||
BEPolicy &operator=(BEPolicy &&) noexcept DELETED_FUNCTION;
|
||||
UPX_CXX_DISABLE_COPY_MOVE(BEPolicy)
|
||||
// disable dynamic allocation
|
||||
UPX_CXX_DISABLE_NEW_DELETE
|
||||
UPX_CXX_DISABLE_NEW_DELETE(BEPolicy)
|
||||
};
|
||||
|
||||
struct LEPolicy
|
||||
@ -209,12 +203,9 @@ struct LEPolicy
|
||||
|
||||
private:
|
||||
// disable copy and move
|
||||
LEPolicy(const LEPolicy &) DELETED_FUNCTION;
|
||||
LEPolicy &operator=(const LEPolicy &) DELETED_FUNCTION;
|
||||
LEPolicy(LEPolicy &&) noexcept DELETED_FUNCTION;
|
||||
LEPolicy &operator=(LEPolicy &&) noexcept DELETED_FUNCTION;
|
||||
UPX_CXX_DISABLE_COPY_MOVE(LEPolicy)
|
||||
// disable dynamic allocation
|
||||
UPX_CXX_DISABLE_NEW_DELETE
|
||||
UPX_CXX_DISABLE_NEW_DELETE(LEPolicy)
|
||||
};
|
||||
|
||||
// Native Endianness policy (aka host policy)
|
||||
|
@ -564,6 +564,17 @@ TEST_CASE("acc_vget") {
|
||||
CHECK_EQ(acc_vget_acc_hvoid_p(nullptr, 0), nullptr);
|
||||
}
|
||||
|
||||
TEST_CASE("ptr_invalidate_and_poison") {
|
||||
int *ip = nullptr;
|
||||
ptr_invalidate_and_poison(ip);
|
||||
assert(ip != nullptr);
|
||||
(void) ip;
|
||||
double *dp;
|
||||
ptr_invalidate_and_poison(dp);
|
||||
assert(dp != nullptr);
|
||||
(void) dp;
|
||||
}
|
||||
|
||||
TEST_CASE("working -fno-strict-aliasing") {
|
||||
bool ok;
|
||||
long v = 0;
|
||||
|
@ -98,9 +98,54 @@ ACC_COMPILE_TIME_ASSERT_HEADER(!compile_time::string_ge("abc", "abz"))
|
||||
ACC_COMPILE_TIME_ASSERT_HEADER(compile_time::string_le("abc", "abz"))
|
||||
|
||||
/*************************************************************************
|
||||
// UPX_CXX_DISABLE_NEW_DELETE
|
||||
// UPX_CXX_DISABLE_xxx
|
||||
**************************************************************************/
|
||||
|
||||
namespace {
|
||||
template <class TA, class TB, int TC = 0>
|
||||
struct MyType1 {
|
||||
MyType1() noexcept {}
|
||||
UPX_CXX_DISABLE_ADDRESS(MyType1)
|
||||
UPX_CXX_DISABLE_COPY_MOVE(MyType1)
|
||||
UPX_CXX_DISABLE_NEW_DELETE_NO_VIRTUAL(MyType1)
|
||||
};
|
||||
template <class TA, class TB, int TC = 0>
|
||||
struct MyType2 {
|
||||
MyType2() noexcept {}
|
||||
UPX_CXX_DISABLE_COPY_MOVE(MyType2)
|
||||
typedef MyType2<TA, TB, TC> Self;
|
||||
UPX_CXX_DISABLE_ADDRESS(Self)
|
||||
UPX_CXX_DISABLE_NEW_DELETE_NO_VIRTUAL(Self)
|
||||
};
|
||||
template <class TA, class TB, int TC = 0>
|
||||
struct MyVType1 {
|
||||
MyVType1() noexcept {}
|
||||
virtual ~MyVType1() noexcept {}
|
||||
UPX_CXX_DISABLE_ADDRESS(MyVType1)
|
||||
UPX_CXX_DISABLE_COPY_MOVE(MyVType1)
|
||||
UPX_CXX_DISABLE_NEW_DELETE(MyVType1)
|
||||
};
|
||||
template <class TA, class TB, int TC = 0>
|
||||
struct MyVType2 {
|
||||
MyVType2() noexcept {}
|
||||
virtual ~MyVType2() noexcept {}
|
||||
UPX_CXX_DISABLE_COPY_MOVE(MyVType2)
|
||||
typedef MyVType2<TA, TB, TC> Self;
|
||||
UPX_CXX_DISABLE_ADDRESS(Self)
|
||||
UPX_CXX_DISABLE_NEW_DELETE(Self)
|
||||
};
|
||||
TEST_CASE("upx_cxx_disable") {
|
||||
MyType1<char, int, 1> dummy1;
|
||||
MyType2<char, int, 2> dummy2;
|
||||
MyVType1<char, int, 1> vdummy1;
|
||||
MyVType2<char, int, 2> vdummy2;
|
||||
(void) dummy1;
|
||||
(void) dummy2;
|
||||
(void) vdummy1;
|
||||
(void) vdummy2;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace test_disable_new_delete {
|
||||
|
||||
struct A1 {
|
||||
@ -108,7 +153,7 @@ struct A1 {
|
||||
};
|
||||
struct A2 {
|
||||
int a;
|
||||
UPX_CXX_DISABLE_NEW_DELETE_NO_VIRTUAL
|
||||
UPX_CXX_DISABLE_NEW_DELETE_NO_VIRTUAL(A2)
|
||||
};
|
||||
struct B1_A1 : public A1 {
|
||||
int b;
|
||||
@ -118,11 +163,11 @@ struct B1_A2 : public A2 {
|
||||
};
|
||||
struct B2_A1 : public A1 {
|
||||
int b;
|
||||
UPX_CXX_DISABLE_NEW_DELETE_NO_VIRTUAL
|
||||
UPX_CXX_DISABLE_NEW_DELETE_NO_VIRTUAL(B2_A1)
|
||||
};
|
||||
struct B2_A2 : public A2 {
|
||||
int b;
|
||||
UPX_CXX_DISABLE_NEW_DELETE_NO_VIRTUAL
|
||||
UPX_CXX_DISABLE_NEW_DELETE_NO_VIRTUAL(B2_A2)
|
||||
};
|
||||
|
||||
struct X1 {
|
||||
@ -132,7 +177,7 @@ struct X1 {
|
||||
struct X2 {
|
||||
virtual ~X2() noexcept {}
|
||||
int x;
|
||||
UPX_CXX_DISABLE_NEW_DELETE
|
||||
UPX_CXX_DISABLE_NEW_DELETE(X2)
|
||||
};
|
||||
struct Y1_X1 : public X1 {
|
||||
int y;
|
||||
@ -142,11 +187,11 @@ struct Y1_X2 : public X2 {
|
||||
};
|
||||
struct Y2_X1 : public X1 {
|
||||
int y;
|
||||
UPX_CXX_DISABLE_NEW_DELETE
|
||||
UPX_CXX_DISABLE_NEW_DELETE(Y2_X1)
|
||||
};
|
||||
struct Y2_X2 : public X2 {
|
||||
int y;
|
||||
UPX_CXX_DISABLE_NEW_DELETE
|
||||
UPX_CXX_DISABLE_NEW_DELETE(Y2_X2)
|
||||
};
|
||||
struct Z1_X1 : public X1 {
|
||||
virtual ~Z1_X1() noexcept {}
|
||||
@ -159,12 +204,12 @@ struct Z1_X2 : public X2 {
|
||||
struct Z2_X1 : public X1 {
|
||||
virtual ~Z2_X1() noexcept {}
|
||||
int z;
|
||||
UPX_CXX_DISABLE_NEW_DELETE
|
||||
UPX_CXX_DISABLE_NEW_DELETE(Z2_X1)
|
||||
};
|
||||
struct Z2_X2 : public X2 {
|
||||
virtual ~Z2_X2() noexcept {}
|
||||
int z;
|
||||
UPX_CXX_DISABLE_NEW_DELETE
|
||||
UPX_CXX_DISABLE_NEW_DELETE(Z2_X2)
|
||||
};
|
||||
|
||||
} // namespace test_disable_new_delete
|
||||
|
11
src/except.h
11
src/except.h
@ -43,7 +43,7 @@ protected:
|
||||
Throwable(const char *m = nullptr, int e = 0, bool w = false) noexcept;
|
||||
|
||||
public:
|
||||
Throwable(const Throwable &) noexcept;
|
||||
Throwable(const Throwable &) noexcept; // copy constructor
|
||||
virtual ~Throwable() noexcept;
|
||||
const char *getMsg() const noexcept { return msg; }
|
||||
int getErrno() const noexcept { return err; }
|
||||
@ -57,14 +57,13 @@ protected:
|
||||
|
||||
private:
|
||||
// disable copy assignment and move
|
||||
Throwable &operator=(const Throwable &) DELETED_FUNCTION;
|
||||
Throwable(Throwable &&) noexcept DELETED_FUNCTION;
|
||||
Throwable &operator=(Throwable &&) noexcept DELETED_FUNCTION;
|
||||
Throwable &operator=(const Throwable &) noexcept DELETED_FUNCTION; // copy assignment
|
||||
UPX_CXX_DISABLE_MOVE(Throwable)
|
||||
// disable dynamic allocation => force throwing by value
|
||||
UPX_CXX_DISABLE_NEW_DELETE
|
||||
UPX_CXX_DISABLE_NEW_DELETE(Throwable)
|
||||
// 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 DELETED_FUNCTION;
|
||||
UPX_CXX_DISABLE_ADDRESS(Throwable)
|
||||
|
||||
private:
|
||||
static upx_std_atomic(size_t) debug_counter; // for debugging
|
||||
|
@ -321,10 +321,7 @@ private:
|
||||
|
||||
private:
|
||||
// disable copy and move
|
||||
Packer(const Packer &) DELETED_FUNCTION;
|
||||
Packer &operator=(const Packer &) DELETED_FUNCTION;
|
||||
Packer(Packer &&) noexcept DELETED_FUNCTION;
|
||||
Packer &operator=(Packer &&) noexcept DELETED_FUNCTION;
|
||||
UPX_CXX_DISABLE_COPY_MOVE(Packer)
|
||||
};
|
||||
|
||||
/* vim:set ts=4 sw=4 et: */
|
||||
|
@ -33,55 +33,105 @@
|
||||
namespace upx {
|
||||
|
||||
/*************************************************************************
|
||||
// core
|
||||
// core util
|
||||
**************************************************************************/
|
||||
|
||||
// disable taking the address => force passing by reference (instead of pointer)
|
||||
#define UPX_CXX_DISABLE_ADDRESS(Klass) \
|
||||
private: \
|
||||
Klass *operator&() const noexcept DELETED_FUNCTION;
|
||||
|
||||
// disable copy and move
|
||||
#define UPX_CXX_DISABLE_COPY(KlassName) \
|
||||
private: \
|
||||
KlassName(const KlassName &) noexcept DELETED_FUNCTION; /* copy constructor */ \
|
||||
KlassName &operator=(const KlassName &) noexcept DELETED_FUNCTION; /* copy assignment */
|
||||
#define UPX_CXX_DISABLE_MOVE(KlassName) \
|
||||
private: \
|
||||
KlassName(KlassName &&) noexcept DELETED_FUNCTION; /* move constructor */ \
|
||||
KlassName &operator=(KlassName &&) noexcept DELETED_FUNCTION; /* move assignment */
|
||||
#define UPX_CXX_DISABLE_COPY_MOVE(KlassName) \
|
||||
UPX_CXX_DISABLE_COPY(KlassName) \
|
||||
UPX_CXX_DISABLE_MOVE(KlassName)
|
||||
|
||||
// fun with C++: disable common "new" and ALL "delete" operators
|
||||
#define UPX_CXX_DISABLE_NEW_DELETE_COMMON__ \
|
||||
// https://en.cppreference.com/w/cpp/memory/new/operator_delete
|
||||
#define UPX_CXX_DISABLE_NEW_DELETE_IMPL__(Klass) \
|
||||
private: \
|
||||
/* common allocation functions (4) */ \
|
||||
static void *operator new(std::size_t) = delete; \
|
||||
static void *operator new[](std::size_t) = delete; \
|
||||
static void *operator new(std::size_t, void *) = delete; \
|
||||
static void *operator new[](std::size_t, void *) = delete; \
|
||||
static void *operator new(std::size_t) DELETED_FUNCTION; \
|
||||
static void *operator new[](std::size_t) DELETED_FUNCTION; \
|
||||
static void *operator new(std::size_t, void *) DELETED_FUNCTION; \
|
||||
static void *operator new[](std::size_t, void *) DELETED_FUNCTION; \
|
||||
/* replaceable placement deallocation functions (4) */ \
|
||||
static void operator delete(void *, const std::nothrow_t &) noexcept = delete; \
|
||||
static void operator delete[](void *, const std::nothrow_t &) noexcept = delete; \
|
||||
static void operator delete(void *, std::align_val_t, const std::nothrow_t &) noexcept = \
|
||||
delete; \
|
||||
static void operator delete[](void *, std::align_val_t, const std::nothrow_t &) noexcept = \
|
||||
delete; \
|
||||
static void operator delete(void *, const std::nothrow_t &) noexcept DELETED_FUNCTION; \
|
||||
static void operator delete[](void *, const std::nothrow_t &) noexcept DELETED_FUNCTION; \
|
||||
static void operator delete(void *, std::align_val_t, const std::nothrow_t &) \
|
||||
noexcept DELETED_FUNCTION; \
|
||||
static void operator delete[](void *, std::align_val_t, const std::nothrow_t &) \
|
||||
noexcept DELETED_FUNCTION; \
|
||||
/* non-allocating placement deallocation functions (2) */ \
|
||||
static void operator delete(void *, void *) noexcept = delete; \
|
||||
static void operator delete[](void *, void *) noexcept = delete;
|
||||
static void operator delete(void *, void *) noexcept DELETED_FUNCTION; \
|
||||
static void operator delete[](void *, void *) noexcept DELETED_FUNCTION;
|
||||
|
||||
// for classes with virtual methods
|
||||
#define UPX_CXX_DISABLE_NEW_DELETE \
|
||||
UPX_CXX_DISABLE_NEW_DELETE_COMMON__ \
|
||||
/* replaceable usual deallocation functions (8) */ \
|
||||
/* class-specific usual deallocation functions (8) */
|
||||
#define UPX_CXX_DISABLE_NEW_DELETE_IMPL_CSUDF_A__(Klass) \
|
||||
protected: \
|
||||
static void operator delete(void *) noexcept {} \
|
||||
static void operator delete[](void *) noexcept = delete; \
|
||||
static void operator delete(void *, std::align_val_t) {} \
|
||||
static void operator delete[](void *, std::align_val_t) noexcept = delete; \
|
||||
static void operator delete(void *, std::size_t) {} \
|
||||
static void operator delete[](void *, std::size_t) noexcept = delete; \
|
||||
static void operator delete(void *, std::size_t, std::align_val_t) {} \
|
||||
static void operator delete[](void *, std::size_t, std::align_val_t) noexcept = delete; \
|
||||
private:
|
||||
static void operator delete(void *, std::align_val_t) noexcept {} \
|
||||
static void operator delete(void *, std::size_t) noexcept {} \
|
||||
static void operator delete(void *, std::size_t, std::align_val_t) noexcept {} \
|
||||
private: \
|
||||
static void operator delete[](void *) noexcept DELETED_FUNCTION; \
|
||||
static void operator delete[](void *, std::align_val_t) noexcept DELETED_FUNCTION; \
|
||||
static void operator delete[](void *, std::size_t) noexcept DELETED_FUNCTION; \
|
||||
static void operator delete[](void *, std::size_t, std::align_val_t) noexcept DELETED_FUNCTION;
|
||||
#define UPX_CXX_DISABLE_NEW_DELETE_IMPL_CSUDF_B__(Klass) \
|
||||
private: \
|
||||
static void operator delete(void *) noexcept DELETED_FUNCTION; \
|
||||
static void operator delete[](void *) noexcept DELETED_FUNCTION; \
|
||||
static void operator delete(void *, std::align_val_t) noexcept DELETED_FUNCTION; \
|
||||
static void operator delete[](void *, std::align_val_t) noexcept DELETED_FUNCTION; \
|
||||
static void operator delete(void *, std::size_t) noexcept DELETED_FUNCTION; \
|
||||
static void operator delete[](void *, std::size_t) noexcept DELETED_FUNCTION; \
|
||||
static void operator delete(void *, std::size_t, std::align_val_t) noexcept DELETED_FUNCTION; \
|
||||
static void operator delete[](void *, std::size_t, std::align_val_t) noexcept DELETED_FUNCTION;
|
||||
|
||||
// for classes WITHOUT any virtual methods
|
||||
#define UPX_CXX_DISABLE_NEW_DELETE_NO_VIRTUAL \
|
||||
UPX_CXX_DISABLE_NEW_DELETE_COMMON__ \
|
||||
/* replaceable usual deallocation functions (8) */ \
|
||||
static void operator delete(void *) noexcept = delete; \
|
||||
static void operator delete[](void *) noexcept = delete; \
|
||||
static void operator delete(void *, std::align_val_t) = delete; \
|
||||
static void operator delete[](void *, std::align_val_t) noexcept = delete; \
|
||||
static void operator delete(void *, std::size_t) = delete; \
|
||||
static void operator delete[](void *, std::size_t) noexcept = delete; \
|
||||
static void operator delete(void *, std::size_t, std::align_val_t) = delete; \
|
||||
static void operator delete[](void *, std::size_t, std::align_val_t) noexcept = delete;
|
||||
/* class-specific usual destroying deallocation functions (4) */
|
||||
#if __cplusplus >= 202002L
|
||||
#define UPX_CXX_DISABLE_NEW_DELETE_IMPL_CSUDDF_A__(Klass) \
|
||||
protected: \
|
||||
static void operator delete(Klass *, std::destroying_delete_t) noexcept {} \
|
||||
static void operator delete(Klass *, std::destroying_delete_t, std::align_val_t) noexcept {} \
|
||||
static void operator delete(Klass *, std::destroying_delete_t, std::size_t) noexcept {} \
|
||||
static void operator delete(Klass *, std::destroying_delete_t, std::size_t, std::align_val_t) \
|
||||
noexcept {} \
|
||||
private:
|
||||
#define UPX_CXX_DISABLE_NEW_DELETE_IMPL_CSUDDF_B__(Klass) \
|
||||
private: \
|
||||
static void operator delete(Klass *, std::destroying_delete_t) noexcept DELETED_FUNCTION; \
|
||||
static void operator delete(Klass *, std::destroying_delete_t, std::align_val_t) \
|
||||
noexcept DELETED_FUNCTION; \
|
||||
static void operator delete(Klass *, std::destroying_delete_t, std::size_t) \
|
||||
noexcept DELETED_FUNCTION; \
|
||||
static void operator delete(Klass *, std::destroying_delete_t, std::size_t, std::align_val_t) \
|
||||
noexcept DELETED_FUNCTION;
|
||||
#else
|
||||
#define UPX_CXX_DISABLE_NEW_DELETE_IMPL_CSUDDF_A__(Klass) private:
|
||||
#define UPX_CXX_DISABLE_NEW_DELETE_IMPL_CSUDDF_B__(Klass) private:
|
||||
#endif
|
||||
|
||||
// for classes which may have virtual methods
|
||||
#define UPX_CXX_DISABLE_NEW_DELETE(Klass) \
|
||||
UPX_CXX_DISABLE_NEW_DELETE_IMPL__(Klass) \
|
||||
UPX_CXX_DISABLE_NEW_DELETE_IMPL_CSUDF_A__(Klass) \
|
||||
UPX_CXX_DISABLE_NEW_DELETE_IMPL_CSUDDF_A__(Klass)
|
||||
|
||||
// this only works for classes WITHOUT any virtual methods
|
||||
#define UPX_CXX_DISABLE_NEW_DELETE_NO_VIRTUAL(Klass) \
|
||||
UPX_CXX_DISABLE_NEW_DELETE_IMPL__(Klass) \
|
||||
UPX_CXX_DISABLE_NEW_DELETE_IMPL_CSUDF_B__(Klass) \
|
||||
UPX_CXX_DISABLE_NEW_DELETE_IMPL_CSUDDF_B__(Klass)
|
||||
|
||||
/*************************************************************************
|
||||
// type_traits
|
||||
@ -137,11 +187,7 @@ protected:
|
||||
#else
|
||||
forceinline ~noncopyable() noexcept = default;
|
||||
#endif
|
||||
private:
|
||||
noncopyable(const noncopyable &) noexcept DELETED_FUNCTION; // copy constructor
|
||||
noncopyable &operator=(const noncopyable &) noexcept DELETED_FUNCTION; // copy assignment
|
||||
noncopyable(noncopyable &&) noexcept DELETED_FUNCTION; // move constructor
|
||||
noncopyable &operator=(noncopyable &&) noexcept DELETED_FUNCTION; // move assignment
|
||||
UPX_CXX_DISABLE_COPY_MOVE(noncopyable)
|
||||
};
|
||||
|
||||
namespace compile_time {
|
||||
@ -178,7 +224,7 @@ struct TriBool final {
|
||||
// constructors
|
||||
forceinline constexpr TriBool() noexcept {}
|
||||
forceinline constexpr TriBool(value_type x) noexcept : value(x) {}
|
||||
// permissive, converts all other values to Third!!
|
||||
// IMPORTANT NOTE: permissive, converts all other values to Third!
|
||||
constexpr TriBool(promoted_type x) noexcept : value(x == 0 ? False : (x == 1 ? True : Third)) {}
|
||||
#if __cplusplus >= 202002L
|
||||
forceinline constexpr ~TriBool() noexcept = default;
|
||||
@ -214,8 +260,8 @@ struct TriBool final {
|
||||
#endif
|
||||
|
||||
private:
|
||||
value_type value = False; // the actual value of this type
|
||||
UPX_CXX_DISABLE_NEW_DELETE_NO_VIRTUAL // UPX convention
|
||||
value_type value = False; // the actual value of this type
|
||||
UPX_CXX_DISABLE_NEW_DELETE_NO_VIRTUAL(TriBool) // UPX convention
|
||||
};
|
||||
|
||||
typedef TriBool<> tribool;
|
||||
@ -245,7 +291,7 @@ struct OptVar final {
|
||||
void assertValue() const noexcept { assertValue(value); }
|
||||
|
||||
constexpr OptVar() noexcept {}
|
||||
OptVar &operator=(const T &other) noexcept {
|
||||
OptVar &operator=(const T &other) noexcept { // copy constructor
|
||||
assertValue(other);
|
||||
value = other;
|
||||
is_set = true;
|
||||
@ -259,6 +305,7 @@ struct OptVar final {
|
||||
|
||||
value_type value = default_value;
|
||||
bool is_set = false;
|
||||
UPX_CXX_DISABLE_NEW_DELETE_NO_VIRTUAL(OptVar) // UPX convention
|
||||
};
|
||||
|
||||
// optional assignments
|
||||
@ -312,9 +359,9 @@ struct OwningPointer final {
|
||||
constexpr const_pointer operator->() const noexcept { return ptr; }
|
||||
private:
|
||||
pointer ptr;
|
||||
reference operator[](std::ptrdiff_t) noexcept = delete;
|
||||
const_reference operator[](std::ptrdiff_t) const noexcept = delete;
|
||||
UPX_CXX_DISABLE_NEW_DELETE_NO_VIRTUAL // UPX convention
|
||||
reference operator[](std::ptrdiff_t) noexcept DELETED_FUNCTION;
|
||||
const_reference operator[](std::ptrdiff_t) const noexcept DELETED_FUNCTION;
|
||||
UPX_CXX_DISABLE_NEW_DELETE_NO_VIRTUAL(OwningPointer) // UPX convention
|
||||
};
|
||||
// must overload mem_clear()
|
||||
template <class T>
|
||||
|
@ -84,7 +84,7 @@ public: // raw access
|
||||
private:
|
||||
// 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]
|
||||
MemBufferBase<T> *operator&() const noexcept DELETED_FUNCTION;
|
||||
UPX_CXX_DISABLE_ADDRESS(MemBufferBase)
|
||||
};
|
||||
|
||||
/*************************************************************************
|
||||
@ -209,15 +209,8 @@ private:
|
||||
Debug debug;
|
||||
#endif
|
||||
|
||||
// disable copy and move
|
||||
MemBuffer(const MemBuffer &) DELETED_FUNCTION;
|
||||
MemBuffer &operator=(const MemBuffer &) DELETED_FUNCTION;
|
||||
#if __cplusplus >= 201103L
|
||||
MemBuffer(MemBuffer &&) noexcept DELETED_FUNCTION;
|
||||
MemBuffer &operator=(MemBuffer &&) noexcept DELETED_FUNCTION;
|
||||
#endif
|
||||
// disable dynamic allocation
|
||||
UPX_CXX_DISABLE_NEW_DELETE_NO_VIRTUAL
|
||||
UPX_CXX_DISABLE_COPY_MOVE(MemBuffer) // disable copy and move
|
||||
UPX_CXX_DISABLE_NEW_DELETE_NO_VIRTUAL(MemBuffer) // disable dynamic allocation
|
||||
};
|
||||
|
||||
/* vim:set ts=4 sw=4 et: */
|
||||
|
@ -128,8 +128,10 @@ forceinline void ptr_check_no_overlap(const void *a, size_t a_size, const void *
|
||||
// invalidate and poison a pointer: point to a non-null invalid address
|
||||
// - resulting pointer should crash on dereference
|
||||
// - this should be efficient, so no mmap() guard page etc.
|
||||
// - this should play nice with runtime checkers like ASAN, MSAN, valgrind, etc.
|
||||
// - this should play nice with runtime checkers like ASAN, MSAN, UBSAN, valgrind, etc.
|
||||
// - 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
|
||||
template <class T>
|
||||
inline void ptr_invalidate_and_poison(T *(&ptr)) noexcept {
|
||||
ptr = (T *) (void *) 251; // 0x000000fb // NOLINT(performance-no-int-to-ptr)
|
||||
|
Loading…
Reference in New Issue
Block a user