xref: /openbsd-src/lib/libcrypto/bio/b_print.c (revision 1ad61ae0a79a724d2d3ec69e69c8e1d1ff6b53a0)
1 /* $OpenBSD: b_print.c,v 1.27 2023/07/05 21:23:37 beck Exp $ */
2 
3 /* Theo de Raadt places this file in the public domain. */
4 
5 #include <openssl/bio.h>
6 
7 int
8 BIO_printf(BIO *bio, const char *format, ...)
9 {
10 	va_list args;
11 	int ret;
12 
13 	va_start(args, format);
14 	ret = BIO_vprintf(bio, format, args);
15 	va_end(args);
16 	return (ret);
17 }
18 LCRYPTO_ALIAS(BIO_printf);
19 
20 #ifdef HAVE_FUNOPEN
21 static int
22 _BIO_write(void *cookie, const char *buf, int nbytes)
23 {
24 	return BIO_write(cookie, buf, nbytes);
25 }
26 
27 int
28 BIO_vprintf(BIO *bio, const char *format, va_list args)
29 {
30 	int ret;
31 	FILE *fp;
32 
33 	fp = funopen(bio, NULL, &_BIO_write, NULL, NULL);
34 	if (fp == NULL) {
35 		ret = -1;
36 		goto fail;
37 	}
38 	ret = vfprintf(fp, format, args);
39 	fclose(fp);
40 fail:
41 	return (ret);
42 }
43 LCRYPTO_ALIAS(BIO_vprintf);
44 
45 #else /* !HAVE_FUNOPEN */
46 
47 int
48 BIO_vprintf(BIO *bio, const char *format, va_list args)
49 {
50 	int ret;
51 	char *buf = NULL;
52 
53 	ret = vasprintf(&buf, format, args);
54 	if (ret == -1)
55 		return (ret);
56 	BIO_write(bio, buf, ret);
57 	free(buf);
58 	return (ret);
59 }
60 LCRYPTO_ALIAS(BIO_vprintf);
61 
62 #endif /* HAVE_FUNOPEN */
63 
64 /*
65  * BIO_snprintf and BIO_vsnprintf return -1 for overflow,
66  * due to the history of this API.  Justification:
67  *
68  * Traditional snprintf surfaced in 4.4BSD, and returned
69  * "number of bytes wanted". Solaris and Windows opted to
70  * return -1.  A draft standard was written which returned -1.
71  * Due to the large volume of code already using the first
72  * semantics, the draft was repaired before standardization to
73  * specify "number of bytes wanted" plus "-1 for character conversion
74  * style errors".  Solaris adapted to this rule, but Windows stuck
75  * with -1.
76  *
77  * Original OpenSSL comment which is full of lies:
78  *
79  * "In case of truncation, return -1 like traditional snprintf.
80  * (Current drafts for ISO/IEC 9899 say snprintf should return
81  * the number of characters that would have been written,
82  * had the buffer been large enough.)"
83  */
84 int
85 BIO_snprintf(char *buf, size_t n, const char *format, ...)
86 {
87 	va_list args;
88 	int ret;
89 
90 	va_start(args, format);
91 	ret = vsnprintf(buf, n, format, args);
92 	va_end(args);
93 
94 	if (ret >= n || ret == -1)
95 		return (-1);
96 	return (ret);
97 }
98 LCRYPTO_ALIAS(BIO_snprintf);
99 
100 int
101 BIO_vsnprintf(char *buf, size_t n, const char *format, va_list args)
102 {
103 	int ret;
104 
105 	ret = vsnprintf(buf, n, format, args);
106 
107 	if (ret >= n || ret == -1)
108 		return (-1);
109 	return (ret);
110 }
111 LCRYPTO_ALIAS(BIO_vsnprintf);
112