Coverage Report

Created: 2018-08-29 13:53

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