summaryrefslogtreecommitdiff
path: root/test/errtest.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 /test/errtest.c
parente363534cfe0ae01503dde6963e0631ec5f7fef3f (diff)
downloadopenssl-new-2de108dfa343c3e06eb98beb122cd06306bb12fd.tar.gz
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 'test/errtest.c')
-rw-r--r--test/errtest.c39
1 files changed, 39 insertions, 0 deletions
diff --git a/test/errtest.c b/test/errtest.c
new file mode 100644
index 0000000000..e464d08bc0
--- /dev/null
+++ b/test/errtest.c
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2018 The OpenSSL Project Authors. All Rights Reserved.
+ *
+ * Licensed under the OpenSSL license (the "License"). You may not use
+ * this file except in compliance with the License. You can obtain a copy
+ * in the file LICENSE in the source distribution or at
+ * https://www.openssl.org/source/license.html
+ */
+
+#include <openssl/opensslconf.h>
+#include <openssl/err.h>
+
+#include "testutil.h"
+
+#if defined(OPENSSL_SYS_WINDOWS)
+# include <windows.h>
+#else
+# include <errno.h>
+#endif
+
+/* Test that querying the error queue preserves the OS error. */
+static int preserves_system_error(void)
+{
+#if defined(OPENSSL_SYS_WINDOWS)
+ SetLastError(ERROR_INVALID_FUNCTION);
+ ERR_get_error();
+ return TEST_int_eq(GetLastError(), ERROR_INVALID_FUNCTION);
+#else
+ errno = EINVAL;
+ ERR_get_error();
+ return TEST_int_eq(errno, EINVAL);
+#endif
+}
+
+int setup_tests(void)
+{
+ ADD_TEST(preserves_system_error);
+ return 1;
+}