From e2deec82359fe01d377197d8825ca12162eae1f9 Mon Sep 17 00:00:00 2001 From: Timo Kreuzer Date: Tue, 22 Jul 2025 14:18:58 +0300 Subject: [PATCH] [UCRT] Fix __crt_fast_encode_pointer GCC was optimizing away the xor with __security_cookie when passing nullptr_t, because the return value was also nullptr_t, assuming it must be nullptr. --- sdk/lib/vcruntime/inc/internal_shared.h | 28 +++++++++++++++++++------ 1 file changed, 22 insertions(+), 6 deletions(-) diff --git a/sdk/lib/vcruntime/inc/internal_shared.h b/sdk/lib/vcruntime/inc/internal_shared.h index b3274a030d9..bca394b6c31 100644 --- a/sdk/lib/vcruntime/inc/internal_shared.h +++ b/sdk/lib/vcruntime/inc/internal_shared.h @@ -185,18 +185,34 @@ template __forceinline T __crt_fast_encode_pointer(T ptr) { - union { T Ptr; uintptr_t Uint; } u = { ptr }; - u.Uint ^= __security_cookie; - return u.Ptr; + return reinterpret_cast( + reinterpret_cast(ptr) ^ __security_cookie); +} + +// Workaround for nullptr encoding. +// Casting nullptr_t to uinttptr_t is not allowed in C++. Using a union compiles, +// but GCC will optimize it to a constant zero, which is not what we want. +class encoded_nullptr_t +{ + void* m_ptr; +public: + inline encoded_nullptr_t(void* P) : m_ptr(P) { }; + template operator T*() { return (T*)m_ptr; } +}; + +__forceinline +encoded_nullptr_t __crt_fast_encode_pointer(decltype(nullptr) ptr) +{ + void* encoded_null = __crt_fast_encode_pointer((void*)ptr); + return encoded_nullptr_t(encoded_null); } template __forceinline T __crt_fast_decode_pointer(T ptr) { - union { T Ptr; uintptr_t Uint; } u = { ptr }; - u.Uint ^= __security_cookie; - return u.Ptr; + return reinterpret_cast( + reinterpret_cast(ptr) ^ __security_cookie); } template