diff --git a/.clang-format b/.clang-format new file mode 100644 index 0000000..551c865 --- /dev/null +++ b/.clang-format @@ -0,0 +1,36 @@ +--- +Language: Cpp +Standard: c++20 +BasedOnStyle: LLVM + +IndentWidth: 4 +TabWidth: 4 +NamespaceIndentation: All +AccessModifierOffset: -4 + +ColumnLimit: 120 + +PenaltyReturnTypeOnItsOwnLine: 1000 + +BinPackParameters: false +BinPackArguments: false +AlignAfterOpenBracket: BlockIndent + +AllowShortFunctionsOnASingleLine: None +InsertBraces: true +AllowShortLambdasOnASingleLine: Empty + +BreakConstructorInitializers: AfterColon +PackConstructorInitializers: CurrentLine + +PointerAlignment: Left +ReferenceAlignment: Left + +SpaceAfterTemplateKeyword: false +AlwaysBreakTemplateDeclarations: No + +SortIncludes: Never + +AlignTrailingComments: + Kind: Always + OverEmptyLines: 2 diff --git a/.clang-tidy b/.clang-tidy new file mode 100644 index 0000000..51d9e93 --- /dev/null +++ b/.clang-tidy @@ -0,0 +1,55 @@ +Checks: > + readability-identifier-naming, + readability-implicit-bool-conversion, + misc-const-correctness, + -clang-diagnostic-error + +CheckOptions: + - key: readability-identifier-naming.ClassCase + value: lower_case + - key: readability-identifier-naming.StructCase + value: lower_case + + - key: readability-identifier-naming.FunctionCase + value: lower_case + - key: readability-identifier-naming.MethodCase + value: lower_case + - key: readability-identifier-naming.MethodIgnoredRegexp + value: '^[A-Z][A-Z0-9_]*$' + + - key: readability-identifier-naming.VariableCase + value: lower_case + - key: readability-identifier-naming.VariableIgnoredRegexp + value: '^[A-Z][A-Z0-9_]*$' + - key: readability-identifier-naming.LocalVariableCase + value: lower_case + - key: readability-identifier-naming.ParameterCase + value: lower_case + + - key: readability-identifier-naming.MemberCase + value: lower_case + - key: readability-identifier-naming.MemberIgnoredRegexp + value: '^([A-Z][A-Z0-9_]*|[a-z][a-z0-9_]*_)$' + - key: readability-identifier-naming.PrivateMemberSuffix + value: '_' + - key: readability-identifier-naming.ProtectedMemberSuffix + value: '_' + - key: readability-identifier-naming.ConstantMemberIgnoredRegexp + value: '^[A-Z][A-Z0-9_]*$' + + - key: readability-identifier-naming.EnumConstantCase + value: CamelCase + + - key: readability-identifier-naming.EnumCase + value: lower_case + + - key: readability-identifier-naming.TemplateParameterCase + value: CamelCase + + - key: readability-identifier-naming.NamespaceCase + value: lower_case + + - key: readability-identifier-naming.TypeAliasCase + value: lower_case + - key: readability-identifier-naming.TypeAliasIgnoredRegexp + value: '^[A-Z]$' diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8eaf380..071e60f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -107,10 +107,38 @@ jobs: alert-threshold: '150%' fail-on-alert: true + clang-format: + name: Clang Format + runs-on: ubuntu-latest + if: github.event_name == 'pull_request' + steps: + - uses: actions/checkout@v4 + - name: Check formatting + run: | + find include tests -name "*.h" -o -name "*.cpp" | \ + xargs clang-format --dry-run --Werror + + clang-tidy: + name: Clang Tidy + runs-on: ubuntu-latest + if: github.event_name == 'pull_request' + steps: + - uses: actions/checkout@v4 + - name: Install Clang-Tidy 19 + run: | + wget -qO- https://apt.llvm.org/llvm-snapshot.gpg.key | sudo tee /etc/apt/trusted.gpg.d/apt.llvm.org.asc + echo "deb http://apt.llvm.org/noble/ llvm-toolchain-noble-19 main" | sudo tee /etc/apt/sources.list.d/llvm.list + sudo apt-get update + sudo apt-get install -y clang-tidy-19 + - name: Check tidy + run: | + find include -name "*.h" -o -name "*.cpp" | \ + xargs -I{} clang-tidy-19 {} -- -x c++ -std=c++20 -I include -include cstdint -include cstddef + all-checks: name: All Checks runs-on: ubuntu-latest if: github.event_name == 'pull_request' - needs: [unittests] + needs: [unittests, clang-format, clang-tidy] steps: - run: echo "All checks passed" diff --git a/.gitignore b/.gitignore index 6a9a1d3..3ab59dc 100644 --- a/.gitignore +++ b/.gitignore @@ -18,4 +18,5 @@ install/ *.tlog *.user *.iml -*.xml \ No newline at end of file +*.xml +*.bat \ No newline at end of file diff --git a/include/obfuscxx/obfuscxx.h b/include/obfuscxx/obfuscxx.h index b500f93..f8a5514 100644 --- a/include/obfuscxx/obfuscxx.h +++ b/include/obfuscxx/obfuscxx.h @@ -30,9 +30,9 @@ using max_align_t = double; #if defined(__aarch64__) || defined(_M_ARM64) || defined(__ARM_NEON) #include -#elif defined(_MSC_VER) || defined(__clang__) +#elif defined(_WIN32) #include -#elif defined(__GNUC__) +#elif defined(__GNUC__) || defined(__clang__) #include #include #else @@ -64,11 +64,11 @@ using max_align_t = double; #endif #if defined(__clang__) || defined(__GNUC__) -#define OBFUSCXX_MEM_BARRIER(...) __asm__ volatile("" : "+r"(__VA_ARGS__) :: "memory"); +#define OBFUSCXX_MEM_BARRIER(...) __asm__ volatile("" : "+r"(__VA_ARGS__)::"memory"); #if defined(__aarch64__) || defined(_M_ARM64) -#define OBFUSCXX_MEM_BARRIER_VEC(v0, v1, sum) __asm__ volatile("" : "+w"(v0), "+w"(v1), "+r"(sum) :: "memory"); +#define OBFUSCXX_MEM_BARRIER_VEC(v0, v1, sum) __asm__ volatile("" : "+w"(v0), "+w"(v1), "+r"(sum)::"memory"); #else -#define OBFUSCXX_MEM_BARRIER_VEC(v0, v1, sum) __asm__ volatile("" : "+x"(v0), "+x"(v1), "+r"(sum) :: "memory"); +#define OBFUSCXX_MEM_BARRIER_VEC(v0, v1, sum) __asm__ volatile("" : "+x"(v0), "+x"(v1), "+r"(sum)::"memory"); #endif #elif defined(_MSC_VER) #define OBFUSCXX_MEM_BARRIER(...) _ReadWriteBarrier(); @@ -76,7 +76,9 @@ using max_align_t = double; #endif #ifndef OBFUSCXX_DISABLE_WARNS -#define OBFUSCXX_RUNTIME_WARNING [[deprecated("OBFUSCXX: Runtime set() uses encrypt method without SIMD obfuscation. For better protection, initialize at compile-time.")]] +#define OBFUSCXX_RUNTIME_WARNING \ + [[deprecated("OBFUSCXX: Runtime set() uses encrypt method without SIMD obfuscation. For better protection, " \ + "initialize at compile-time.")]] #else #define OBFUSCXX_RUNTIME_WARNING #endif @@ -105,10 +107,11 @@ namespace ngu { return hash; } - OBFUSCXX_FORCEINLINE std::uint64_t hash_runtime(char const *str) { + OBFUSCXX_FORCEINLINE std::uint64_t hash_runtime(char const* str) { std::size_t length = 0; - while (str[length]) + while (str[length] != 0) { ++length; + } std::uint64_t hash = 0; @@ -127,81 +130,133 @@ namespace ngu { constexpr std::uint64_t rol64(std::uint64_t x, int n) { n &= 63; - if (n == 0) return x; + if (n == 0) { + return x; + } return (x << n) | (x >> (64 - n)); } constexpr std::uint64_t ror64(std::uint64_t x, int n) { n &= 63; - if (n == 0) return x; + if (n == 0) { + return x; + } return (x >> n) | (x << (64 - n)); } - } + } // namespace detail template struct simd; #if defined(__aarch64__) || defined(_M_ARM64) template<> struct simd { using vec = uint32x4_t; - static OBFUSCXX_FORCEINLINE vec shl4(vec v) { return vshlq_n_u32(v, 4); } - static OBFUSCXX_FORCEINLINE vec shr5(vec v) { return vshrq_n_u32(v, 5); } - static OBFUSCXX_FORCEINLINE vec vxor(vec a, vec b) { return veorq_u32(a, b); } - static OBFUSCXX_FORCEINLINE vec vadd(vec a, vec b) { return vaddq_u32(a, b); } - static OBFUSCXX_FORCEINLINE vec vsub(vec a, vec b) { return vsubq_u32(a, b); } - static OBFUSCXX_FORCEINLINE vec broadcast(std::uint32_t v) { return vdupq_n_u32(v); } - static OBFUSCXX_FORCEINLINE vec from_scalar(std::uint32_t v) { return vdupq_n_u32(v); } - static OBFUSCXX_FORCEINLINE std::uint32_t to_scalar(vec v) { return vgetq_lane_u32(v, 0); } + static OBFUSCXX_FORCEINLINE vec shl4(vec v) { + return vshlq_n_u32(v, 4); + } + static OBFUSCXX_FORCEINLINE vec shr5(vec v) { + return vshrq_n_u32(v, 5); + } + static OBFUSCXX_FORCEINLINE vec vxor(vec a, vec b) { + return veorq_u32(a, b); + } + static OBFUSCXX_FORCEINLINE vec vadd(vec a, vec b) { + return vaddq_u32(a, b); + } + static OBFUSCXX_FORCEINLINE vec vsub(vec a, vec b) { + return vsubq_u32(a, b); + } + static OBFUSCXX_FORCEINLINE vec broadcast(std::uint32_t v) { + return vdupq_n_u32(v); + } + static OBFUSCXX_FORCEINLINE vec from_scalar(std::uint32_t v) { + return vdupq_n_u32(v); + } + static OBFUSCXX_FORCEINLINE std::uint32_t to_scalar(vec v) { + return vgetq_lane_u32(v, 0); + } }; #else template<> struct simd<__m128i> { using vec = __m128i; - static OBFUSCXX_FORCEINLINE vec shl4(vec v) { return _mm_slli_epi32(v, 4); } - static OBFUSCXX_FORCEINLINE vec shr5(vec v) { return _mm_srli_epi32(v, 5); } - static OBFUSCXX_FORCEINLINE vec vxor(vec a, vec b) { return _mm_xor_si128(a, b); } - static OBFUSCXX_FORCEINLINE vec vadd(vec a, vec b) { return _mm_add_epi32(a, b); } - static OBFUSCXX_FORCEINLINE vec vsub(vec a, vec b) { return _mm_sub_epi32(a, b); } - static OBFUSCXX_FORCEINLINE vec broadcast(std::uint32_t v) { return _mm_set1_epi32(v); } - static OBFUSCXX_FORCEINLINE vec from_scalar(std::uint32_t v) { return _mm_cvtsi32_si128(v); } - static OBFUSCXX_FORCEINLINE std::uint32_t to_scalar(vec v) { return _mm_cvtsi128_si32(v); } + static OBFUSCXX_FORCEINLINE vec shl4(vec v) { + return _mm_slli_epi32(v, 4); + } + static OBFUSCXX_FORCEINLINE vec shr5(vec v) { + return _mm_srli_epi32(v, 5); + } + static OBFUSCXX_FORCEINLINE vec vxor(vec a, vec b) { + return _mm_xor_si128(a, b); + } + static OBFUSCXX_FORCEINLINE vec vadd(vec a, vec b) { + return _mm_add_epi32(a, b); + } + static OBFUSCXX_FORCEINLINE vec vsub(vec a, vec b) { + return _mm_sub_epi32(a, b); + } + static OBFUSCXX_FORCEINLINE vec broadcast(std::uint32_t v) { + return _mm_set1_epi32(v); + } + static OBFUSCXX_FORCEINLINE vec from_scalar(std::uint32_t v) { + return _mm_cvtsi32_si128(v); + } + static OBFUSCXX_FORCEINLINE std::uint32_t to_scalar(vec v) { + return _mm_cvtsi128_si32(v); + } }; #if OBFUSCXX_HAS_AVX2 template<> struct simd<__m256i> { using vec = __m256i; - static OBFUSCXX_FORCEINLINE vec shl4(vec v) { return _mm256_slli_epi32(v, 4); } - static OBFUSCXX_FORCEINLINE vec shr5(vec v) { return _mm256_srli_epi32(v, 5); } - static OBFUSCXX_FORCEINLINE vec vxor(vec a, vec b) { return _mm256_xor_si256(a, b); } - static OBFUSCXX_FORCEINLINE vec vadd(vec a, vec b) { return _mm256_add_epi32(a, b); } - static OBFUSCXX_FORCEINLINE vec vsub(vec a, vec b) { return _mm256_sub_epi32(a, b); } - static OBFUSCXX_FORCEINLINE vec broadcast(std::uint32_t v) { return _mm256_set1_epi32(v); } - static OBFUSCXX_FORCEINLINE vec from_scalar(std::uint32_t v) { return _mm256_set1_epi32(v); } - static OBFUSCXX_FORCEINLINE std::uint32_t to_scalar(vec v) { return _mm256_extract_epi32(v, 0); } + static OBFUSCXX_FORCEINLINE vec shl4(vec v) { + return _mm256_slli_epi32(v, 4); + } + static OBFUSCXX_FORCEINLINE vec shr5(vec v) { + return _mm256_srli_epi32(v, 5); + } + static OBFUSCXX_FORCEINLINE vec vxor(vec a, vec b) { + return _mm256_xor_si256(a, b); + } + static OBFUSCXX_FORCEINLINE vec vadd(vec a, vec b) { + return _mm256_add_epi32(a, b); + } + static OBFUSCXX_FORCEINLINE vec vsub(vec a, vec b) { + return _mm256_sub_epi32(a, b); + } + static OBFUSCXX_FORCEINLINE vec broadcast(std::uint32_t v) { + return _mm256_set1_epi32(v); + } + static OBFUSCXX_FORCEINLINE vec from_scalar(std::uint32_t v) { + return _mm256_set1_epi32(v); + } + static OBFUSCXX_FORCEINLINE std::uint32_t to_scalar(vec v) { + return _mm256_extract_epi32(v, 0); + } }; #endif #endif -#define OBFUSCXX_HASH( s ) detail::hash_compile_time( s ) -#define OBFUSCXX_HASH_RT( s ) detail::hash_runtime( s ) +#define OBFUSCXX_HASH(s) detail::hash_compile_time(s) +#define OBFUSCXX_HASH_RT(s) detail::hash_runtime(s) #if defined(_KERNEL_MODE) || defined(_WIN64_DRIVER) -#define OBFUSCXX_ENTROPY ( \ -detail::splitmix64( \ -(OBFUSCXX_HASH(__FILE__) * 0x517cc1b727220a95ULL) + \ -((std::uint64_t)__LINE__ * 0x9e3779b97f4a7c15ULL) + \ -(detail::rol64((std::uint64_t)__COUNTER__, 37) ^ ((std::uint64_t)__LINE__ * 0xff51afd7ed558ccdULL)) \ -) \ -) +#define OBFUSCXX_ENTROPY \ + (detail::splitmix64( \ + (OBFUSCXX_HASH(__FILE__) * 0x517cc1b727220a95ULL) + ((std::uint64_t)__LINE__ * 0x9e3779b97f4a7c15ULL) + \ + (detail::rol64((std::uint64_t)__COUNTER__, 37) ^ ((std::uint64_t)__LINE__ * 0xff51afd7ed558ccdULL)) \ + )) #else -#define OBFUSCXX_ENTROPY ( \ -detail::splitmix64( \ -OBFUSCXX_HASH(__FILE__) + \ -((std::uint64_t)__LINE__ * 0x9e3779b97f4a7c15ULL) + \ -(OBFUSCXX_HASH(__TIME__) ^ ((std::uint64_t)__COUNTER__ << 32)) \ -) \ -) +#define OBFUSCXX_ENTROPY \ + (detail::splitmix64( \ + OBFUSCXX_HASH(__FILE__) + ((std::uint64_t)__LINE__ * 0x9e3779b97f4a7c15ULL) + \ + (OBFUSCXX_HASH(__TIME__) ^ ((std::uint64_t)__COUNTER__ << 32)) \ + )) #endif enum class obf_level : std::uint8_t { Low, Medium, High }; - template + template< + class Type, + std::size_t Size = 1, + obf_level Level = obf_level::Low, + std::uint64_t Entropy = OBFUSCXX_ENTROPY> class obfuscxx { static constexpr bool is_single = Size == 1; static constexpr bool is_array = Size > 1; @@ -211,11 +266,14 @@ OBFUSCXX_HASH(__FILE__) + \ static constexpr std::size_t storage_multiple = OBFUSCXX_HAS_AVX2 ? 8 : 4; static constexpr std::size_t storage_alignment = OBFUSCXX_HAS_AVX2 ? 32 : 16; - static constexpr std::size_t storage_size = is_array ? (Size + storage_multiple - 1) & ~(storage_multiple - 1) : Size; + static constexpr std::size_t storage_size = + is_array ? (Size + storage_multiple - 1) & ~(storage_multiple - 1) : Size; - struct passkey { explicit passkey() = default; }; + struct passkey { + explicit passkey() = default; + }; - static constexpr std::uint64_t seed{ Entropy }; + static constexpr std::uint64_t seed{Entropy}; static constexpr std::uint64_t iv[8] = { 0xcbf43b227a01fe5aULL ^ seed, 0x32703be7aaa7c38fULL ^ detail::ror64(seed, 13), @@ -230,8 +288,9 @@ OBFUSCXX_HASH(__FILE__) + \ static constexpr std::uint64_t unique_index = seed & iv_size; static constexpr std::uint64_t unique_value = iv[unique_index]; - static constexpr std::uint32_t xtea_rounds = - (Level == obf_level::Low) ? 2 : (Level == obf_level::Medium) ? 6 : (8 + ((unique_value % 13) * 2)); + static constexpr std::uint32_t xtea_rounds = (Level == obf_level::Low) ? 2 + : (Level == obf_level::Medium) ? 6 + : (8 + ((unique_value % 13) * 2)); static constexpr std::uint32_t xtea_delta = (0x9E3779B9 ^ static_cast(unique_value)) | 1; @@ -243,11 +302,9 @@ OBFUSCXX_HASH(__FILE__) + \ std::uint32_t sum = 0; for (std::uint32_t i{}; i < xtea_rounds; ++i) { - v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ - (sum + static_cast(iv[sum & 3])); + v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + static_cast(iv[sum & 3])); sum += xtea_delta; - v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ - (sum + static_cast(iv[(sum >> 11) & 3])); + v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + static_cast(iv[(sum >> 11) & 3])); } return (static_cast(v1) << 32) | v0; @@ -276,7 +333,7 @@ OBFUSCXX_HASH(__FILE__) + \ return from_uint64((static_cast(v1) << 32) | v0); } - template static OBFUSCXX_FORCEINLINE void decrypt_rounds(Vec &v0_vec, Vec &v1_vec) { + template static OBFUSCXX_FORCEINLINE void decrypt_rounds(Vec& v0_vec, Vec& v1_vec) { std::uint32_t sum = xtea_delta * xtea_rounds; for (std::uint32_t i{}; i < xtea_rounds; ++i) { @@ -310,12 +367,15 @@ OBFUSCXX_HASH(__FILE__) + \ #endif } - static OBFUSCXX_FORCEINLINE void decrypt_vectorized(const volatile std::uint64_t *src, Type *dst, std::size_t count) { - std::size_t aligned_count = (count + storage_multiple - 1) & ~(storage_multiple - 1); + static OBFUSCXX_FORCEINLINE void decrypt_vectorized( + const volatile std::uint64_t* src, Type* dst, std::size_t count + ) { + std::size_t const aligned_count = (count + storage_multiple - 1) & ~(storage_multiple - 1); #if defined(__aarch64__) || defined(_M_ARM64) for (std::size_t i{}; i < aligned_count; i += 4) { - uint32x4x2_t loaded = vld2q_u32(reinterpret_cast(const_cast(src + i))); + uint32x4x2_t loaded = + vld2q_u32(reinterpret_cast(const_cast(src + i))); uint32x4_t v0_vec = loaded.val[0]; uint32x4_t v1_vec = loaded.val[1]; @@ -336,18 +396,18 @@ OBFUSCXX_HASH(__FILE__) + \ if (cpu_has_avx2()) { #endif for (std::size_t i{}; i < aligned_count; i += 8) { - const auto *p = reinterpret_cast(const_cast(src + i)); + const auto* p = reinterpret_cast(const_cast(src + i)); __m256i d0 = _mm256_load_si256(p); __m256i d1 = _mm256_load_si256(p + 1); __m256i perm_even = _mm256_set_epi32(0, 0, 0, 0, 6, 4, 2, 0); - __m256i perm_odd = _mm256_set_epi32(0, 0, 0, 0, 7, 5, 3, 1); + __m256i perm_odd = _mm256_set_epi32(0, 0, 0, 0, 7, 5, 3, 1); __m256i v0_vec = _mm256_permute2x128_si256( - _mm256_permutevar8x32_epi32(d0, perm_even), - _mm256_permutevar8x32_epi32(d1, perm_even), 0x20); + _mm256_permutevar8x32_epi32(d0, perm_even), _mm256_permutevar8x32_epi32(d1, perm_even), 0x20 + ); __m256i v1_vec = _mm256_permute2x128_si256( - _mm256_permutevar8x32_epi32(d0, perm_odd), - _mm256_permutevar8x32_epi32(d1, perm_odd), 0x20); + _mm256_permutevar8x32_epi32(d0, perm_odd), _mm256_permutevar8x32_epi32(d1, perm_odd), 0x20 + ); decrypt_rounds(v0_vec, v1_vec); @@ -369,7 +429,7 @@ OBFUSCXX_HASH(__FILE__) + \ #if defined(_MSC_VER) && !defined(__clang__) && !defined(OBFUSCXX_MSVC_FORCE_AVX2) } else { for (std::size_t i{}; i < aligned_count; i += 4) { - const auto *p = reinterpret_cast(const_cast(src + i)); + const auto* p = reinterpret_cast(const_cast(src + i)); __m128i d0 = _mm_load_si128(p); __m128i d1 = _mm_load_si128(p + 1); @@ -377,11 +437,13 @@ OBFUSCXX_HASH(__FILE__) + \ __m128i v0_vec = _mm_castps_si128(_mm_shuffle_ps( _mm_castsi128_ps(_mm_and_si128(d0, mask)), _mm_castsi128_ps(_mm_and_si128(d1, mask)), - _MM_SHUFFLE(2, 0, 2, 0))); + _MM_SHUFFLE(2, 0, 2, 0) + )); __m128i v1_vec = _mm_castps_si128(_mm_shuffle_ps( _mm_castsi128_ps(_mm_srli_epi64(d0, 32)), _mm_castsi128_ps(_mm_srli_epi64(d1, 32)), - _MM_SHUFFLE(2, 0, 2, 0))); + _MM_SHUFFLE(2, 0, 2, 0) + )); decrypt_rounds(v0_vec, v1_vec); @@ -399,24 +461,26 @@ OBFUSCXX_HASH(__FILE__) + \ #endif #else for (std::size_t i{}; i < aligned_count; i += 4) { - const auto *p = reinterpret_cast(const_cast(src + i)); + const auto* p = reinterpret_cast(const_cast(src + i)); - __m128i d0 = _mm_load_si128(p); - __m128i d1 = _mm_load_si128(p + 1); - __m128i mask = _mm_set1_epi64x(0xFFFFFFFF); + __m128i const d0 = _mm_load_si128(p); + __m128i const d1 = _mm_load_si128(p + 1); + __m128i const mask = _mm_set1_epi64x(0xFFFFFFFF); __m128i v0_vec = _mm_castps_si128(_mm_shuffle_ps( _mm_castsi128_ps(_mm_and_si128(d0, mask)), _mm_castsi128_ps(_mm_and_si128(d1, mask)), - _MM_SHUFFLE(2, 0, 2, 0))); + _MM_SHUFFLE(2, 0, 2, 0) + )); __m128i v1_vec = _mm_castps_si128(_mm_shuffle_ps( _mm_castsi128_ps(_mm_srli_epi64(d0, 32)), _mm_castsi128_ps(_mm_srli_epi64(d1, 32)), - _MM_SHUFFLE(2, 0, 2, 0))); + _MM_SHUFFLE(2, 0, 2, 0) + )); decrypt_rounds(v0_vec, v1_vec); - __m128i lo64 = _mm_unpacklo_epi32(v0_vec, v1_vec); - __m128i hi64 = _mm_unpackhi_epi32(v0_vec, v1_vec); + __m128i const lo64 = _mm_unpacklo_epi32(v0_vec, v1_vec); + __m128i const hi64 = _mm_unpackhi_epi32(v0_vec, v1_vec); alignas(16) std::uint64_t out64[4]; _mm_store_si128(reinterpret_cast<__m128i*>(&out64[0]), lo64); _mm_store_si128(reinterpret_cast<__m128i*>(&out64[2]), hi64); @@ -460,9 +524,9 @@ OBFUSCXX_HASH(__FILE__) + \ #if !defined(__aarch64__) && !defined(_M_ARM64) static const bool cached = []() { #if defined(_MSC_VER) - int cpuInfo[4]{}; - __cpuidex(cpuInfo, 7, 0); - return (cpuInfo[1] & (1 << 5)) != 0; + int cpu_info[4]{}; + __cpuidex(cpu_info, 7, 0); + return (cpu_info[1] & (1 << 5)) != 0; #else unsigned int eax, ebx, ecx, edx; if (!__get_cpuid_count(7, 0, &eax, &ebx, &ecx, &edx)) @@ -499,67 +563,92 @@ OBFUSCXX_HASH(__FILE__) + \ } } - consteval obfuscxx(const std::initializer_list &list) : obfuscxx(passkey{}) { - for (std::size_t i{}; const auto &v: list) + consteval obfuscxx(const std::initializer_list& list) : obfuscxx(passkey{}) { + for (std::size_t i{}; const auto& v : list) { storage_[i++] = encrypt(v); + } } - OBFUSCXX_FORCEINLINE Type get() const requires is_single { - volatile const std::uint64_t *ptr = &storage_[0]; + OBFUSCXX_FORCEINLINE Type get() const + requires is_single + { + volatile const std::uint64_t* ptr = &storage_[0]; std::uint64_t val = *ptr; return decrypt(val); } - OBFUSCXX_FORCEINLINE Type get(std::size_t i) const requires is_array { - volatile const std::uint64_t *ptr = &storage_[i]; + OBFUSCXX_FORCEINLINE Type get(std::size_t i) const + requires is_array + { + volatile const std::uint64_t* ptr = &storage_[i]; std::uint64_t val = *ptr; return decrypt(val); } - OBFUSCXX_FORCEINLINE void copy_to(Type *out, std::size_t count) const requires is_array { + OBFUSCXX_FORCEINLINE void copy_to(Type* out, std::size_t count) const + requires is_array + { std::size_t effective_count = (count < Size) ? count : Size; decrypt_vectorized(storage_, out, effective_count); } - OBFUSCXX_RUNTIME_WARNING OBFUSCXX_FORCEINLINE void set(Type val) requires is_single { + OBFUSCXX_RUNTIME_WARNING OBFUSCXX_FORCEINLINE void set(Type val) + requires is_single + { storage_[0] = encrypt(val); } - OBFUSCXX_RUNTIME_WARNING OBFUSCXX_FORCEINLINE void set(Type val, std::size_t i) requires is_array { + OBFUSCXX_RUNTIME_WARNING OBFUSCXX_FORCEINLINE void set(Type val, std::size_t i) + requires is_array + { storage_[i] = encrypt(val); } - OBFUSCXX_RUNTIME_WARNING OBFUSCXX_FORCEINLINE void set(const std::initializer_list &list) requires is_array { - for (std::size_t i{}; const auto &val: list) { + OBFUSCXX_RUNTIME_WARNING OBFUSCXX_FORCEINLINE void set(const std::initializer_list& list) + requires is_array + { + for (std::size_t i{}; const auto& val : list) { if (i < Size) { storage_[i++] = encrypt(val); } } } - OBFUSCXX_FORCEINLINE Type operator()() const requires is_single { + OBFUSCXX_FORCEINLINE Type operator()() const + requires is_single + { return get(); } - OBFUSCXX_FORCEINLINE Type operator[](std::size_t i) const requires is_array { + OBFUSCXX_FORCEINLINE Type operator[](std::size_t i) const + requires is_array + { return get(i); } - OBFUSCXX_FORCEINLINE obfuscxx &operator=(Type val) requires is_single { + OBFUSCXX_FORCEINLINE obfuscxx& operator=(Type val) + requires is_single + { set(val); return *this; } - OBFUSCXX_FORCEINLINE obfuscxx &operator=(const std::initializer_list &list) requires is_array { + OBFUSCXX_FORCEINLINE obfuscxx& operator=(const std::initializer_list& list) + requires is_array + { set(list); return *this; } - OBFUSCXX_FORCEINLINE bool operator==(const obfuscxx &rhs) const requires is_single { + OBFUSCXX_FORCEINLINE bool operator==(const obfuscxx& rhs) const + requires is_single + { return get() == rhs.get(); } - OBFUSCXX_FORCEINLINE bool operator==(const obfuscxx &rhs) const requires is_array { + OBFUSCXX_FORCEINLINE bool operator==(const obfuscxx& rhs) const + requires is_array + { for (std::size_t i{}; i < Size; ++i) { if (get(i) != rhs.get(i)) { return false; @@ -568,118 +657,177 @@ OBFUSCXX_HASH(__FILE__) + \ return true; } - OBFUSCXX_FORCEINLINE bool operator!=(const obfuscxx &rhs) const { + OBFUSCXX_FORCEINLINE bool operator!=(const obfuscxx& rhs) const { return !(*this == rhs); } - OBFUSCXX_FORCEINLINE operator Type() const requires is_single { + OBFUSCXX_FORCEINLINE operator Type() const + requires is_single + { return get(); } - OBFUSCXX_FORCEINLINE bool operator<(const obfuscxx &rhs) const { + OBFUSCXX_FORCEINLINE bool operator<(const obfuscxx& rhs) const { return get() < rhs.get(); } - OBFUSCXX_FORCEINLINE bool operator>(const obfuscxx &rhs) const { + OBFUSCXX_FORCEINLINE bool operator>(const obfuscxx& rhs) const { return get() > rhs.get(); } - OBFUSCXX_FORCEINLINE bool operator<=(const obfuscxx &rhs) const { + OBFUSCXX_FORCEINLINE bool operator<=(const obfuscxx& rhs) const { return get() <= rhs.get(); } - OBFUSCXX_FORCEINLINE bool operator>=(const obfuscxx &rhs) const { + OBFUSCXX_FORCEINLINE bool operator>=(const obfuscxx& rhs) const { return get() >= rhs.get(); } - OBFUSCXX_FORCEINLINE Type operator+(const obfuscxx &rhs) const { + OBFUSCXX_FORCEINLINE Type operator+(const obfuscxx& rhs) const { return get() + rhs.get(); } - OBFUSCXX_FORCEINLINE Type operator-(const obfuscxx &rhs) const { + OBFUSCXX_FORCEINLINE Type operator-(const obfuscxx& rhs) const { return get() - rhs.get(); } - OBFUSCXX_FORCEINLINE Type operator*(const obfuscxx &rhs) const requires (!is_single_pointer) { + OBFUSCXX_FORCEINLINE Type operator*(const obfuscxx& rhs) const + requires(!is_single_pointer) + { return get() * rhs.get(); } - OBFUSCXX_FORCEINLINE Type operator/(const obfuscxx &rhs) const requires (!is_single_pointer) { + OBFUSCXX_FORCEINLINE Type operator/(const obfuscxx& rhs) const + requires(!is_single_pointer) + { return get() / rhs.get(); } - OBFUSCXX_FORCEINLINE obfuscxx &operator+=(const obfuscxx &rhs) requires (!is_single_pointer) { + OBFUSCXX_FORCEINLINE obfuscxx& operator+=(const obfuscxx& rhs) + requires(!is_single_pointer) + { set(get() + rhs.get()); return *this; } - OBFUSCXX_FORCEINLINE obfuscxx &operator-=(const obfuscxx &rhs) requires (!is_single_pointer) { + OBFUSCXX_FORCEINLINE obfuscxx& operator-=(const obfuscxx& rhs) + requires(!is_single_pointer) + { set(get() - rhs.get()); return *this; } - OBFUSCXX_FORCEINLINE Type operator->() requires is_single_pointer { + OBFUSCXX_FORCEINLINE Type operator->() + requires is_single_pointer + { return get(); } - OBFUSCXX_FORCEINLINE Type &operator*() requires is_single_pointer { + OBFUSCXX_FORCEINLINE Type& operator*() + requires is_single_pointer + { return *get(); } struct iterator { - const obfuscxx *parent; + const obfuscxx* parent; std::size_t index; - Type operator*() const { return parent->get(index); } + Type operator*() const { + return parent->get(index); + } - iterator &operator++() { + iterator& operator++() { ++index; return *this; } - bool operator!=(const iterator &other) const { return index != other.index; } - bool operator==(const iterator &other) const { return index == other.index; } + bool operator!=(const iterator& other) const { + return index != other.index; + } + bool operator==(const iterator& other) const { + return index == other.index; + } }; - iterator begin() const requires is_array { return {this, 0}; } - iterator end() const requires is_array { return {this, Size}; } - static constexpr std::size_t size() { return Size; } + iterator begin() const + requires is_array + { + return {this, 0}; + } + iterator end() const + requires is_array + { + return {this, Size}; + } + static constexpr std::size_t size() { + return Size; + } template struct string_copy { private: - static constexpr bool is_char = std::is_same_v || - std::is_same_v; - static constexpr bool is_wchar = std::is_same_v || - std::is_same_v; + static constexpr bool is_char = std::is_same_v || std::is_same_v; + static constexpr bool is_wchar = + std::is_same_v || std::is_same_v; public: - operator const char *() const requires is_char { return data; } - operator const wchar_t *() const requires is_wchar { return data; } + operator const char*() const + requires is_char + { + return data; + } + operator const wchar_t*() const + requires is_wchar + { + return data; + } - const CharType *c_str() const { return data; } - const CharType &operator[](std::size_t i) const { return data[i]; } + const CharType* c_str() const { + return data; + } + const CharType& operator[](std::size_t i) const { + return data[i]; + } - const CharType *begin() const { return data; } - const CharType *end() const { return data + N; } + const CharType* begin() const { + return data; + } + const CharType* end() const { + return data + N; + } - constexpr std::size_t size() const { return N; } + constexpr std::size_t size() const { + return N; + } CharType data[N]; }; template struct array_copy { - const ArrayType *get() const { return data; } + const ArrayType* get() const { + return data; + } - const ArrayType *begin() const { return data; } - const ArrayType *end() const { return data + N; } + const ArrayType* begin() const { + return data; + } + const ArrayType* end() const { + return data + N; + } - constexpr std::size_t size() const { return N; } - constexpr std::size_t size_bytes() const { return N * sizeof(ArrayType); } + constexpr std::size_t size() const { + return N; + } + constexpr std::size_t size_bytes() const { + return N * sizeof(ArrayType); + } ArrayType data[N]; }; - OBFUSCXX_FORCEINLINE string_copy to_string() const requires (is_char || is_wchar) { + OBFUSCXX_FORCEINLINE string_copy to_string() const + requires(is_char || is_wchar) + { string_copy result{}; if constexpr (is_array) { copy_to(result.data, Size); @@ -689,7 +837,9 @@ OBFUSCXX_HASH(__FILE__) + \ return result; } - OBFUSCXX_FORCEINLINE array_copy to_array() const requires (is_array) { + OBFUSCXX_FORCEINLINE array_copy to_array() const + requires(is_array) + { array_copy result{}; copy_to(result.data, Size); return result; @@ -698,11 +848,11 @@ OBFUSCXX_HASH(__FILE__) + \ private: alignas(storage_alignment) OBFUSCXX_VOLATILE std::uint64_t storage_[storage_size]{}; }; -} +} // namespace ngu #if defined(__clang__) || defined(__GNUC__) -template constexpr auto operator""_obf() { - constexpr CharType str[] = {chars..., '\0'}; +template constexpr auto operator""_obf() { + constexpr CharType str[] = {Chars..., '\0'}; return ngu::obfuscxx(str).to_string(); } #endif diff --git a/tests/benchmark/benchmark.cpp b/tests/benchmark/benchmark.cpp index aa77577..102e6cf 100644 --- a/tests/benchmark/benchmark.cpp +++ b/tests/benchmark/benchmark.cpp @@ -24,7 +24,7 @@ using namespace ngu; static void BM_IntegerGet_Low(benchmark::State& state) { - obfuscxx int_value{ 42 }; + obfuscxx int_value{42}; for (auto _ : state) { benchmark::DoNotOptimize(int_value.get()); } @@ -32,7 +32,7 @@ static void BM_IntegerGet_Low(benchmark::State& state) { BENCHMARK(BM_IntegerGet_Low); static void BM_IntegerGet_Medium(benchmark::State& state) { - obfuscxx int_value{ 42 }; + obfuscxx int_value{42}; for (auto _ : state) { benchmark::DoNotOptimize(int_value.get()); } @@ -40,7 +40,7 @@ static void BM_IntegerGet_Medium(benchmark::State& state) { BENCHMARK(BM_IntegerGet_Medium); static void BM_IntegerGet_High(benchmark::State& state) { - obfuscxx int_value{ 42 }; + obfuscxx int_value{42}; for (auto _ : state) { benchmark::DoNotOptimize(int_value.get()); } @@ -48,7 +48,7 @@ static void BM_IntegerGet_High(benchmark::State& state) { BENCHMARK(BM_IntegerGet_High); static void BM_FloatGet_Low(benchmark::State& state) { - obfuscxx float_value{ 42.5f }; + obfuscxx float_value{42.5f}; for (auto _ : state) { benchmark::DoNotOptimize(float_value.get()); } @@ -56,7 +56,7 @@ static void BM_FloatGet_Low(benchmark::State& state) { BENCHMARK(BM_FloatGet_Low); static void BM_FloatGet_Medium(benchmark::State& state) { - obfuscxx float_value{ 42.5f }; + obfuscxx float_value{42.5f}; for (auto _ : state) { benchmark::DoNotOptimize(float_value.get()); } @@ -64,7 +64,7 @@ static void BM_FloatGet_Medium(benchmark::State& state) { BENCHMARK(BM_FloatGet_Medium); static void BM_FloatGet_High(benchmark::State& state) { - obfuscxx float_value{ 42.5f }; + obfuscxx float_value{42.5f}; for (auto _ : state) { benchmark::DoNotOptimize(float_value.get()); } diff --git a/tests/unittest/unittest.cpp b/tests/unittest/unittest.cpp index a40e124..73aee60 100644 --- a/tests/unittest/unittest.cpp +++ b/tests/unittest/unittest.cpp @@ -26,7 +26,7 @@ using namespace ngu; TEST(ObfuscxxTest, IntegerValue) { - obfuscxx value{ 100 }; + obfuscxx value{100}; EXPECT_EQ(value.get(), 100); value = 50; @@ -34,13 +34,13 @@ TEST(ObfuscxxTest, IntegerValue) { } TEST(ObfuscxxTest, FloatValue) { - obfuscxx value{ 1.5f }; + obfuscxx value{1.5f}; EXPECT_FLOAT_EQ(value.get(), 1.5f); } TEST(ObfuscxxTest, ArrayIteration) { - obfuscxx array{ 1, 2, 3, 4 }; - int expected[] = { 1, 2, 3, 4 }; + obfuscxx array{1, 2, 3, 4}; + int expected[] = {1, 2, 3, 4}; int i = 0; for (auto val : array) { EXPECT_EQ(val, expected[i++]); @@ -57,16 +57,16 @@ TEST(ObfuscxxTest, ToString) { TEST(ObfuscxxTest, PointerValue) { obfuscxx pointer{}; - pointer = new int{ 101 }; + pointer = new int{101}; EXPECT_NE(pointer.get(), nullptr); EXPECT_EQ(*pointer.get(), 101); delete pointer.get(); } TEST(ObfuscxxTest, ComparisonOperators) { - obfuscxx a{ 100 }; - obfuscxx b{ 100 }; - obfuscxx c{ 50 }; + obfuscxx a{100}; + obfuscxx b{100}; + obfuscxx c{50}; EXPECT_TRUE(a == b); EXPECT_FALSE(a == c); @@ -79,8 +79,8 @@ TEST(ObfuscxxTest, ComparisonOperators) { } TEST(ObfuscxxTest, ArithmeticOperators) { - obfuscxx a{ 10 }; - obfuscxx b{ 5 }; + obfuscxx a{10}; + obfuscxx b{5}; EXPECT_EQ(a + b, 15); EXPECT_EQ(a - b, 5); @@ -95,9 +95,9 @@ TEST(ObfuscxxTest, ArithmeticOperators) { } TEST(ObfuscxxTest, ObfuscationLevels) { - obfuscxx low{ 42 }; - obfuscxx medium{ 42 }; - obfuscxx high{ 42 }; + obfuscxx low{42}; + obfuscxx medium{42}; + obfuscxx high{42}; EXPECT_EQ(low.get(), 42); EXPECT_EQ(medium.get(), 42); @@ -105,10 +105,10 @@ TEST(ObfuscxxTest, ObfuscationLevels) { } TEST(ObfuscxxTest, EdgeCases) { - obfuscxx max_int{ INT_MAX }; - obfuscxx min_int{ INT_MIN }; - obfuscxx zero{ 0 }; - obfuscxx negative{ -12345 }; + obfuscxx max_int{INT_MAX}; + obfuscxx min_int{INT_MIN}; + obfuscxx zero{0}; + obfuscxx negative{-12345}; EXPECT_EQ(max_int.get(), INT_MAX); EXPECT_EQ(min_int.get(), INT_MIN); @@ -117,10 +117,10 @@ TEST(ObfuscxxTest, EdgeCases) { } TEST(ObfuscxxTest, FloatEdgeCases) { - obfuscxx zero{ 0.0f }; - obfuscxx negative{ -3.14f }; - obfuscxx small{ 0.0001f }; - obfuscxx large{ 123456.789f }; + obfuscxx zero{0.0f}; + obfuscxx negative{-3.14f}; + obfuscxx small{0.0001f}; + obfuscxx large{123456.789f}; EXPECT_FLOAT_EQ(zero.get(), 0.0f); EXPECT_FLOAT_EQ(negative.get(), -3.14f); @@ -129,7 +129,7 @@ TEST(ObfuscxxTest, FloatEdgeCases) { } TEST(ObfuscxxTest, ArrayOperators) { - obfuscxx array{ 10, 20, 30, 40, 50 }; + obfuscxx array{10, 20, 30, 40, 50}; EXPECT_EQ(array[0], 10); EXPECT_EQ(array[2], 30); @@ -142,7 +142,7 @@ TEST(ObfuscxxTest, ArrayOperators) { } TEST(ObfuscxxTest, ArraySet) { - obfuscxx array{ 1, 2, 3 }; + obfuscxx array{1, 2, 3}; array.set(100, 0); array.set(200, 1); @@ -154,8 +154,8 @@ TEST(ObfuscxxTest, ArraySet) { } TEST(ObfuscxxTest, ArrayCopyTo) { - obfuscxx array{ 1, 2, 3, 4, 5 }; - int output[5] = { 0 }; + obfuscxx array{1, 2, 3, 4, 5}; + int output[5] = {0}; array.copy_to(output, 5); @@ -165,8 +165,8 @@ TEST(ObfuscxxTest, ArrayCopyTo) { } TEST(ObfuscxxTest, ToArray) { - const obfuscxx array{ 0, 1, 2, 3 }; - auto const deobf_array = array.to_array(); + const obfuscxx array{0, 1, 2, 3}; + auto const deobf_array = array.to_array(); std::array buffer{}; memcpy(buffer.data(), deobf_array.get(), deobf_array.size_bytes()); @@ -178,9 +178,9 @@ TEST(ObfuscxxTest, ToArray) { } TEST(ObfuscxxTest, ArrayAssignment) { - obfuscxx array{ 1, 2, 3 }; + obfuscxx array{1, 2, 3}; - array = { 10, 20, 30 }; + array = {10, 20, 30}; EXPECT_EQ(array[0], 10); EXPECT_EQ(array[1], 20); @@ -188,7 +188,7 @@ TEST(ObfuscxxTest, ArrayAssignment) { } TEST(ObfuscxxTest, DataIsEncrypted) { - obfuscxx value{ 42 }; + obfuscxx value{42}; const uint64_t* raw_data = reinterpret_cast(&value); volatile uint64_t encrypted = *raw_data; @@ -200,7 +200,7 @@ TEST(ObfuscxxTest, DataIsEncrypted) { TEST(ObfuscxxTest, PointerOperators) { obfuscxx ptr{}; - ptr = new int{ 999 }; + ptr = new int{999}; EXPECT_NE(ptr.get(), nullptr); @@ -223,13 +223,13 @@ TEST(ObfuscxxTest, LongString) { } TEST(ObfuscxxTest, ConstCorrectness) { - const obfuscxx const_value{ 42 }; + const obfuscxx const_value{42}; EXPECT_EQ(const_value.get(), 42); EXPECT_EQ(const_value(), 42); } TEST(ObfuscxxTest, IteratorOperations) { - obfuscxx array{ 1, 2, 3, 4, 5 }; + obfuscxx array{1, 2, 3, 4, 5}; auto it = array.begin(); EXPECT_EQ(*it, 1); @@ -247,9 +247,9 @@ TEST(ObfuscxxTest, IteratorOperations) { } TEST(ObfuscxxTest, DifferentTypes) { - obfuscxx u64{ 0xFFFFFFFFFFFFFFFF }; - obfuscxx i8{ -127 }; - obfuscxx dbl{ 3.141592653589793 }; + obfuscxx u64{0xFFFFFFFFFFFFFFFF}; + obfuscxx i8{-127}; + obfuscxx dbl{3.141592653589793}; EXPECT_EQ(u64.get(), 0xFFFFFFFFFFFFFFFF); EXPECT_EQ(i8.get(), -127); @@ -257,7 +257,7 @@ TEST(ObfuscxxTest, DifferentTypes) { } TEST(ObfuscxxTest, MultipleAssignments) { - obfuscxx value{ 10 }; + obfuscxx value{10}; value = 20; EXPECT_EQ(value.get(), 20); @@ -270,9 +270,9 @@ TEST(ObfuscxxTest, MultipleAssignments) { } TEST(ObfuscxxTest, ArrayEquality) { - obfuscxx a{ 1, 2, 3 }; - obfuscxx b{ 1, 2, 3 }; - obfuscxx c{ 1, 2, 4 }; + obfuscxx a{1, 2, 3}; + obfuscxx b{1, 2, 3}; + obfuscxx c{1, 2, 4}; EXPECT_TRUE(a == b); EXPECT_FALSE(a == c); @@ -280,7 +280,7 @@ TEST(ObfuscxxTest, ArrayEquality) { } TEST(ObfuscxxTest, ImplicitConversion) { - obfuscxx value{ 42 }; + obfuscxx value{42}; int x = value; EXPECT_EQ(x, 42);