-/* $OpenBSD: err.c,v 1.64 2024/10/02 14:54:26 jsing Exp $ */
+/* $OpenBSD: err.c,v 1.65 2024/10/02 15:21:39 jsing Exp $ */
/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
int top, bottom;
} ERR_STATE;
-static void err_load_strings(int lib, ERR_STRING_DATA *str);
-
-static ERR_STATE *ERR_get_state(void);
-static void ERR_STATE_free(ERR_STATE *s);
-
#ifndef OPENSSL_NO_ERR
static ERR_STRING_DATA ERR_str_libraries[] = {
{ERR_PACK(ERR_LIB_NONE,0,0), "unknown library"},
};
#endif
+static void ERR_STATE_free(ERR_STATE *s);
+
/*
* The internal state used by "err_defaults" - as such, the setting, reading,
* creating, and deleting of this data should only be permitted via the
* internal to the "err_defaults" implementation.
*/
-static unsigned long get_error_values(int inc, int top, const char **file,
- int *line, const char **data, int *flags);
-
/* The internal functions used in the "err_defaults" implementation */
static unsigned long
free(s);
}
+static ERR_STATE *
+ERR_get_state(void)
+{
+ static ERR_STATE fallback;
+ ERR_STATE *ret, tmp, *tmpp = NULL;
+ int i;
+ CRYPTO_THREADID tid;
+
+ CRYPTO_THREADID_current(&tid);
+ CRYPTO_THREADID_cpy(&tmp.tid, &tid);
+ ret = err_thread_get_item(&tmp);
+
+ /* ret == the error state, if NULL, make a new one */
+ if (ret == NULL) {
+ ret = malloc(sizeof(ERR_STATE));
+ if (ret == NULL)
+ return (&fallback);
+ CRYPTO_THREADID_cpy(&ret->tid, &tid);
+ ret->top = 0;
+ ret->bottom = 0;
+ for (i = 0; i < ERR_NUM_ERRORS; i++) {
+ ret->err_data[i] = NULL;
+ ret->err_data_flags[i] = 0;
+ }
+ tmpp = err_thread_set_item(ret);
+ /* To check if insertion failed, do a get. */
+ if (err_thread_get_item(ret) != ret) {
+ ERR_STATE_free(ret); /* could not insert it */
+ return (&fallback);
+ }
+ /* If a race occurred in this function and we came second, tmpp
+ * is the first one that we just replaced. */
+ if (tmpp)
+ ERR_STATE_free(tmpp);
+ }
+ return ret;
+}
+
+static void
+err_load_strings(int lib, ERR_STRING_DATA *str)
+{
+ while (str->error) {
+ if (lib)
+ str->error |= ERR_PACK(lib, 0, 0);
+ err_set_item(str);
+ str++;
+ }
+}
+
+static unsigned long
+get_error_values(int inc, int top, const char **file, int *line,
+ const char **data, int *flags)
+{
+ int i = 0;
+ ERR_STATE *es;
+ unsigned long ret;
+
+ es = ERR_get_state();
+
+ if (inc && top) {
+ if (file)
+ *file = "";
+ if (line)
+ *line = 0;
+ if (data)
+ *data = "";
+ if (flags)
+ *flags = 0;
+
+ return ERR_R_INTERNAL_ERROR;
+ }
+
+ if (es->bottom == es->top)
+ return 0;
+ if (top)
+ i = es->top; /* last error */
+ else
+ i = (es->bottom + 1) % ERR_NUM_ERRORS; /* first error */
+
+ ret = es->err_buffer[i];
+ if (inc) {
+ es->bottom = i;
+ es->err_buffer[i] = 0;
+ }
+
+ if ((file != NULL) && (line != NULL)) {
+ if (es->err_file[i] == NULL) {
+ *file = "NA";
+ if (line != NULL)
+ *line = 0;
+ } else {
+ *file = es->err_file[i];
+ if (line != NULL)
+ *line = es->err_line[i];
+ }
+ }
+
+ if (data == NULL) {
+ if (inc) {
+ err_clear_data(es, i);
+ }
+ } else {
+ if (es->err_data[i] == NULL) {
+ *data = "";
+ if (flags != NULL)
+ *flags = 0;
+ } else {
+ *data = es->err_data[i];
+ if (flags != NULL)
+ *flags = es->err_data_flags[i];
+ }
+ }
+ return ret;
+}
+
void
ERR_load_ERR_strings_internal(void)
{
#endif
}
-
void
ERR_load_ERR_strings(void)
{
}
LCRYPTO_ALIAS(ERR_load_ERR_strings);
-static void
-err_load_strings(int lib, ERR_STRING_DATA *str)
-{
- while (str->error) {
- if (lib)
- str->error |= ERR_PACK(lib, 0, 0);
- err_set_item(str);
- str++;
- }
-}
-
void
ERR_load_strings(int lib, ERR_STRING_DATA *str)
{
}
LCRYPTO_ALIAS(ERR_free_strings);
-/********************************************************/
+int
+ERR_get_next_error_library(void)
+{
+ return err_get_next_lib();
+}
+LCRYPTO_ALIAS(ERR_get_next_error_library);
void
-ERR_put_error(int lib, int func, int reason, const char *file, int line)
+ERR_remove_thread_state(const CRYPTO_THREADID *id)
+{
+ ERR_STATE tmp;
+
+ if (id)
+ CRYPTO_THREADID_cpy(&tmp.tid, id);
+ else
+ CRYPTO_THREADID_current(&tmp.tid);
+ /* err_thread_del_item automatically destroys the LHASH if the number of
+ * items reaches zero. */
+ err_thread_del_item(&tmp);
+}
+LCRYPTO_ALIAS(ERR_remove_thread_state);
+
+void
+ERR_remove_state(unsigned long pid)
+{
+ ERR_remove_thread_state(NULL);
+}
+LCRYPTO_ALIAS(ERR_remove_state);
+
+int
+ERR_set_mark(void)
{
ERR_STATE *es;
- int save_errno = errno;
es = ERR_get_state();
- es->top = (es->top + 1) % ERR_NUM_ERRORS;
- if (es->top == es->bottom)
- es->bottom = (es->bottom + 1) % ERR_NUM_ERRORS;
- es->err_flags[es->top] = 0;
- es->err_buffer[es->top] = ERR_PACK(lib, func, reason);
- es->err_file[es->top] = file;
- es->err_line[es->top] = line;
- err_clear_data(es, es->top);
- errno = save_errno;
+ if (es->bottom == es->top)
+ return 0;
+ es->err_flags[es->top] |= ERR_FLAG_MARK;
+ return 1;
}
-LCRYPTO_ALIAS(ERR_put_error);
+LCRYPTO_ALIAS(ERR_set_mark);
+
+int
+ERR_pop_to_mark(void)
+{
+ ERR_STATE *es;
+
+ es = ERR_get_state();
+
+ while (es->bottom != es->top &&
+ (es->err_flags[es->top] & ERR_FLAG_MARK) == 0) {
+ err_clear(es, es->top);
+ es->top -= 1;
+ if (es->top == -1)
+ es->top = ERR_NUM_ERRORS - 1;
+ }
+
+ if (es->bottom == es->top)
+ return 0;
+ es->err_flags[es->top]&=~ERR_FLAG_MARK;
+ return 1;
+}
+LCRYPTO_ALIAS(ERR_pop_to_mark);
void
ERR_clear_error(void)
}
LCRYPTO_ALIAS(ERR_clear_error);
-
-unsigned long
-ERR_get_error(void)
+void
+err_clear_last_constant_time(int clear)
{
- return (get_error_values(1, 0, NULL, NULL, NULL, NULL));
-}
-LCRYPTO_ALIAS(ERR_get_error);
+ ERR_STATE *es;
+ int top;
-unsigned long
-ERR_get_error_line(const char **file, int *line)
-{
- return (get_error_values(1, 0, file, line, NULL, NULL));
-}
-LCRYPTO_ALIAS(ERR_get_error_line);
+ es = ERR_get_state();
+ if (es == NULL)
+ return;
-unsigned long
-ERR_get_error_line_data(const char **file, int *line,
- const char **data, int *flags)
-{
- return (get_error_values(1, 0, file, line, data, flags));
-}
-LCRYPTO_ALIAS(ERR_get_error_line_data);
+ top = es->top;
+ es->err_flags[top] &= ~(0 - clear);
+ es->err_buffer[top] &= ~(0UL - clear);
+ es->err_file[top] = (const char *)((uintptr_t)es->err_file[top] &
+ ~((uintptr_t)0 - clear));
+ es->err_line[top] |= 0 - clear;
-unsigned long
-ERR_peek_error(void)
-{
- return (get_error_values(0, 0, NULL, NULL, NULL, NULL));
+ es->top = (top + ERR_NUM_ERRORS - clear) % ERR_NUM_ERRORS;
}
-LCRYPTO_ALIAS(ERR_peek_error);
-unsigned long
-ERR_peek_error_line(const char **file, int *line)
+void
+ERR_put_error(int lib, int func, int reason, const char *file, int line)
{
- return (get_error_values(0, 0, file, line, NULL, NULL));
-}
-LCRYPTO_ALIAS(ERR_peek_error_line);
+ ERR_STATE *es;
+ int save_errno = errno;
-unsigned long
-ERR_peek_error_line_data(const char **file, int *line,
- const char **data, int *flags)
-{
- return (get_error_values(0, 0, file, line, data, flags));
-}
-LCRYPTO_ALIAS(ERR_peek_error_line_data);
+ es = ERR_get_state();
+
+ es->top = (es->top + 1) % ERR_NUM_ERRORS;
+ if (es->top == es->bottom)
+ es->bottom = (es->bottom + 1) % ERR_NUM_ERRORS;
+ es->err_flags[es->top] = 0;
+ es->err_buffer[es->top] = ERR_PACK(lib, func, reason);
+ es->err_file[es->top] = file;
+ es->err_line[es->top] = line;
+ err_clear_data(es, es->top);
+ errno = save_errno;
+}
+LCRYPTO_ALIAS(ERR_put_error);
+
+void
+ERR_asprintf_error_data(char * format, ...)
+{
+ char *errbuf = NULL;
+ va_list ap;
+ int r;
+
+ va_start(ap, format);
+ r = vasprintf(&errbuf, format, ap);
+ va_end(ap);
+ if (r == -1)
+ ERR_set_error_data("malloc failed", ERR_TXT_STRING);
+ else
+ ERR_set_error_data(errbuf, ERR_TXT_MALLOCED|ERR_TXT_STRING);
+}
+LCRYPTO_ALIAS(ERR_asprintf_error_data);
+
+void
+ERR_set_error_data(char *data, int flags)
+{
+ ERR_STATE *es;
+ int i;
+
+ es = ERR_get_state();
+
+ i = es->top;
+ if (i == 0)
+ i = ERR_NUM_ERRORS - 1;
+
+ err_clear_data(es, i);
+ es->err_data[i] = data;
+ es->err_data_flags[i] = flags;
+}
+LCRYPTO_ALIAS(ERR_set_error_data);
+
+unsigned long
+ERR_get_error(void)
+{
+ return (get_error_values(1, 0, NULL, NULL, NULL, NULL));
+}
+LCRYPTO_ALIAS(ERR_get_error);
+
+unsigned long
+ERR_get_error_line(const char **file, int *line)
+{
+ return (get_error_values(1, 0, file, line, NULL, NULL));
+}
+LCRYPTO_ALIAS(ERR_get_error_line);
+
+unsigned long
+ERR_get_error_line_data(const char **file, int *line,
+ const char **data, int *flags)
+{
+ return (get_error_values(1, 0, file, line, data, flags));
+}
+LCRYPTO_ALIAS(ERR_get_error_line_data);
+
+unsigned long
+ERR_peek_error(void)
+{
+ return (get_error_values(0, 0, NULL, NULL, NULL, NULL));
+}
+LCRYPTO_ALIAS(ERR_peek_error);
+
+unsigned long
+ERR_peek_error_line(const char **file, int *line)
+{
+ return (get_error_values(0, 0, file, line, NULL, NULL));
+}
+LCRYPTO_ALIAS(ERR_peek_error_line);
+
+unsigned long
+ERR_peek_error_line_data(const char **file, int *line,
+ const char **data, int *flags)
+{
+ return (get_error_values(0, 0, file, line, data, flags));
+}
+LCRYPTO_ALIAS(ERR_peek_error_line_data);
unsigned long
ERR_peek_last_error(void)
}
LCRYPTO_ALIAS(ERR_peek_last_error_line_data);
-static unsigned long
-get_error_values(int inc, int top, const char **file, int *line,
- const char **data, int *flags)
+const char *
+ERR_lib_error_string(unsigned long e)
{
- int i = 0;
- ERR_STATE *es;
- unsigned long ret;
-
- es = ERR_get_state();
+ const ERR_STRING_DATA *p;
+ ERR_STRING_DATA d;
+ unsigned long l;
- if (inc && top) {
- if (file)
- *file = "";
- if (line)
- *line = 0;
- if (data)
- *data = "";
- if (flags)
- *flags = 0;
+ if (!OPENSSL_init_crypto(0, NULL))
+ return NULL;
- return ERR_R_INTERNAL_ERROR;
- }
+ l = ERR_GET_LIB(e);
+ d.error = ERR_PACK(l, 0, 0);
+ p = err_get_item(&d);
+ return ((p == NULL) ? NULL : p->string);
+}
+LCRYPTO_ALIAS(ERR_lib_error_string);
- if (es->bottom == es->top)
- return 0;
- if (top)
- i = es->top; /* last error */
- else
- i = (es->bottom + 1) % ERR_NUM_ERRORS; /* first error */
+const char *
+ERR_func_error_string(unsigned long e)
+{
+ const ERR_STRING_DATA *p;
+ ERR_STRING_DATA d;
+ unsigned long l, f;
- ret = es->err_buffer[i];
- if (inc) {
- es->bottom = i;
- es->err_buffer[i] = 0;
- }
+ l = ERR_GET_LIB(e);
+ f = ERR_GET_FUNC(e);
+ d.error = ERR_PACK(l, f, 0);
+ p = err_get_item(&d);
+ return ((p == NULL) ? NULL : p->string);
+}
+LCRYPTO_ALIAS(ERR_func_error_string);
- if ((file != NULL) && (line != NULL)) {
- if (es->err_file[i] == NULL) {
- *file = "NA";
- if (line != NULL)
- *line = 0;
- } else {
- *file = es->err_file[i];
- if (line != NULL)
- *line = es->err_line[i];
- }
- }
+const char *
+ERR_reason_error_string(unsigned long e)
+{
+ const ERR_STRING_DATA *p = NULL;
+ ERR_STRING_DATA d;
+ unsigned long l, r;
- if (data == NULL) {
- if (inc) {
- err_clear_data(es, i);
- }
- } else {
- if (es->err_data[i] == NULL) {
- *data = "";
- if (flags != NULL)
- *flags = 0;
- } else {
- *data = es->err_data[i];
- if (flags != NULL)
- *flags = es->err_data_flags[i];
- }
+ l = ERR_GET_LIB(e);
+ r = ERR_GET_REASON(e);
+ d.error = ERR_PACK(l, 0, r);
+ p = err_get_item(&d);
+ if (!p) {
+ d.error = ERR_PACK(0, 0, r);
+ p = err_get_item(&d);
}
- return ret;
+ return ((p == NULL) ? NULL : p->string);
}
+LCRYPTO_ALIAS(ERR_reason_error_string);
void
ERR_error_string_n(unsigned long e, char *buf, size_t len)
return ret;
}
LCRYPTO_ALIAS(ERR_error_string);
-
-const char *
-ERR_lib_error_string(unsigned long e)
-{
- const ERR_STRING_DATA *p;
- ERR_STRING_DATA d;
- unsigned long l;
-
- if (!OPENSSL_init_crypto(0, NULL))
- return NULL;
-
- l = ERR_GET_LIB(e);
- d.error = ERR_PACK(l, 0, 0);
- p = err_get_item(&d);
- return ((p == NULL) ? NULL : p->string);
-}
-LCRYPTO_ALIAS(ERR_lib_error_string);
-
-const char *
-ERR_func_error_string(unsigned long e)
-{
- const ERR_STRING_DATA *p;
- ERR_STRING_DATA d;
- unsigned long l, f;
-
- l = ERR_GET_LIB(e);
- f = ERR_GET_FUNC(e);
- d.error = ERR_PACK(l, f, 0);
- p = err_get_item(&d);
- return ((p == NULL) ? NULL : p->string);
-}
-LCRYPTO_ALIAS(ERR_func_error_string);
-
-const char *
-ERR_reason_error_string(unsigned long e)
-{
- const ERR_STRING_DATA *p = NULL;
- ERR_STRING_DATA d;
- unsigned long l, r;
-
- l = ERR_GET_LIB(e);
- r = ERR_GET_REASON(e);
- d.error = ERR_PACK(l, 0, r);
- p = err_get_item(&d);
- if (!p) {
- d.error = ERR_PACK(0, 0, r);
- p = err_get_item(&d);
- }
- return ((p == NULL) ? NULL : p->string);
-}
-LCRYPTO_ALIAS(ERR_reason_error_string);
-
-void
-ERR_remove_thread_state(const CRYPTO_THREADID *id)
-{
- ERR_STATE tmp;
-
- if (id)
- CRYPTO_THREADID_cpy(&tmp.tid, id);
- else
- CRYPTO_THREADID_current(&tmp.tid);
- /* err_thread_del_item automatically destroys the LHASH if the number of
- * items reaches zero. */
- err_thread_del_item(&tmp);
-}
-LCRYPTO_ALIAS(ERR_remove_thread_state);
-
-void
-ERR_remove_state(unsigned long pid)
-{
- ERR_remove_thread_state(NULL);
-}
-LCRYPTO_ALIAS(ERR_remove_state);
-
-static ERR_STATE *
-ERR_get_state(void)
-{
- static ERR_STATE fallback;
- ERR_STATE *ret, tmp, *tmpp = NULL;
- int i;
- CRYPTO_THREADID tid;
-
- CRYPTO_THREADID_current(&tid);
- CRYPTO_THREADID_cpy(&tmp.tid, &tid);
- ret = err_thread_get_item(&tmp);
-
- /* ret == the error state, if NULL, make a new one */
- if (ret == NULL) {
- ret = malloc(sizeof(ERR_STATE));
- if (ret == NULL)
- return (&fallback);
- CRYPTO_THREADID_cpy(&ret->tid, &tid);
- ret->top = 0;
- ret->bottom = 0;
- for (i = 0; i < ERR_NUM_ERRORS; i++) {
- ret->err_data[i] = NULL;
- ret->err_data_flags[i] = 0;
- }
- tmpp = err_thread_set_item(ret);
- /* To check if insertion failed, do a get. */
- if (err_thread_get_item(ret) != ret) {
- ERR_STATE_free(ret); /* could not insert it */
- return (&fallback);
- }
- /* If a race occurred in this function and we came second, tmpp
- * is the first one that we just replaced. */
- if (tmpp)
- ERR_STATE_free(tmpp);
- }
- return ret;
-}
-
-int
-ERR_get_next_error_library(void)
-{
- return err_get_next_lib();
-}
-LCRYPTO_ALIAS(ERR_get_next_error_library);
-
-void
-ERR_set_error_data(char *data, int flags)
-{
- ERR_STATE *es;
- int i;
-
- es = ERR_get_state();
-
- i = es->top;
- if (i == 0)
- i = ERR_NUM_ERRORS - 1;
-
- err_clear_data(es, i);
- es->err_data[i] = data;
- es->err_data_flags[i] = flags;
-}
-LCRYPTO_ALIAS(ERR_set_error_data);
-
-void
-ERR_asprintf_error_data(char * format, ...)
-{
- char *errbuf = NULL;
- va_list ap;
- int r;
-
- va_start(ap, format);
- r = vasprintf(&errbuf, format, ap);
- va_end(ap);
- if (r == -1)
- ERR_set_error_data("malloc failed", ERR_TXT_STRING);
- else
- ERR_set_error_data(errbuf, ERR_TXT_MALLOCED|ERR_TXT_STRING);
-}
-LCRYPTO_ALIAS(ERR_asprintf_error_data);
-
-int
-ERR_set_mark(void)
-{
- ERR_STATE *es;
-
- es = ERR_get_state();
-
- if (es->bottom == es->top)
- return 0;
- es->err_flags[es->top] |= ERR_FLAG_MARK;
- return 1;
-}
-LCRYPTO_ALIAS(ERR_set_mark);
-
-int
-ERR_pop_to_mark(void)
-{
- ERR_STATE *es;
-
- es = ERR_get_state();
-
- while (es->bottom != es->top &&
- (es->err_flags[es->top] & ERR_FLAG_MARK) == 0) {
- err_clear(es, es->top);
- es->top -= 1;
- if (es->top == -1)
- es->top = ERR_NUM_ERRORS - 1;
- }
-
- if (es->bottom == es->top)
- return 0;
- es->err_flags[es->top]&=~ERR_FLAG_MARK;
- return 1;
-}
-LCRYPTO_ALIAS(ERR_pop_to_mark);
-
-void
-err_clear_last_constant_time(int clear)
-{
- ERR_STATE *es;
- int top;
-
- es = ERR_get_state();
- if (es == NULL)
- return;
-
- top = es->top;
-
- es->err_flags[top] &= ~(0 - clear);
- es->err_buffer[top] &= ~(0UL - clear);
- es->err_file[top] = (const char *)((uintptr_t)es->err_file[top] &
- ~((uintptr_t)0 - clear));
- es->err_line[top] |= 0 - clear;
-
- es->top = (top + ERR_NUM_ERRORS - clear) % ERR_NUM_ERRORS;
-}