Coverage Report

Created: 2025-06-13 06:58

/src/openssl32/crypto/err/err_save.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright 2023 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
#define OSSL_FORCE_ERR_STATE
11
12
#include <openssl/err.h>
13
#include "err_local.h"
14
15
/*
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.
19
 */
20
21
ERR_STATE *OSSL_ERR_STATE_new(void)
22
44.4k
{
23
44.4k
    return CRYPTO_zalloc(sizeof(ERR_STATE), NULL, 0);
24
44.4k
}
25
26
void OSSL_ERR_STATE_save(ERR_STATE *es)
27
11.3k
{
28
11.3k
    size_t i;
29
11.3k
    ERR_STATE *thread_es;
30
31
11.3k
    if (es == NULL)
32
0
        return;
33
34
192k
    for (i = 0; i < ERR_NUM_ERRORS; i++)
35
181k
        err_clear(es, i, 1);
36
37
11.3k
    thread_es = ossl_err_get_state_int();
38
11.3k
    if (thread_es == NULL)
39
0
        return;
40
41
11.3k
    memcpy(es, thread_es, sizeof(*es));
42
    /* Taking over the pointers, just clear the thread state. */
43
11.3k
    memset(thread_es, 0, sizeof(*thread_es));
44
11.3k
}
45
46
void OSSL_ERR_STATE_save_to_mark(ERR_STATE *es)
47
4.51k
{
48
4.51k
    size_t i, j, count;
49
4.51k
    int top;
50
4.51k
    ERR_STATE *thread_es;
51
52
4.51k
    if (es == NULL)
53
0
        return;
54
55
4.51k
    thread_es = ossl_err_get_state_int();
56
4.51k
    if (thread_es == NULL) {
57
0
        for (i = 0; i < ERR_NUM_ERRORS; ++i)
58
0
            err_clear(es, i, 1);
59
60
0
        es->top = es->bottom = 0;
61
0
        return;
62
0
    }
63
64
    /* Determine number of errors we are going to move. */
65
4.51k
    for (count = 0, top = thread_es->top;
66
10.8k
         thread_es->bottom != top
67
10.8k
         && thread_es->err_marks[top] == 0;
68
6.31k
         ++count)
69
6.31k
        top = top > 0 ? top - 1 : ERR_NUM_ERRORS - 1;
70
71
    /* Move the errors, preserving order. */
72
10.8k
    for (i = 0, j = top; i < count; ++i) {
73
6.31k
        j = (j + 1) % ERR_NUM_ERRORS;
74
75
6.31k
        err_clear(es, i, 1);
76
77
        /* Move the error entry to the given ERR_STATE. */
78
6.31k
        es->err_flags[i]        = thread_es->err_flags[j];
79
6.31k
        es->err_marks[i]        = 0;
80
6.31k
        es->err_buffer[i]       = thread_es->err_buffer[j];
81
6.31k
        es->err_data[i]         = thread_es->err_data[j];
82
6.31k
        es->err_data_size[i]    = thread_es->err_data_size[j];
83
6.31k
        es->err_data_flags[i]   = thread_es->err_data_flags[j];
84
6.31k
        es->err_file[i]         = thread_es->err_file[j];
85
6.31k
        es->err_line[i]         = thread_es->err_line[j];
86
6.31k
        es->err_func[i]         = thread_es->err_func[j];
87
88
6.31k
        thread_es->err_flags[j]      = 0;
89
6.31k
        thread_es->err_buffer[j]     = 0;
90
6.31k
        thread_es->err_data[j]       = NULL;
91
6.31k
        thread_es->err_data_size[j]  = 0;
92
6.31k
        thread_es->err_data_flags[j] = 0;
93
6.31k
        thread_es->err_file[j]       = NULL;
94
6.31k
        thread_es->err_line[j]       = 0;
95
6.31k
        thread_es->err_func[j]       = NULL;
96
6.31k
    }
97
98
4.51k
    if (i > 0) {
99
4.51k
        thread_es->top = top;
100
        /* If we moved anything, es's stack always starts at [0]. */
101
4.51k
        es->top     = i - 1;
102
4.51k
        es->bottom  = ERR_NUM_ERRORS - 1;
103
4.51k
    } else {
104
        /* Didn't move anything - empty stack */
105
0
        es->top = es->bottom = 0;
106
0
    }
107
108
    /* Erase extra space as a precaution. */
109
70.4k
    for (; i < ERR_NUM_ERRORS; ++i)
110
65.9k
        err_clear(es, i, 1);
111
4.51k
}
112
113
void OSSL_ERR_STATE_restore(const ERR_STATE *es)
114
19.3k
{
115
19.3k
    size_t i;
116
19.3k
    ERR_STATE *thread_es;
117
118
19.3k
    if (es == NULL || es->bottom == es->top)
119
7.40k
        return;
120
121
11.9k
    thread_es = ossl_err_get_state_int();
122
11.9k
    if (thread_es == NULL)
123
0
        return;
124
125
37.6k
    for (i = (size_t)es->bottom; i != (size_t)es->top;) {
126
25.6k
        size_t top;
127
128
25.6k
        i = (i + 1) % ERR_NUM_ERRORS;
129
25.6k
        if ((es->err_flags[i] & ERR_FLAG_CLEAR) != 0)
130
0
            continue;
131
132
25.6k
        err_get_slot(thread_es);
133
25.6k
        top = thread_es->top;
134
25.6k
        err_clear(thread_es, top, 0);
135
136
25.6k
        thread_es->err_flags[top] = es->err_flags[i];
137
25.6k
        thread_es->err_buffer[top] = es->err_buffer[i];
138
139
25.6k
        err_set_debug(thread_es, top, es->err_file[i], es->err_line[i],
140
25.6k
                      es->err_func[i]);
141
142
25.6k
        if (es->err_data[i] != NULL && es->err_data_size[i] != 0) {
143
21.9k
            void *data;
144
21.9k
            size_t data_sz = es->err_data_size[i];
145
146
21.9k
            data = CRYPTO_malloc(data_sz, NULL, 0);
147
21.9k
            if (data != NULL) {
148
21.9k
                memcpy(data, es->err_data[i], data_sz);
149
21.9k
                err_set_data(thread_es, top, data, data_sz,
150
21.9k
                             es->err_data_flags[i] | ERR_TXT_MALLOCED);
151
21.9k
            }
152
21.9k
        } else {
153
3.76k
            err_clear_data(thread_es, top, 0);
154
3.76k
        }
155
25.6k
    }
156
11.9k
}