Commit faa5318c65 for openssl.org
commit faa5318c654d8444312aa0703cbdd7518550a053
Author: Tomas Mraz <tomas@openssl.org>
Date: Wed Feb 25 18:15:47 2026 +0100
ossl_err_get_state_int(): Avoid saving the last sys error if not needed
In calls like ERR_set_mark(), ERR_clear_last_mark() and
others, there is no point in saving the last sys error.
It can be potentially expensive (on Windows).
Reviewed-by: Simo Sorce <simo@redhat.com>
Reviewed-by: Paul Dale <paul.dale@oracle.com>
Reviewed-by: Neil Horman <nhorman@openssl.org>
MergeDate: Thu Apr 16 18:12:49 2026
(Merged from https://github.com/openssl/openssl/pull/30179)
diff --git a/crypto/err/err.c b/crypto/err/err.c
index b3e15196f6..bf637e1d45 100644
--- a/crypto/err/err.c
+++ b/crypto/err/err.c
@@ -25,9 +25,6 @@
#include "internal/e_os.h"
#include "err_local.h"
-/* Forward declaration in case it's not published because of configuration */
-ERR_STATE *ERR_get_state(void);
-
#ifndef OPENSSL_NO_ERR
static int err_load_strings(const ERR_STRING_DATA *str);
#endif
@@ -331,7 +328,7 @@ void ERR_clear_error(void)
int i;
ERR_STATE *es;
- es = ossl_err_get_state_int();
+ es = ossl_err_get_state_int(0);
if (es == NULL)
return;
@@ -445,7 +442,7 @@ static unsigned long get_error_values(ERR_GET_ACTION g,
ERR_STATE *es;
unsigned long ret;
- es = ossl_err_get_state_int();
+ es = ossl_err_get_state_int(1);
if (es == NULL)
return 0;
@@ -648,10 +645,13 @@ static void err_delete_thread_state(void *unused)
OSSL_ERR_STATE_free(state);
}
-ERR_STATE *ossl_err_get_state_int(void)
+ERR_STATE *ossl_err_get_state_int(int save_sys_error)
{
ERR_STATE *state;
- int saveerrno = get_last_sys_error();
+ int saveerrno = 0;
+
+ if (save_sys_error)
+ saveerrno = get_last_sys_error();
if (!OPENSSL_init_crypto(OPENSSL_INIT_BASE_ONLY, NULL))
return NULL;
@@ -686,7 +686,8 @@ ERR_STATE *ossl_err_get_state_int(void)
OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL);
}
- set_sys_error(saveerrno);
+ if (save_sys_error)
+ set_sys_error(saveerrno);
return state;
}
@@ -753,7 +754,7 @@ static int err_set_error_data_int(char *data, size_t size, int flags,
{
ERR_STATE *es;
- es = ossl_err_get_state_int();
+ es = ossl_err_get_state_int(1);
if (es == NULL)
return 0;
@@ -799,7 +800,7 @@ void ERR_add_error_vdata(int num, va_list args)
ERR_STATE *es;
/* Get the current error data; if an allocated string get it. */
- es = ossl_err_get_state_int();
+ es = ossl_err_get_state_int(1);
if (es == NULL)
return;
i = es->top;
@@ -856,7 +857,7 @@ void err_clear_last_constant_time(int clear)
ERR_STATE *es;
int top;
- es = ossl_err_get_state_int();
+ es = ossl_err_get_state_int(0);
if (es == NULL)
return;
diff --git a/crypto/err/err_blocks.c b/crypto/err/err_blocks.c
index cc0fce0419..90451ea880 100644
--- a/crypto/err/err_blocks.c
+++ b/crypto/err/err_blocks.c
@@ -15,7 +15,7 @@ void ERR_new(void)
{
ERR_STATE *es;
- es = ossl_err_get_state_int();
+ es = ossl_err_get_state_int(1);
if (es == NULL)
return;
@@ -28,7 +28,7 @@ void ERR_set_debug(const char *file, int line, const char *func)
{
ERR_STATE *es;
- es = ossl_err_get_state_int();
+ es = ossl_err_get_state_int(1);
if (es == NULL)
return;
@@ -52,7 +52,7 @@ void ERR_vset_error(int lib, int reason, const char *fmt, va_list args)
unsigned long flags = 0;
size_t i;
- es = ossl_err_get_state_int();
+ es = ossl_err_get_state_int(1);
if (es == NULL)
return;
i = es->top;
diff --git a/crypto/err/err_local.h b/crypto/err/err_local.h
index 775d8e6bdf..4ddf7f7664 100644
--- a/crypto/err/err_local.h
+++ b/crypto/err/err_local.h
@@ -112,6 +112,6 @@ static ossl_inline void err_clear(ERR_STATE *es, size_t i, int deall)
es->err_func[i] = NULL;
}
-ERR_STATE *ossl_err_get_state_int(void);
+ERR_STATE *ossl_err_get_state_int(int save_sys_error);
void ossl_err_string_int(unsigned long e, const char *func,
char *buf, size_t len);
diff --git a/crypto/err/err_mark.c b/crypto/err/err_mark.c
index 2ebe86b9de..29aef24a12 100644
--- a/crypto/err/err_mark.c
+++ b/crypto/err/err_mark.c
@@ -14,7 +14,7 @@ int ERR_set_mark(void)
{
ERR_STATE *es;
- es = ossl_err_get_state_int();
+ es = ossl_err_get_state_int(0);
if (es == NULL)
return 0;
@@ -28,7 +28,7 @@ int ERR_pop(void)
{
ERR_STATE *es;
- es = ossl_err_get_state_int();
+ es = ossl_err_get_state_int(0);
if (es == NULL || es->bottom == es->top)
return 0;
@@ -41,7 +41,7 @@ int ERR_pop_to_mark(void)
{
ERR_STATE *es;
- es = ossl_err_get_state_int();
+ es = ossl_err_get_state_int(0);
if (es == NULL)
return 0;
@@ -62,7 +62,7 @@ int ERR_count_to_mark(void)
ERR_STATE *es;
int count = 0, top;
- es = ossl_err_get_state_int();
+ es = ossl_err_get_state_int(1);
if (es == NULL)
return 0;
@@ -81,7 +81,7 @@ int ERR_clear_last_mark(void)
ERR_STATE *es;
int top;
- es = ossl_err_get_state_int();
+ es = ossl_err_get_state_int(0);
if (es == NULL)
return 0;
diff --git a/crypto/err/err_save.c b/crypto/err/err_save.c
index 37980c8845..62f5d752dc 100644
--- a/crypto/err/err_save.c
+++ b/crypto/err/err_save.c
@@ -32,7 +32,7 @@ void OSSL_ERR_STATE_save(ERR_STATE *es)
for (i = 0; i < ERR_NUM_ERRORS; i++)
err_clear(es, i, 1);
- thread_es = ossl_err_get_state_int();
+ thread_es = ossl_err_get_state_int(1);
if (thread_es == NULL)
return;
@@ -50,7 +50,7 @@ void OSSL_ERR_STATE_save_to_mark(ERR_STATE *es)
if (es == NULL)
return;
- thread_es = ossl_err_get_state_int();
+ thread_es = ossl_err_get_state_int(1);
if (thread_es == NULL) {
for (i = 0; i < ERR_NUM_ERRORS; ++i)
err_clear(es, i, 1);
@@ -116,7 +116,7 @@ void OSSL_ERR_STATE_restore(const ERR_STATE *es)
if (es == NULL || es->bottom == es->top)
return;
- thread_es = ossl_err_get_state_int();
+ thread_es = ossl_err_get_state_int(0);
if (thread_es == NULL)
return;