Coverage Report

Created: 2025-06-13 06:58

/src/openssl32/crypto/txt_db/txt_db.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright 1995-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
#include <stdio.h>
11
#include <stdlib.h>
12
#include <string.h>
13
#include "internal/cryptlib.h"
14
#include <openssl/buffer.h>
15
#include <openssl/txt_db.h>
16
17
#undef BUFSIZE
18
0
#define BUFSIZE 512
19
20
TXT_DB *TXT_DB_read(BIO *in, int num)
21
0
{
22
0
    TXT_DB *ret = NULL;
23
0
    int esc = 0;
24
0
    int i, add, n;
25
0
    int size = BUFSIZE;
26
0
    int offset = 0;
27
0
    char *p, *f;
28
0
    OPENSSL_STRING *pp;
29
0
    BUF_MEM *buf = NULL;
30
31
0
    if ((buf = BUF_MEM_new()) == NULL)
32
0
        goto err;
33
0
    if (!BUF_MEM_grow(buf, size))
34
0
        goto err;
35
36
0
    if ((ret = OPENSSL_malloc(sizeof(*ret))) == NULL)
37
0
        goto err;
38
0
    ret->num_fields = num;
39
0
    ret->index = NULL;
40
0
    ret->qual = NULL;
41
0
    if ((ret->data = sk_OPENSSL_PSTRING_new_null()) == NULL)
42
0
        goto err;
43
0
    if ((ret->index = OPENSSL_malloc(sizeof(*ret->index) * num)) == NULL)
44
0
        goto err;
45
0
    if ((ret->qual = OPENSSL_malloc(sizeof(*(ret->qual)) * num)) == NULL)
46
0
        goto err;
47
0
    for (i = 0; i < num; i++) {
48
0
        ret->index[i] = NULL;
49
0
        ret->qual[i] = NULL;
50
0
    }
51
52
0
    add = (num + 1) * sizeof(char *);
53
0
    buf->data[size - 1] = '\0';
54
0
    offset = 0;
55
0
    for (;;) {
56
0
        if (offset != 0) {
57
0
            size += BUFSIZE;
58
0
            if (!BUF_MEM_grow_clean(buf, size))
59
0
                goto err;
60
0
        }
61
0
        buf->data[offset] = '\0';
62
0
        BIO_gets(in, &(buf->data[offset]), size - offset);
63
0
        if (buf->data[offset] == '\0')
64
0
            break;
65
0
        if ((offset == 0) && (buf->data[0] == '#'))
66
0
            continue;
67
0
        i = strlen(&(buf->data[offset]));
68
0
        offset += i;
69
0
        if (buf->data[offset - 1] != '\n')
70
0
            continue;
71
0
        else {
72
0
            buf->data[offset - 1] = '\0'; /* blat the '\n' */
73
0
            if ((p = OPENSSL_malloc(add + offset)) == NULL)
74
0
                goto err;
75
0
            offset = 0;
76
0
        }
77
0
        pp = (char **)p;
78
0
        p += add;
79
0
        n = 0;
80
0
        pp[n++] = p;
81
0
        f = buf->data;
82
83
0
        esc = 0;
84
0
        for (;;) {
85
0
            if (*f == '\0')
86
0
                break;
87
0
            if (*f == '\t') {
88
0
                if (esc)
89
0
                    p--;
90
0
                else {
91
0
                    *(p++) = '\0';
92
0
                    f++;
93
0
                    if (n >= num)
94
0
                        break;
95
0
                    pp[n++] = p;
96
0
                    continue;
97
0
                }
98
0
            }
99
0
            esc = (*f == '\\');
100
0
            *(p++) = *(f++);
101
0
        }
102
0
        *(p++) = '\0';
103
0
        if ((n != num) || (*f != '\0')) {
104
0
            OPENSSL_free(pp);
105
0
            ret->error = DB_ERROR_WRONG_NUM_FIELDS;
106
0
            goto err;
107
0
        }
108
0
        pp[n] = p;
109
0
        if (!sk_OPENSSL_PSTRING_push(ret->data, pp)) {
110
0
            OPENSSL_free(pp);
111
0
            goto err;
112
0
        }
113
0
    }
114
0
    BUF_MEM_free(buf);
115
0
    return ret;
116
0
 err:
117
0
    BUF_MEM_free(buf);
118
0
    if (ret != NULL) {
119
0
        sk_OPENSSL_PSTRING_free(ret->data);
120
0
        OPENSSL_free(ret->index);
121
0
        OPENSSL_free(ret->qual);
122
0
        OPENSSL_free(ret);
123
0
    }
124
0
    return NULL;
125
0
}
126
127
OPENSSL_STRING *TXT_DB_get_by_index(TXT_DB *db, int idx,
128
                                    OPENSSL_STRING *value)
