Coverage Report

Created: 2025-08-28 07:07

/src/openssl34/crypto/bio/bf_prefix.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright 2018-2021 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 <string.h>
12
#include <errno.h>
13
#include "bio_local.h"
14
15
static int prefix_write(BIO *b, const char *out, size_t outl,
16
                        size_t *numwritten);
17
static int prefix_read(BIO *b, char *buf, size_t size, size_t *numread);
18
static int prefix_puts(BIO *b, const char *str);
19
static int prefix_gets(BIO *b, char *str, int size);
20
static long prefix_ctrl(BIO *b, int cmd, long arg1, void *arg2);
21
static int prefix_create(BIO *b);
22
static int prefix_destroy(BIO *b);
23
static long prefix_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp);
24
25
static const BIO_METHOD prefix_meth = {
26
    BIO_TYPE_BUFFER,
27
    "prefix",
28
    prefix_write,
29
    NULL,
30
    prefix_read,
31
    NULL,
32
    prefix_puts,
33
    prefix_gets,
34
    prefix_ctrl,
35
    prefix_create,
36
    prefix_destroy,
37
    prefix_callback_ctrl,
38
};
39
40
const BIO_METHOD *BIO_f_prefix(void)
41
9.56M
{
42
9.56M
    return &prefix_meth;
43
9.56M
}
44
45
typedef struct prefix_ctx_st {
46
    char *prefix;              /* Text prefix, given by user */
47
    unsigned int indent;       /* Indentation amount, given by user */
48
49
    int linestart;             /* flag to indicate we're at the line start */
50
} PREFIX_CTX;
51
52
static int prefix_create(BIO *b)
53
9.56M
{
54
9.56M
    PREFIX_CTX *ctx = OPENSSL_zalloc(sizeof(*ctx));
55
56
9.56M
    if (ctx == NULL)
57
0
        return 0;
58
59
9.56M
    ctx->prefix = NULL;
60
9.56M
    ctx->indent = 0;
61
9.56M
    ctx->linestart = 1;
62
9.56M
    BIO_set_data(b, ctx);
63
9.56M
    BIO_set_init(b, 1);
64
9.56M
    return 1;
65
9.56M
}
66
67
static int prefix_destroy(BIO *b)
68
9.56M
{
69
9.56M
    PREFIX_CTX *ctx = BIO_get_data(b);
70
71
9.56M
    OPENSSL_free(ctx->prefix);
72
9.56M
    OPENSSL_free(ctx);
73
9.56M
    return 1;
74
9.56M
}
75
76
static int prefix_read(BIO *b, char *in, size_t size, size_t *numread)
77
0
{
78
0
    return BIO_read_ex(BIO_next(b), in, size, numread);
79
0
}
80
81
static int prefix_write(BIO *b, const char *out, size_t outl,
82
                        size_t *numwritten)
