{ERR_PACK(ERR_LIB_TS, 0, 0), "time stamp routines"},
{ERR_PACK(ERR_LIB_ENGINE, 0, 0), "engine routines"},
{ERR_PACK(ERR_LIB_OCSP, 0, 0), "OCSP routines"},
+ {ERR_PACK(ERR_LIB_UI, 0, 0), "UI routines"},
{ERR_PACK(ERR_LIB_FIPS, 0, 0), "FIPS routines"},
{ERR_PACK(ERR_LIB_CMS, 0, 0), "CMS routines"},
{ERR_PACK(ERR_LIB_HMAC, 0, 0), "HMAC routines"},
{ERR_PACK(0, SYS_F_GETSOCKOPT, 0), "getsockopt"},
{ERR_PACK(0, SYS_F_GETSOCKNAME, 0), "getsockname"},
{ERR_PACK(0, SYS_F_GETHOSTBYNAME, 0), "gethostbyname"},
+ {ERR_PACK(0, SYS_F_FFLUSH, 0), "fflush"},
{0, NULL},
};
#endif
static CRYPTO_ONCE err_init = CRYPTO_ONCE_STATIC_INIT;
+static int set_err_thread_local;
static CRYPTO_THREAD_LOCAL err_thread_local;
static CRYPTO_ONCE err_string_init = CRYPTO_ONCE_STATIC_INIT;
DEFINE_RUN_ONCE_STATIC(do_err_strings_init)
{
- OPENSSL_init_crypto(0, NULL);
+ if (!OPENSSL_init_crypto(0, NULL))
+ return 0;
err_string_lock = CRYPTO_THREAD_lock_new();
return err_string_lock != NULL;
}
void err_cleanup(void)
{
+ if (set_err_thread_local != 0)
+ CRYPTO_THREAD_cleanup_local(&err_thread_local);
CRYPTO_THREAD_lock_free(err_string_lock);
err_string_lock = NULL;
}
}
#endif
es = ERR_get_state();
+ if (es == NULL)
+ return;
es->top = (es->top + 1) % ERR_NUM_ERRORS;
if (es->top == es->bottom)
ERR_STATE *es;
es = ERR_get_state();
+ if (es == NULL)
+ return;
for (i = 0; i < ERR_NUM_ERRORS; i++) {
err_clear(es, i);
unsigned long ret;
es = ERR_get_state();
+ if (es == NULL)
+ return 0;
if (inc && top) {
if (file)
void err_delete_thread_state(void)
{
- ERR_STATE *state = ERR_get_state();
+ ERR_STATE *state = CRYPTO_THREAD_get_local(&err_thread_local);
if (state == NULL)
return;
DEFINE_RUN_ONCE_STATIC(err_do_init)
{
+ set_err_thread_local = 1;
return CRYPTO_THREAD_init_local(&err_thread_local, NULL);
}
ERR_STATE *ERR_get_state(void)
{
- ERR_STATE *state = NULL;
+ ERR_STATE *state;
+
+ if (!OPENSSL_init_crypto(OPENSSL_INIT_BASE_ONLY, NULL))
+ return NULL;
if (!RUN_ONCE(&err_init, err_do_init))
return NULL;
state = CRYPTO_THREAD_get_local(&err_thread_local);
+ if (state == (ERR_STATE*)-1)
+ return NULL;
if (state == NULL) {
- state = OPENSSL_zalloc(sizeof(*state));
- if (state == NULL)
+ if (!CRYPTO_THREAD_set_local(&err_thread_local, (ERR_STATE*)-1))
return NULL;
- if (!CRYPTO_THREAD_set_local(&err_thread_local, state)) {
+ if ((state = OPENSSL_zalloc(sizeof(*state))) == NULL) {
+ CRYPTO_THREAD_set_local(&err_thread_local, NULL);
+ return NULL;
+ }
+
+ if (!ossl_init_thread_start(OPENSSL_INIT_THREAD_ERR_STATE)
+ || !CRYPTO_THREAD_set_local(&err_thread_local, state)) {
ERR_STATE_free(state);
+ CRYPTO_THREAD_set_local(&err_thread_local, NULL);
return NULL;
}
/* Ignore failures from these */
OPENSSL_init_crypto(OPENSSL_INIT_LOAD_CRYPTO_STRINGS, NULL);
- ossl_init_thread_start(OPENSSL_INIT_THREAD_ERR_STATE);
}
return state;
}
+/*
+ * err_shelve_state returns the current thread local error state
+ * and freezes the error module until err_unshelve_state is called.
+ */
+int err_shelve_state(void **state)
+{
+ if (!OPENSSL_init_crypto(OPENSSL_INIT_BASE_ONLY, NULL))
+ return 0;
+
+ if (!RUN_ONCE(&err_init, err_do_init))
+ return 0;
+
+ *state = CRYPTO_THREAD_get_local(&err_thread_local);
+ if (!CRYPTO_THREAD_set_local(&err_thread_local, (ERR_STATE*)-1))
+ return 0;
+
+ return 1;
+}
+
+/*
+ * err_unshelve_state restores the error state that was returned
+ * by err_shelve_state previously.
+ */
+void err_unshelve_state(void* state)
+{
+ if (state != (void*)-1)
+ CRYPTO_THREAD_set_local(&err_thread_local, (ERR_STATE*)state);
+}
+
int ERR_get_next_error_library(void)
{
int ret;
- if (!RUN_ONCE(&err_string_init, do_err_strings_init)) {
+ if (!RUN_ONCE(&err_string_init, do_err_strings_init))
return 0;
- }
CRYPTO_THREAD_write_lock(err_string_lock);
ret = int_err_library_number++;
int i;
es = ERR_get_state();
+ if (es == NULL)
+ return;
i = es->top;
- if (i == 0)
- i = ERR_NUM_ERRORS - 1;
err_clear_data(es, i);
es->err_data[i] = data;
ERR_STATE *es;
es = ERR_get_state();
+ if (es == NULL)
+ return 0;
if (es->bottom == es->top)
return 0;
ERR_STATE *es;
es = ERR_get_state();
+ if (es == NULL)
+ return 0;
while (es->bottom != es->top
&& (es->err_flags[es->top] & ERR_FLAG_MARK) == 0) {