summaryrefslogtreecommitdiffstats
path: root/crypto/threads_win.c
diff options
context:
space:
mode:
authorDavid Benjamin <davidben@google.com>2018-05-20 17:24:30 -0400
committerDavid Benjamin <davidben@google.com>2018-05-23 17:34:54 -0400
commit2de108dfa343c3e06eb98beb122cd06306bb12fd (patch)
tree3e49b8444a3c29a076eac36a126b77d7891d2f5b /crypto/threads_win.c
parente363534cfe0ae01503dde6963e0631ec5f7fef3f (diff)
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 <rsalz@openssl.org> (Merged from https://github.com/openssl/openssl/pull/6316)
Diffstat (limited to 'crypto/threads_win.c')
-rw-r--r--crypto/threads_win.c21
1 files changed, 20 insertions, 1 deletions
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)