83
72.2M
{
84
72.2M
    PREFIX_CTX *ctx = BIO_get_data(b);
85
86
72.2M
    if (ctx == NULL)
87
0
        return 0;
88
89
    /*
90
     * If no prefix is set or if it's empty, and no indentation amount is set,
91
     * we've got nothing to do here
92
     */
93
72.2M
    if ((ctx->prefix == NULL || *ctx->prefix == '\0')
94
72.2M
        && ctx->indent == 0) {
95
        /*
96
         * We do note if what comes next will be a new line, though, so we're
97
         * prepared to handle prefix and indentation the next time around.
98
         */
99
0
        if (outl > 0)
100
0
            ctx->linestart = (out[outl-1] == '\n');
101
0
        return BIO_write_ex(BIO_next(b), out, outl, numwritten);
102
0
    }
103
104
72.2M
    *numwritten = 0;
105
106
148M
    while (outl > 0) {
107
76.0M
        size_t i;
108
76.0M
        char c;
109
110
        /*
111
         * If we know that we're at the start of the line, output prefix and
112
         * indentation.
113
         */
114
76.0M
        if (ctx->linestart) {
115
13.6M
            size_t dontcare;
116
117
13.6M
            if (ctx->prefix != NULL
118
13.6M
                && !BIO_write_ex(BIO_next(b), ctx->prefix, strlen(ctx->prefix),
119
9.49M
                                 &dontcare))
120
0
                return 0;
121
13.6M
            BIO_printf(BIO_next(b), "%*s", ctx->indent, "");
122
13.6M
            ctx->linestart = 0;
123
13.6M
        }
124
125
        /* Now, go look for the next LF, or the end of the string */
126
442M
        for (i = 0, c = '\0'; i < outl && (c = out[i]) != '\n'; i++)
127
366M
            continue;
128
76.0M
        if (c == '\n')
129
4.18M
            i++;
130
131
        /* Output what we found so far */
132
152M
        while (i > 0) {
133
76.0M
            size_t num = 0;
134
135
76.0M
            if (!BIO_write_ex(BIO_next(b), out, i, &num))
136
0
                return 0;
137
76.0M
            out += num;
138
76.0M
            outl -= num;
139
76.0M
            *numwritten += num;
140
76.0M
            i -= num;
141
76.0M
        }
142
143
        /* If we found a LF, what follows is a new line, so take note */
144
76.0M
        if (c == '\n')
145
4.18M
            ctx->linestart = 1;
146
76.0M
    }
147
148
72.2M
    return 1;
149
72.2M
}
150
151
static long prefix_ctrl(BIO *b, int cmd, long num, void *ptr)
152
57.2M
{
153
57.2M
    long ret = 0;
154
57.2M
    PREFIX_CTX *ctx;
155
156
57.2M
    if (b == NULL || (ctx = BIO_get_data(b)) == NULL)
157
0
        return -1;
158
159
57.2M
    switch (cmd) {
160
9.49M
    case BIO_CTRL_SET_PREFIX:
161
9.49M
        OPENSSL_free(ctx->prefix);
162
9.49M
        if (ptr == NULL) {
163
0
            ctx->prefix = NULL;
164
0
            ret = 1;
165
9.49M
        } else {
166
9.49M
            ctx->prefix = OPENSSL_strdup((const char *)ptr);
167
9.49M
            ret = ctx->prefix != NULL;
168
9.49M
        }
169
9.49M
        break;
170
19.1M
    case BIO_CTRL_SET_INDENT:
171
19.1M
        if (num >= 0) {
172
19.1M
            ctx->indent = (unsigned int)num;
173
19.1M
            ret = 1;
174
19.1M
        }
175
19.1M
        break;
176
9.49M
    case BIO_CTRL_GET_INDENT:
177
9.49M
        ret = (long)ctx->indent;
178
9.49M
        break;
179
19.1M
    default:
180
        /* Commands that we intercept before passing them along */
181
19.1M
        switch (cmd) {
182
0
        case BIO_C_FILE_SEEK:
183
0
        case BIO_CTRL_RESET:
184
0
            ctx->linestart = 1;
185
0
            break;
186
19.1M
        }
187
19.1M
        if (BIO_next(b) != NULL)
188
19.1M
            ret = BIO_ctrl(BIO_next(b), cmd, num, ptr);
189
19.1M
        break;
190
57.2M
    }
191
57.2M
    return ret;
192
57.2M
}
193
194
static long prefix_callback_ctrl(BIO *b, int cmd, BIO_info_cb *fp)
195
0
{
196
0
    return BIO_callback_ctrl(BIO_next(b), cmd, fp);
197
0
}
198
199
static int prefix_gets(BIO *b, char *buf, int size)
200
0
{
201
0
    return BIO_gets(BIO_next(b), buf, size);
202
0
}
203
204
static int prefix_puts(BIO *b, const char *str)
205
0
{
206
0
    return BIO_write(b, str, strlen(str));
207
0
}