Coverage Report

Created: 2025-12-10 06:24

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/openssl/crypto/bio/bio_print.c
Line
Count
Source
1
/*
2
 * Copyright 1995-2025 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 "internal/cryptlib.h"
13
#include "crypto/ctype.h"
14
#include "internal/numbers.h"
15
#include <openssl/bio.h>
16
#include <openssl/configuration.h>
17
18
int BIO_printf(BIO *bio, const char *format, ...)
19
0
{
20
0
    va_list args;
21
0
    int ret;
22
23
0
    va_start(args, format);
24
25
0
    ret = BIO_vprintf(bio, format, args);
26
27
0
    va_end(args);
28
0
    return ret;
29
0
}
30
31
#if defined(_WIN32)
32
/*
33
 * _MSC_VER described here:
34
 * https://learn.microsoft.com/en-us/cpp/overview/compiler-versions?view=msvc-170
35
 *
36
 * Beginning with the UCRT in Visual Studio 2015 and Windows 10, snprintf is no
37
 * longer identical to _snprintf. The snprintf behavior is now C99 standard
38
 * conformant. The difference is that if you run out of buffer, snprintf
39
 * null-terminates the end of the buffer and returns the number of characters
40
 * that would have been required whereas _snprintf doesn't null-terminate the
41
 * buffer and returns -1. Also, snprintf() includes one more character in the
42
 * output because it doesn't null-terminate the buffer.
43
 * [ https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/snprintf-snprintf-snprintf-l-snwprintf-snwprintf-l?view=msvc-170#remarks
44
 *
45
 * for older MSVC (older than 2015) we can use _vscprintf() and _vsnprintf()
46
 * as suggested here:
47
 * https://stackoverflow.com/questions/2915672/snprintf-and-visual-studio-2010
48
 *
49
 */
50
static int msvc_bio_vprintf(BIO *bio, const char *format, va_list args)
51
{
52
    char buf[512];
53
    char *abuf;
54
    int ret, sz;
55
56
    sz = _vsnprintf_s(buf, sizeof(buf), _TRUNCATE, format, args);
57
    if (sz == -1) {
58
        sz = _vscprintf(format, args) + 1;
59
        abuf = (char *)OPENSSL_malloc(sz);
60
        if (abuf == NULL) {
61
            ret = -1;
62
        } else {
63
            sz = _vsnprintf(abuf, sz, format, args);
64
            ret = BIO_write(bio, abuf, sz);
65
            OPENSSL_free(abuf);
66
        }
67
    } else {
68
        ret = BIO_write(bio, buf, sz);
69
    }
70
71
    return ret;
72
}
73
74
/*
75
 * This function is for unit test on windows only when built with Visual Studio
76
 */
77
int ossl_BIO_snprintf_msvc(char *buf, size_t n, const char *format, ...)
78
{
79
    va_list args;
80
    int ret;
81
82
    va_start(args, format);
83
    ret = _vsnprintf_s(buf, n, _TRUNCATE, format, args);
84
    va_end(args);
85
86
    return ret;
87
}
88
89
#endif
90
91
int BIO_vprintf(BIO *bio, const char *format, va_list args)
92
0
{
93
0
    va_list cp_args;
94
0
#if !defined(_MSC_VER) || _MSC_VER > 1900
95
0
    int sz;
96
0
#endif
97
0
    int ret = -1;
98
99
0
    va_copy(cp_args, args);
100
#if defined(_MSC_VER) && _MSC_VER < 1900
101
    ret = msvc_bio_vprintf(bio, format, cp_args);
102
#else
103
0
    char buf[512];
104
0
    char *abuf;
105
    /*
106
     * some compilers modify va_list, hence each call to v*printf()
107
     * should operate with its own instance of va_list. The first
108
     * call to vsnprintf() here uses args we got in function argument.
109
     * The second call is going to use cp_args we made earlier.
110
     */
111
0
    sz = vsnprintf(buf, sizeof(buf), format, args);
112
0
    if (sz >= 0) {
113
0
        if ((size_t)sz > sizeof(buf)) {
114
0
            sz += 1;
115
0
            abuf = (char *)OPENSSL_malloc(sz);
116
0
            if (abuf == NULL) {
117
0
                ret = -1;
118
0
            } else {
119
0
                sz = vsnprintf(abuf, sz, format, cp_args);
120
0
                ret = BIO_write(bio, abuf, sz);
121
0
                OPENSSL_free(abuf);
122
0
            }
123
0
        } else {
124
            /* vsnprintf returns length not including nul-terminator */
125
0
            ret = BIO_write(bio, buf, sz);
126
0
        }
127
0
    }
128
0
#endif
129
0
    va_end(cp_args);
130
0
    return ret;
131
0
}
132
133
/*
134
 * For historical reasons BIO_snprintf and friends return a failure for string
135
 * truncation (-1) instead of the POSIX requirement of a success with the
136
 * number of characters that would have been written. Upon seeing -1 on
137
 * return, the caller must treat output buf as unsafe (as a buf with missing
138
 * nul terminator).
139
 */
140
int BIO_snprintf(char *buf, size_t n, const char *format, ...)
141
5.48k
{
142
5.48k
    va_list args;
143
5.48k
    int ret;
144
145
5.48k
    va_start(args, format);
146
147
#if defined(_MSC_VER) && _MSC_VER < 1900
148
    ret = _vsnprintf_s(buf, n, _TRUNCATE, format, args);
149
#else
150
5.48k
    ret = vsnprintf(buf, n, format, args);
151
5.48k
    if ((size_t)ret >= n)
152
0
        ret = -1;
153
5.48k
#endif
154
5.48k
    va_end(args);
155
156
5.48k
    return ret;
157
5.48k
}
158
159
int BIO_vsnprintf(char *buf, size_t n, const char *format, va_list args)
160
1.09k
{
161
1.09k
    int ret;
162
163
#if defined(_MSC_VER) && _MSC_VER < 1900
164
    ret = _vsnprintf_s(buf, n, _TRUNCATE, format, args);
165
#else
166
1.09k
    ret = vsnprintf(buf, n, format, args);
167
1.09k
    if ((size_t)ret >= n)
168
0
        ret = -1;
169
1.09k
#endif
170
1.09k
    return ret;
171
1.09k
}