/src/openssl/crypto/bio/bio_print.c
Line | Count | Source |
1 | | /* |
2 | | * Copyright 1995-2026 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 | | int BIO_vprintf(BIO *bio, const char *format, va_list args) |
32 | 0 | { |
33 | 0 | va_list cp_args; |
34 | 0 | int sz; |
35 | 0 | int ret = -1; |
36 | 0 | char buf[512]; |
37 | 0 | char *abuf; |
38 | | #if defined(_MSC_VER) && _MSC_VER < 1900 |
39 | | char *msvc_fmt_alloc = NULL; |
40 | | #endif |
41 | 0 | const char *fmt; |
42 | |
|
43 | | #if defined(_MSC_VER) && _MSC_VER < 1900 |
44 | | /* Fix MSVC 2013 format to accept C99 format strings */ |
45 | | if (!msvc_translate_printf_format(format, &fmt, &msvc_fmt_alloc)) |
46 | | goto done; |
47 | | #else |
48 | 0 | fmt = format; |
49 | 0 | #endif |
50 | |
|
51 | 0 | va_copy(cp_args, args); |
52 | | |
53 | | /* |
54 | | * some compilers modify va_list, hence each call to v*printf() |
55 | | * should operate with its own instance of va_list. The first |
56 | | * call to vsnprintf() here uses args we got in function argument. |
57 | | * The second call is going to use cp_args we made earlier. |
58 | | */ |
59 | 0 | sz = vsnprintf(buf, sizeof(buf), fmt, args); |
60 | 0 | if (sz >= 0) { |
61 | 0 | if ((size_t)sz >= sizeof(buf)) { |
62 | 0 | sz += 1; |
63 | 0 | abuf = (char *)OPENSSL_malloc(sz); |
64 | 0 | if (abuf == NULL) { |
65 | 0 | ret = -1; |
66 | 0 | } else { |
67 | 0 | sz = vsnprintf(abuf, sz, fmt, cp_args); |
68 | 0 | ret = BIO_write(bio, abuf, sz); |
69 | 0 | OPENSSL_free(abuf); |
70 | 0 | } |
71 | 0 | } else { |
72 | | /* vsnprintf returns length not including nul-terminator */ |
73 | 0 | ret = BIO_write(bio, buf, sz); |
74 | 0 | } |
75 | 0 | } |
76 | 0 | va_end(cp_args); |
77 | | #if defined(_MSC_VER) && _MSC_VER < 1900 |
78 | | done: |
79 | | OPENSSL_free(msvc_fmt_alloc); |
80 | | #endif |
81 | 0 | return ret; |
82 | 0 | } |
83 | | |
84 | | #ifndef OPENSSL_NO_DEPRECATED_4_1 |
85 | | /* |
86 | | * For historical reasons BIO_snprintf and friends return -1 on truncation |
87 | | * instead of the C99 snprintf semantic of returning the number of characters |
88 | | * that would have been written. Deprecated in 4.1; new code should call |
89 | | * snprintf() / vsnprintf() directly. |
90 | | */ |
91 | | int BIO_snprintf(char *buf, size_t n, const char *format, ...) |
92 | 0 | { |
93 | 0 | va_list args; |
94 | 0 | int ret; |
95 | |
|
96 | 0 | va_start(args, format); |
97 | |
|
98 | 0 | ret = vsnprintf(buf, n, format, args); |
99 | 0 | if ((size_t)ret >= n) |
100 | 0 | ret = -1; |
101 | 0 | va_end(args); |
102 | |
|
103 | 0 | return ret; |
104 | 0 | } |
105 | | |
106 | | int BIO_vsnprintf(char *buf, size_t n, const char *format, va_list args) |
107 | 0 | { |
108 | 0 | int ret; |
109 | |
|
110 | 0 | ret = vsnprintf(buf, n, format, args); |
111 | 0 | if ((size_t)ret >= n) |
112 | 0 | ret = -1; |
113 | |
|
114 | 0 | return ret; |
115 | 0 | } |
116 | | #endif /* OPENSSL_NO_DEPRECATED_4_1 */ |