From 9333d6df114dd0aa05802ec9c6c8c8e5075d39cd Mon Sep 17 00:00:00 2001 From: Brian Smith Date: Tue, 26 Jan 2016 14:32:46 -1000 Subject: [PATCH] Fix data <-> function pointer casts in thread_win.c. The uses of |memcpy| to cast pointer-to-function to pointer-to-data and back again did not have well-defined semantics. Use a union instead to avoid the need for such a conversion get well-defined semantics. Change-Id: I8ee54a83ba75440f7bc78c194eb55e2cf09b05d8 Reviewed-on: https://boringssl-review.googlesource.com/6972 Reviewed-by: David Benjamin --- crypto/thread_win.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/crypto/thread_win.c b/crypto/thread_win.c index e1b3a54d..e48ab5f5 100644 --- a/crypto/thread_win.c +++ b/crypto/thread_win.c @@ -31,7 +31,13 @@ OPENSSL_COMPILE_ASSERT(sizeof(CRYPTO_MUTEX) >= sizeof(CRITICAL_SECTION), CRYPTO_MUTEX_too_small); -static void run_once(CRYPTO_once_t *once, void (*init)(void *), void *arg) { +union run_once_arg_t { + void (*func)(void); + void *data; +}; + +static void run_once(CRYPTO_once_t *once, void (*init)(union run_once_arg_t), + union run_once_arg_t arg) { /* Values must be aligned. */ assert((((uintptr_t) once) & 3) == 0); @@ -72,17 +78,13 @@ static void run_once(CRYPTO_once_t *once, void (*init)(void *), void *arg) { } } -static void call_once_init(void *arg) { - void (*init_func)(void); - /* MSVC does not like casting between data and function pointers. */ - memcpy(&init_func, &arg, sizeof(void *)); - init_func(); +static void call_once_init(union run_once_arg_t arg) { + arg.func(); } void CRYPTO_once(CRYPTO_once_t *in_once, void (*init)(void)) { - void *arg; - /* MSVC does not like casting between data and function pointers. */ - memcpy(&arg, &init, sizeof(void *)); + union run_once_arg_t arg; + arg.func = init; run_once(in_once, call_once_init, arg); } @@ -109,16 +111,18 @@ void CRYPTO_MUTEX_cleanup(CRYPTO_MUTEX *lock) { DeleteCriticalSection((CRITICAL_SECTION *) lock); } -static void static_lock_init(void *arg) { - struct CRYPTO_STATIC_MUTEX *lock = arg; +static void static_lock_init(union run_once_arg_t arg) { + struct CRYPTO_STATIC_MUTEX *lock = arg.data; if (!InitializeCriticalSectionAndSpinCount(&lock->lock, 0x400)) { abort(); } } void CRYPTO_STATIC_MUTEX_lock_read(struct CRYPTO_STATIC_MUTEX *lock) { + union run_once_arg_t arg; + arg.data = lock; /* Since we have to support Windows XP, read locks are actually exclusive. */ - run_once(&lock->once, static_lock_init, lock); + run_once(&lock->once, static_lock_init, arg); EnterCriticalSection(&lock->lock); }