129
0
{
130
0
    OPENSSL_STRING *ret;
131
0
    LHASH_OF(OPENSSL_STRING) *lh;
132
133
0
    if (idx >= db->num_fields) {
134
0
        db->error = DB_ERROR_INDEX_OUT_OF_RANGE;
135
0
        return NULL;
136
0
    }
137
0
    lh = db->index[idx];
138
0
    if (lh == NULL) {
139
0
        db->error = DB_ERROR_NO_INDEX;
140
0
        return NULL;
141
0
    }
142
0
    ret = lh_OPENSSL_STRING_retrieve(lh, value);
143
0
    db->error = DB_ERROR_OK;
144
0
    return ret;
145
0
}
146
147
int TXT_DB_create_index(TXT_DB *db, int field, int (*qual) (OPENSSL_STRING *),
148
                        OPENSSL_LH_HASHFUNC hash, OPENSSL_LH_COMPFUNC cmp)
149
0
{
150
0
    LHASH_OF(OPENSSL_STRING) *idx;
151
0
    OPENSSL_STRING *r, *k;
152
0
    int i, n;
153
154
0
    if (field >= db->num_fields) {
155
0
        db->error = DB_ERROR_INDEX_OUT_OF_RANGE;
156
0
        return 0;
157
0
    }
158
    /* FIXME: we lose type checking at this point */
159
0
    if ((idx = (LHASH_OF(OPENSSL_STRING) *)OPENSSL_LH_new(hash, cmp)) == NULL) {
160
0
        db->error = DB_ERROR_MALLOC;
161
0
        return 0;
162
0
    }
163
0
    n = sk_OPENSSL_PSTRING_num(db->data);
164
0
    for (i = 0; i < n; i++) {
165
0
        r = sk_OPENSSL_PSTRING_value(db->data, i);
166
0
        if ((qual != NULL) && (qual(r) == 0))
167
0
            continue;
168
0
        if ((k = lh_OPENSSL_STRING_insert(idx, r)) != NULL) {
169
0
            db->error = DB_ERROR_INDEX_CLASH;
170
0
            db->arg1 = sk_OPENSSL_PSTRING_find(db->data, k);
171
0
            db->arg2 = i;
172
0
            lh_OPENSSL_STRING_free(idx);
173
0
            return 0;
174
0
        }
175
0
        if (lh_OPENSSL_STRING_retrieve(idx, r) == NULL) {
176
0
            db->error = DB_ERROR_MALLOC;
177
0
            lh_OPENSSL_STRING_free(idx);
178
0
            return 0;
179
0
        }
180
0
    }
181
0
    lh_OPENSSL_STRING_free(db->index[field]);
182
0
    db->index[field] = idx;
183
0
    db->qual[field] = qual;
184
0
    return 1;
185
0
}
186
187
long TXT_DB_write(BIO *out, TXT_DB *db)
188
0
{
189
0
    long i, j, n, nn, l, tot = 0;
190
0
    char *p, **pp, *f;
191
0
    BUF_MEM *buf = NULL;
192
0
    long ret = -1;
193
194
0
    if ((buf = BUF_MEM_new()) == NULL)
195
0
        goto err;
196
0
    n = sk_OPENSSL_PSTRING_num(db->data);
197
0
    nn = db->num_fields;
198
0
    for (i = 0; i < n; i++) {
199
0
        pp = sk_OPENSSL_PSTRING_value(db->data, i);
200
201
0
        l = 0;
202
0
        for (j = 0; j < nn; j++) {
203
0
            if (pp[j] != NULL)
204
0
                l += strlen(pp[j]);
205
0
        }
206
0
        if (!BUF_MEM_grow_clean(buf, (int)(l * 2 + nn)))
207
0
            goto err;
208
209
0
        p = buf->data;
210
0
        for (j = 0; j < nn; j++) {
211
0
            f = pp[j];
212
0
            if (f != NULL)
213
0
                for (;;) {
214
0
                    if (*f == '\0')
215
0
                        break;
216
0
                    if (*f == '\t')
217
0
                        *(p++) = '\\';
218
0
                    *(p++) = *(f++);
219
0
                }
220
0
            *(p++) = '\t';
221
0
        }
222
0
        p[-1] = '\n';
223
0
        j = p - buf->data;
224
0
        if (BIO_write(out, buf->data, (int)j) != j)
225
0
            goto err;
226
0
        tot += j;
227
0
    }
228
0
    ret = tot;
229
0
 err:
230
0
    BUF_MEM_free(buf);
231
0
    return ret;
232
0
}
233
234
int TXT_DB_insert(TXT_DB *db, OPENSSL_STRING *row)
235
0
{
236
0
    int i;
237
0
    OPENSSL_STRING *r;
238
239
0
    for (i = 0; i < db->num_fields; i++) {
240
0
        if (db->index[i] != NULL) {
241
0
            if ((db->qual[i] != NULL) && (db->qual[i] (row) == 0))
242
0
                continue;
243
0
            r = lh_OPENSSL_STRING_retrieve(db->index[i], row);
244
0
            if (r != NULL) {
245
0
                db->error = DB_ERROR_INDEX_CLASH;
246
0
                db->arg1 = i;
247
0
                db->arg_row = r;
248
0
                goto err;
249
0
            }
250
0
        }
251
0
    }
252
253
0
    for (i = 0; i < db->num_fields; i++) {
254
0
        if (db->index[i] != NULL) {
255
0
            if ((db->qual[i] != NULL) && (db->qual[i] (row) == 0))
256
0
                continue;
257
0
            (void)lh_OPENSSL_STRING_insert(db->index[i], row);
258
0
            if (lh_OPENSSL_STRING_retrieve(db->index[i], row) == NULL)
259
0
                goto err1;
260
0
        }
261
0
    }
262
0
    if (!sk_OPENSSL_PSTRING_push(db->data, row))
263
0
        goto err1;
264
0
    return 1;
265
266
0
 err1:
267
0
    db->error = DB_ERROR_MALLOC;
268
0
    while (i-- > 0) {
269
0
        if (db->index[i] != NULL) {
270
0
            if ((db->qual[i] != NULL) && (db->qual[i] (row) == 0))
271
0
                continue;
272
0
            (void)lh_OPENSSL_STRING_delete(db->index[i], row);
273
0
        }
274
0
    }
275
0
 err:
276
0
    return 0;
277
0
}
278
279
void TXT_DB_free(TXT_DB *db)
280
0
{
281
0
    int i, n;
282
0
    char **p, *max;
283
284
0
    if (db == NULL)
285
0
        return;
286
0
    if (db->index != NULL) {
287
0
        for (i = db->num_fields - 1; i >= 0; i--)
288
0
            lh_OPENSSL_STRING_free(db->index[i]);
289
0
        OPENSSL_free(db->index);
290
0
    }
291
0
    OPENSSL_free(db->qual);
292
0
    if (db->data != NULL) {
293
0
        for (i = sk_OPENSSL_PSTRING_num(db->data) - 1; i >= 0; i--) {
294
            /*
295
             * check if any 'fields' have been allocated from outside of the
296
             * initial block
297
             */
298
0
            p = sk_OPENSSL_PSTRING_value(db->data, i);
299
0
            max = p[db->num_fields]; /* last address */
300
0
            if (max == NULL) {  /* new row */
301
0
                for (n = 0; n < db->num_fields; n++)
302
0
                    OPENSSL_free(p[n]);
303
0
            } else {
304
0
                for (n = 0; n < db->num_fields; n++) {
305
0
                    if (((p[n] < (char *)p) || (p[n] > max)))
306
0
                        OPENSSL_free(p[n]);
307
0
                }
308
0
            }
309
0
            OPENSSL_free(sk_OPENSSL_PSTRING_value(db->data, i));
310
0
        }
311
0
        sk_OPENSSL_PSTRING_free(db->data);
312
0
    }
313
0
    OPENSSL_free(db);
314
0
}