Coverage Report

Created: 2026-09-12 06:55

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/openssl41/crypto/err/err_save.c
Line
Count
Source
1
/*
2
 * Copyright 2023-2026 The OpenSSL Project Authors. All Rights Reserved.
3
 *
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
8
 */
9
10
#include <openssl/err.h>
11
#include "err_local.h"
12
13
/*
14
 * Save and restore error state.
15
 * We are using CRYPTO_zalloc(.., NULL, 0) instead of OPENSSL_malloc() in
16
 * these functions to prevent mem alloc error loop.
17
 */
18
19
ERR_STATE *OSSL_ERR_STATE_new(void)
20
105k
{
21
105k
    return CRYPTO_zalloc(sizeof(ERR_STATE), NULL, 0);
22
105k
}
23
24
void OSSL_ERR_STATE_save(ERR_STATE *es)
25
21.2k
{
26
21.2k
    int i;
27
21.2k
    ERR_STATE *thread_es;
28
29
21.2k
    if (es == NULL)
30
0
        return;
31
32
361k
    for (i = 0; i < ERR_NUM_ERRORS; i++)
33
340k
        err_clear(es, i, 1);
34
35
21.2k
    thread_es = ossl_err_get_state_int(1);
36
21.2k
    if (thread_es == NULL)
37
0
        return;
38
39
21.2k
    memcpy(es, thread_es, sizeof(*es));
40
    /* Taking over the pointers, just clear the thread state. */
41
21.2k
    memset(thread_es, 0, sizeof(*thread_es));
42
21.2k
}
43
44
void OSSL_ERR_STATE_save_to_mark(ERR_STATE *es)
45
9.35k
{
46
9.35k
    int i, j, count;
47
9.35k
    int top;
48
9.35k
    ERR_STATE *thread_es;
49
50
9.35k
    if (es == NULL)
51
0
        return;
52
53
9.35k
    thread_es = ossl_err_get_state_int(1);
54
9.35k
    if (thread_es == NULL) {
55
0
        for (i = 0; i < ERR_NUM_ERRORS; ++i)
56
0
            err_clear(es, i, 1);
57
58
0
        es->top = es->bottom = 0;
59
0
        return;
60
0
    }
61
62
    /* Determine number of errors we are going to move. */
63
9.35k
    for (count = 0, top = thread_es->top;
64
21.3k
        thread_es->bottom != top
65
11.9k
        && thread_es->err_marks[top] == 0;
66
11.9k
        ++count)
67
11.9k
        top = top > 0 ? top - 1 : ERR_NUM_ERRORS - 1;
68
69
    /* Move the errors, preserving order. */
70
21.3k
    for (i = 0, j = top; i < count; ++i) {
71
11.9k
        j = (j + 1) % ERR_NUM_ERRORS;
72
73
11.9k
        err_clear(es, i, 1);
74
75
        /* Move the error entry to the given ERR_STATE. */
76
11.9k
        es->err_flags[i] = thread_es->err_flags[j];
77
11.9k
        es->err_marks[i] = 0;
78
11.9k
        es->err_buffer[i] = thread_es->err_buffer[j];
79
11.9k
        es->err_data[i] = thread_es->err_data[j];
80
11.9k
        es->err_data_size[i] = thread_es->err_data_size[j];
81
11.9k
        es->err_data_flags[i] = thread_es->err_data_flags[j];
82
11.9k
        es->err_file[i] = thread_es->err_file[j];
83
11.9k
        es->err_line[i] = thread_es->err_line[j];
84
11.9k
        es->err_func[i] = thread_es->err_func[j];
85
86
11.9k
        thread_es->err_flags[j] = 0;
87
11.9k
        thread_es->err_buffer[j] = 0;
88
11.9k
        thread_es->err_data[j] = NULL;
89
11.9k
        thread_es->err_data_size[j] = 0;
90
11.9k
        thread_es->err_data_flags[j] = 0;
91
11.9k
        thread_es->err_file[j] = NULL;
92
11.9k
        thread_es->err_line[j] = 0;
93
11.9k
        thread_es->err_func[j] = NULL;
94
11.9k
    }
95
96
9.35k
    if (i > 0) {
97
9.35k
        thread_es->top = top;
98
        /* If we moved anything, es's stack always starts at [0]. */
99
9.35k
        es->top = i - 1;
100
9.35k
        es->bottom = ERR_NUM_ERRORS - 1;
101
9.35k
    } else {
102
        /* Didn't move anything - empty stack */
103
0
        es->top = es->bottom = 0;
104
0
    }
105
106
    /* Erase extra space as a precaution. */
107
146k
    for (; i < ERR_NUM_ERRORS; ++i)
108
137k
        err_clear(es, i, 1);
109
9.35k
}
110
111
void OSSL_ERR_STATE_restore(const ERR_STATE *es)
112
36.4k
{
113
36.4k
    int i;
114
36.4k
    ERR_STATE *thread_es;
115
116
36.4k
    if (es == NULL || es->bottom == es->top)
117
13.8k
        return;
118
119
22.5k
    thread_es = ossl_err_get_state_int(0);
120
22.5k
    if (thread_es == NULL)
121
0
        return;
122
123
76.5k
    for (i = es->bottom; i != es->top;) {
124
54.0k
        int top;
125
126
54.0k
        i = (i + 1) % ERR_NUM_ERRORS;
127
54.0k
        if ((es->err_flags[i] & ERR_FLAG_CLEAR) != 0)
128
0
            continue;
129
130
54.0k
        err_get_slot(thread_es);
131
54.0k
        top = thread_es->top;
132
54.0k
        err_clear(thread_es, top, 0);
133
134
54.0k
        thread_es->err_flags[top] = es->err_flags[i];
135
54.0k
        thread_es->err_buffer[top] = es->err_buffer[i];
136
137
54.0k
        err_set_debug(thread_es, top, es->err_file[i], es->err_line[i],
138
54.0k
            es->err_func[i]);
139
140
54.0k
        if (es->err_data[i] != NULL && es->err_data_size[i] != 0) {
141
45.0k
            void *data;
142
45.0k
            size_t data_sz = es->err_data_size[i];
143
144
45.0k
            data = CRYPTO_malloc(data_sz, NULL, 0);
145
45.0k
            if (data != NULL) {
146
45.0k
                memcpy(data, es->err_data[i], data_sz);
147
45.0k
                err_set_data(thread_es, top, data, data_sz,
148
45.0k
                    es->err_data_flags[i] | ERR_TXT_MALLOCED);
149
45.0k
            }
150
45.0k
        } else {
151
8.97k
            err_clear_data(thread_es, top, 0);
152
8.97k
        }
153
54.0k
    }
154
22.5k
}