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;