]>
git.ipfire.org Git - thirdparty/openssl.git/blob - crypto/err/err_save.c
2 * Copyright 2023 The OpenSSL Project Authors. All Rights Reserved.
4 * Licensed under the Apache License 2.0 (the "License"). You may not use
5 * this file except in compliance with the License. You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
10 #define OSSL_FORCE_ERR_STATE
12 #include <openssl/err.h>
13 #include "err_local.h"
16 * Save and restore error state.
17 * We are using CRYPTO_zalloc(.., NULL, 0) instead of OPENSSL_malloc() in
18 * these functions to prevent mem alloc error loop.
21 ERR_STATE
*OSSL_ERR_STATE_new(void)
23 return CRYPTO_zalloc(sizeof(ERR_STATE
), NULL
, 0);
26 void OSSL_ERR_STATE_save(ERR_STATE
*es
)
34 for (i
= 0; i
< ERR_NUM_ERRORS
; i
++)
37 thread_es
= ossl_err_get_state_int();
38 if (thread_es
== NULL
)
41 memcpy(es
, thread_es
, sizeof(*es
));
42 /* Taking over the pointers, just clear the thread state. */
43 memset(thread_es
, 0, sizeof(*thread_es
));
46 void OSSL_ERR_STATE_save_to_mark(ERR_STATE
*es
)
55 thread_es
= ossl_err_get_state_int();
56 if (thread_es
== NULL
) {
57 for (i
= 0; i
< ERR_NUM_ERRORS
; ++i
)
60 es
->top
= es
->bottom
= 0;
64 /* Determine number of errors we are going to move. */
65 for (count
= 0, top
= thread_es
->top
;
66 thread_es
->bottom
!= top
67 && thread_es
->err_marks
[top
] == 0;
69 top
= top
> 0 ? top
- 1 : ERR_NUM_ERRORS
- 1;
71 /* Move the errors, preserving order. */
72 for (i
= 0, j
= top
; i
< count
; ++i
) {
73 j
= (j
+ 1) % ERR_NUM_ERRORS
;
77 /* Move the error entry to the given ERR_STATE. */
78 es
->err_flags
[i
] = thread_es
->err_flags
[j
];
80 es
->err_buffer
[i
] = thread_es
->err_buffer
[j
];
81 es
->err_data
[i
] = thread_es
->err_data
[j
];
82 es
->err_data_size
[i
] = thread_es
->err_data_size
[j
];
83 es
->err_data_flags
[i
] = thread_es
->err_data_flags
[j
];
84 es
->err_file
[i
] = thread_es
->err_file
[j
];
85 es
->err_line
[i
] = thread_es
->err_line
[j
];
86 es
->err_func
[i
] = thread_es
->err_func
[j
];
88 thread_es
->err_flags
[j
] = 0;
89 thread_es
->err_buffer
[j
] = 0;
90 thread_es
->err_data
[j
] = NULL
;
91 thread_es
->err_data_size
[j
] = 0;
92 thread_es
->err_data_flags
[j
] = 0;
93 thread_es
->err_file
[j
] = NULL
;
94 thread_es
->err_line
[j
] = 0;
95 thread_es
->err_func
[j
] = NULL
;
100 /* If we moved anything, es's stack always starts at [0]. */
102 es
->bottom
= ERR_NUM_ERRORS
- 1;
104 /* Didn't move anything - empty stack */
105 es
->top
= es
->bottom
= 0;
108 /* Erase extra space as a precaution. */
109 for (; i
< ERR_NUM_ERRORS
; ++i
)
113 void OSSL_ERR_STATE_restore(const ERR_STATE
*es
)
116 ERR_STATE
*thread_es
;
118 if (es
== NULL
|| es
->bottom
== es
->top
)
121 thread_es
= ossl_err_get_state_int();
122 if (thread_es
== NULL
)
125 for (i
= (size_t)es
->bottom
; i
!= (size_t)es
->top
;) {
128 i
= (i
+ 1) % ERR_NUM_ERRORS
;
129 if ((es
->err_flags
[i
] & ERR_FLAG_CLEAR
) != 0)
132 err_get_slot(thread_es
);
133 top
= thread_es
->top
;
134 err_clear(thread_es
, top
, 0);
136 thread_es
->err_flags
[top
] = es
->err_flags
[i
];
137 thread_es
->err_buffer
[top
] = es
->err_buffer
[i
];
139 err_set_debug(thread_es
, top
, es
->err_file
[i
], es
->err_line
[i
],
142 if (es
->err_data
[i
] != NULL
&& es
->err_data_size
[i
] != 0) {
144 size_t data_sz
= es
->err_data_size
[i
];
146 data
= CRYPTO_malloc(data_sz
, NULL
, 0);
148 memcpy(data
, es
->err_data
[i
], data_sz
);
149 err_set_data(thread_es
, top
, data
, data_sz
,
150 es
->err_data_flags
[i
] | ERR_TXT_MALLOCED
);
153 err_clear_data(thread_es
, top
, 0);