From 2de108dfa343c3e06eb98beb122cd06306bb12fd Mon Sep 17 00:00:00 2001 From: David Benjamin Date: Sun, 20 May 2018 17:24:30 -0400 Subject: Save and restore the Windows error around TlsGetValue. TlsGetValue clears the last error even on success, so that callers may distinguish it successfully returning NULL or failing. This error-mangling behavior interferes with the caller's use of GetLastError. In particular SSL_get_error queries the error queue to determine whether the caller should look at the OS's errors. To avoid destroying state, save and restore the Windows error. Fixes #6299. Reviewed-by: Rich Salz (Merged from https://github.com/openssl/openssl/pull/6316) --- crypto/threads_win.c | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) (limited to 'crypto/threads_win.c') diff --git a/crypto/threads_win.c b/crypto/threads_win.c index 1e5cf82073..7fdbc1f67f 100644 --- a/crypto/threads_win.c +++ b/crypto/threads_win.c @@ -101,7 +101,26 @@ int CRYPTO_THREAD_init_local(CRYPTO_THREAD_LOCAL *key, void (*cleanup)(void *)) void *CRYPTO_THREAD_get_local(CRYPTO_THREAD_LOCAL *key) { - return TlsGetValue(*key); + DWORD last_error; + void *ret; + + /* + * TlsGetValue clears the last error even on success, so that callers may + * distinguish it successfully returning NULL or failing. It is documented + * to never fail if the argument is a valid index from TlsAlloc, so we do + * not need to handle this. + * + * However, this error-mangling behavior interferes with the caller's use of + * GetLastError. In particular SSL_get_error queries the error queue to + * determine whether the caller should look at the OS's errors. To avoid + * destroying state, save and restore the Windows error. + * + * https://msdn.microsoft.com/en-us/library/windows/desktop/ms686812(v=vs.85).aspx + */ + last_error = GetLastError(); + ret = TlsGetValue(*key); + SetLastError(last_error); + return ret; } int CRYPTO_THREAD_set_local(CRYPTO_THREAD_LOCAL *key, void *val) -- cgit v1.2.3