From b4c429058855c4866db0ba66d8a2be3a0ca2e937 Mon Sep 17 00:00:00 2001 From: Mounir IDRASSI Date: Tue, 13 Oct 2026 17:21:22 +0900 Subject: [PATCH] Tests: check declared buffer alignment at compile time Check wrapper type alignment in both test suites so incidental alignment can't hide an empty CRYPTOPP_ALIGN_DATA, including in ASan builds. Clarify that the compiler may fold the existing address checks. --- src/Common/Tests.c | 20 ++++++++++++++++---- src/Volume/EncryptionTest.cpp | 21 ++++++++++++++++----- 2 files changed, 32 insertions(+), 9 deletions(-) diff --git a/src/Common/Tests.c b/src/Common/Tests.c index eaf13f8e..fd0a1005 100644 --- a/src/Common/Tests.c +++ b/src/Common/Tests.c @@ -1282,12 +1282,24 @@ BOOL TestSectorBufEncryption (PCRYPTO_INFO ci) } #ifndef TC_WINDOWS_DRIVER -// Must stay smaller than the alignment under test: the ABI aligns larger objects by itself. #define TC_ALIGNMENT_PROBE_SIZE 4 -/* Verifies that CRYPTOPP_ALIGN_DATA actually delivers the alignment it requests. It expands - to nothing for compilers that are neither MSVC nor GCC/Clang (see Crypto/config.h), and the - SIMD backends issue aligned loads against buffers declared with it. */ +/* Check type alignment at compile time: static probes can be aligned even with an + empty CRYPTOPP_ALIGN_DATA, for example in AddressSanitizer builds. */ +typedef struct +{ + CRYPTOPP_ALIGN_DATA(TC_DERIVED_KEY_BUFFER_ALIGNMENT) unsigned char buffer[TC_ALIGNMENT_PROBE_SIZE]; +} DerivedKeyAlignmentProbe; + +typedef struct +{ + CRYPTOPP_ALIGN_DATA(TC_KEY_INFO_BUFFER_ALIGNMENT) unsigned char buffer[TC_ALIGNMENT_PROBE_SIZE]; +} KeyInfoAlignmentProbe; + +typedef char DerivedKeyAlignmentCheck[(__alignof (DerivedKeyAlignmentProbe) >= TC_DERIVED_KEY_BUFFER_ALIGNMENT) ? 1 : -1]; +typedef char KeyInfoAlignmentCheck[(__alignof (KeyInfoAlignmentProbe) >= TC_KEY_INFO_BUFFER_ALIGNMENT) ? 1 : -1]; + +/* The compiler may fold the address checks using the declared alignment. */ static BOOL TestBufferAlignment (void) { static CRYPTOPP_ALIGN_DATA(TC_DERIVED_KEY_BUFFER_ALIGNMENT) unsigned char derivedKeyProbe[TC_ALIGNMENT_PROBE_SIZE]; diff --git a/src/Volume/EncryptionTest.cpp b/src/Volume/EncryptionTest.cpp index 2188420d..30f98a78 100644 --- a/src/Volume/EncryptionTest.cpp +++ b/src/Volume/EncryptionTest.cpp @@ -75,15 +75,26 @@ namespace VeraCrypt TestAll (true); } - // Must stay smaller than the alignment under test: the ABI aligns larger objects by itself. #define TC_ALIGNMENT_PROBE_SIZE 4 - // Verifies that CRYPTOPP_ALIGN_DATA actually delivers the alignment it requests. - // It expands to nothing for compilers that are neither MSVC nor GCC/Clang (see - // Crypto/config.h), and the SIMD backends issue aligned loads against buffers - // declared with it, so a silent expansion to nothing would fault at run time. + // The compiler may fold the address checks using the declared alignment. void EncryptionTest::TestAlignment () { + // Check type alignment at compile time: static probes can be aligned even with an + // empty CRYPTOPP_ALIGN_DATA, for example in AddressSanitizer builds. + struct DerivedKeyAlignmentProbe + { + CRYPTOPP_ALIGN_DATA(TC_DERIVED_KEY_BUFFER_ALIGNMENT) uint8 buffer[TC_ALIGNMENT_PROBE_SIZE]; + }; + + struct KeyInfoAlignmentProbe + { + CRYPTOPP_ALIGN_DATA(TC_KEY_INFO_BUFFER_ALIGNMENT) uint8 buffer[TC_ALIGNMENT_PROBE_SIZE]; + }; + + static_assert (alignof (DerivedKeyAlignmentProbe) >= TC_DERIVED_KEY_BUFFER_ALIGNMENT, "Insufficient derived key buffer alignment"); + static_assert (alignof (KeyInfoAlignmentProbe) >= TC_KEY_INFO_BUFFER_ALIGNMENT, "Insufficient key info buffer alignment"); + static CRYPTOPP_ALIGN_DATA(TC_DERIVED_KEY_BUFFER_ALIGNMENT) uint8 derivedKeyProbe[TC_ALIGNMENT_PROBE_SIZE]; static CRYPTOPP_ALIGN_DATA(TC_KEY_INFO_BUFFER_ALIGNMENT) uint8 keyInfoProbe[TC_ALIGNMENT_PROBE_SIZE];