Files
shadowsocks-libev/cmake/ProjectOptions.cmake
T
Max Lv 8d39cd7569 C++20 port 6/14: allocation-free AEAD codecs (#3070)
* Add allocation-free C++ AEAD codecs

src/crypto/aead.hpp implements the SIP004/SIP007 AEAD ciphers as value
types: AeadEngine holds the libsodium or Mbed TLS GCM state by value,
AeadTcpEncryptor/AeadTcpDecryptor frame the chunk stream with a fixed
reassembly buffer, and aead_udp_seal/open handle packets. HKDF-SHA1 runs
on stack SHA-1 state instead of Mbed TLS's allocating HMAC API.

The bundled Mbed TLS config now enables MBEDTLS_BLOCK_CIPHER_C, which
keeps the AES context inside mbedtls_gcm_context, so GCM key setup no
longer allocates. That alone saves the C programs two allocations per
connection.

test_crypto_aead_cpp checks HKDF against RFC 5869 and crypto_hkdf, runs
TCP streams and UDP packets between the C and C++ implementations in
both directions for all five AEAD methods, and covers tampering,
framing and salt replay. alloc_steady_crypto_aead runs it under the
malloc counter and requires zero allocations across 600 new
connections and 600 packets (tests/alloc_audit/check_steady.py).

ss_strict_warnings() now applies -Wextra per source file so targets
mixing new C++ with converted C modules keep the latter at -Wall, and
Result gains move assignment.

* Include <algorithm> for std::min in test_crypto_aead_cpp.cpp

* Build the C++ AEAD codecs against Mbed TLS 2.x

Mbed TLS 2 returns void from mbedtls_sha1_starts/update/finish (the int
versions are the _ret variants), which the system-library build on
Ubuntu (2.28) rejects. crypto/mbedtls_compat.hpp gives one int-returning
spelling for both.

* Include C++ headers before crypto.h in test_crypto_aead_cpp.cpp

crypto.h defines min/max macros for the C sources; libstdc++ headers
included after it fail to parse.

* Disable the zero-allocation checks with a system Mbed TLS

They hold for the bundled Mbed TLS (MBEDTLS_BLOCK_CIPHER_C); a system
one may allocate in GCM key setup, as the Debian package build shows.
2026-10-15 09:56:12 +08:00

75 lines
3.6 KiB
CMake

include(CheckCCompilerFlag)
option(DISABLE_SSP "Disable stack protector" OFF)
if(NOT DISABLE_SSP AND NOT MSVC)
check_c_compiler_flag(-fstack-protector-strong HAS_STACK_PROTECTOR)
endif()
function(ss_project_options target)
set_property(TARGET ${target} PROPERTY NO_SYSTEM_FROM_IMPORTED TRUE)
target_include_directories(${target} BEFORE PRIVATE ${MBEDTLS_INCLUDE_DIRS})
if(WIN32)
target_compile_definitions(${target} PRIVATE WIN32_LEAN_AND_MEAN __USE_MINGW_ANSI_STDIO=1)
# MinGW can otherwise pull in libwinpthread/libgcc from the toolchain,
# even when all explicitly selected dependencies are static archives.
get_target_property(ss_target_type ${target} TYPE)
# Zig already supplies its own runtime for DLLs; its -static switch
# changes the output kind instead of just selecting static libraries.
if(NOT ss_target_type STREQUAL "SHARED_LIBRARY" OR CMAKE_C_COMPILER_ID STREQUAL "GNU")
target_link_options(${target} PRIVATE -static)
endif()
endif()
if(MSVC)
target_compile_options(${target} PRIVATE /W4)
if(SS_WARNINGS_AS_ERRORS)
target_compile_options(${target} PRIVATE /WX)
endif()
else()
target_compile_options(${target} PRIVATE -Wall -Wno-deprecated-declarations -fno-strict-aliasing)
# C++ sources: no exceptions or RTTI, and no locks around function
# statics (the event loop is single-threaded). New C++ code also opts
# into -Wextra through ss_strict_warnings(); modules ported from C get
# it when they are rewritten.
target_compile_options(${target} PRIVATE
$<$<COMPILE_LANGUAGE:CXX>:-fno-exceptions -fno-rtti -fno-threadsafe-statics>)
# GCC's C++ -Wall adds -Wsign-compare and -Wclass-memaccess, which C's
# -Wall does not have. Modules converted from C keep the warning set
# they were written against; ss_strict_warnings() turns both back on.
target_compile_options(${target} PRIVATE
$<$<COMPILE_LANG_AND_ID:CXX,GNU>:-Wno-sign-compare -Wno-class-memaccess>)
if(SS_WARNINGS_AS_ERRORS)
target_compile_options(${target} PRIVATE -Werror)
endif()
if(HAS_STACK_PROTECTOR)
target_compile_options(${target} PRIVATE -fstack-protector-strong)
endif()
if(MINGW OR CYGWIN)
target_compile_options(${target} PRIVATE -mno-ms-bitfields)
endif()
endif()
if(LINUX)
target_compile_definitions(${target} PRIVATE _GNU_SOURCE)
endif()
if(ENABLE_SANITIZERS)
if(MSVC)
message(FATAL_ERROR "ASan + UBSan requires GCC or Clang")
endif()
target_compile_options(${target} PRIVATE -fsanitize=address,undefined -fno-sanitize-recover=all -fno-omit-frame-pointer)
target_link_options(${target} PRIVATE -fsanitize=address,undefined)
endif()
if(ENABLE_COVERAGE)
target_compile_options(${target} PRIVATE -O0 --coverage)
target_link_options(${target} PRIVATE --coverage)
endif()
endfunction()
# Extra warnings for source files written as C++ from the start (src/core,
# src/event, src/crypto and their tests). Per file, so targets that also
# compile converted C modules keep those at -Wall. Source properties are
# directory-scoped: call this from the directory that defines the targets.
function(ss_strict_warnings)
if(NOT MSVC)
set_source_files_properties(${ARGN} PROPERTIES COMPILE_OPTIONS
"-Wextra;$<$<CXX_COMPILER_ID:GNU>:-Wsign-compare>;$<$<CXX_COMPILER_ID:GNU>:-Wclass-memaccess>")
endif()
endfunction()