VirtualBox

source: vbox/trunk/src/libs/openssl-1.1.1g/crypto/bio/b_print.c@ 85915

Last change on this file since 85915 was 83916, checked in by vboxsync, 5 years ago

openssl-1.1.1g: Applied and adjusted our OpenSSL changes to 1.1.1g. bugref:9719

File size: 25.6 KB
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 <string.h>
12#ifndef NO_SYS_TYPES_H
13# include <sys/types.h>
14#endif
15#include <openssl/bn.h> /* To get BN_LLONG properly defined */
16#include "internal/cryptlib.h"
17#include "crypto/ctype.h"
18#include "internal/numbers.h"
19#include <openssl/bio.h>
20
21/*
22 * Copyright Patrick Powell 1995
23 * This code is based on code written by Patrick Powell <[email protected]>
24 * It may be used for any purpose as long as this notice remains intact
25 * on all source code distributions.
26 */
27
28#ifdef HAVE_LONG_DOUBLE
29# define LDOUBLE long double
30#else
31# define LDOUBLE double
32#endif
33
34static int fmtstr(char **, char **, size_t *, size_t *,
35 const char *, int, int, int);
36static int fmtint(char **, char **, size_t *, size_t *,
37 int64_t, int, int, int, int);
38static int fmtfp(char **, char **, size_t *, size_t *,
39 LDOUBLE, int, int, int, int);
40static int doapr_outch(char **, char **, size_t *, size_t *, int);
41static int _dopr(char **sbuffer, char **buffer,
42 size_t *maxlen, size_t *retlen, int *truncated,
43 const char *format, va_list args);
44
45/* format read states */
46#define DP_S_DEFAULT 0
47#define DP_S_FLAGS 1
48#define DP_S_MIN 2
49#define DP_S_DOT 3
50#define DP_S_MAX 4
51#define DP_S_MOD 5
52#define DP_S_CONV 6
53#define DP_S_DONE 7
54
55/* format flags - Bits */
56/* left-aligned padding */
57#define DP_F_MINUS (1 << 0)
58/* print an explicit '+' for a value with positive sign */
59#define DP_F_PLUS (1 << 1)
60/* print an explicit ' ' for a value with positive sign */
61#define DP_F_SPACE (1 << 2)
62/* print 0/0x prefix for octal/hex and decimal point for floating point */
63#define DP_F_NUM (1 << 3)
64/* print leading zeroes */
65#define DP_F_ZERO (1 << 4)
66/* print HEX in UPPPERcase */
67#define DP_F_UP (1 << 5)
68/* treat value as unsigned */
69#define DP_F_UNSIGNED (1 << 6)
70
71/* conversion flags */
72#define DP_C_SHORT 1
73#define DP_C_LONG 2
74#define DP_C_LDOUBLE 3
75#define DP_C_LLONG 4
76#define DP_C_SIZE 5
77
78/* Floating point formats */
79#define F_FORMAT 0
80#define E_FORMAT 1
81#define G_FORMAT 2
82
83/* some handy macros */
84#define char_to_int(p) (p - '0')
85#define OSSL_MAX(p,q) ((p >= q) ? p : q)
86
87static int
88_dopr(char **sbuffer,
89 char **buffer,
90 size_t *maxlen,
91 size_t *retlen, int *truncated, const char *format, va_list args)
92{
93 char ch;
94 int64_t value;
95 LDOUBLE fvalue;
96 char *strvalue;
97 int min;
98 int max;
99 int state;
100 int flags;
101 int cflags;
102 size_t currlen;
103
104 state = DP_S_DEFAULT;
105 flags = currlen = cflags = min = 0;
106 max = -1;
107 ch = *format++;
108
109 while (state != DP_S_DONE) {
110 if (ch == '\0' || (buffer == NULL && currlen >= *maxlen))
111 state = DP_S_DONE;
112
113 switch (state) {
114 case DP_S_DEFAULT:
115 if (ch == '%')
116 state = DP_S_FLAGS;
117 else
118 if (!doapr_outch(sbuffer, buffer, &currlen, maxlen, ch))
119 return 0;
120 ch = *format++;
121 break;
122 case DP_S_FLAGS:
123 switch (ch) {
124 case '-':
125 flags |= DP_F_MINUS;
126 ch = *format++;
127 break;
128 case '+':
129 flags |= DP_F_PLUS;
130 ch = *format++;
131 break;
132 case ' ':
133 flags |= DP_F_SPACE;
134 ch = *format++;
135 break;
136 case '#':
137 flags |= DP_F_NUM;
138 ch = *format++;
139 break;
140 case '0':
141 flags |= DP_F_ZERO;
142 ch = *format++;
143 break;
144 default:
145 state = DP_S_MIN;
146 break;
147 }
148 break;
149 case DP_S_MIN:
150 if (ossl_isdigit(ch)) {
151 min = 10 * min + char_to_int(ch);
152 ch = *format++;
153 } else if (ch == '*') {
154 min = va_arg(args, int);
155 ch = *format++;
156 state = DP_S_DOT;
157 } else
158 state = DP_S_DOT;
159 break;
160 case DP_S_DOT:
161 if (ch == '.') {
162 state = DP_S_MAX;
163 ch = *format++;
164 } else
165 state = DP_S_MOD;
166 break;
167 case DP_S_MAX:
168 if (ossl_isdigit(ch)) {
169 if (max < 0)
170 max = 0;
171 max = 10 * max + char_to_int(ch);
172 ch = *format++;
173 } else if (ch == '*') {
174 max = va_arg(args, int);
175 ch = *format++;
176 state = DP_S_MOD;
177 } else
178 state = DP_S_MOD;
179 break;
180 case DP_S_MOD:
181 switch (ch) {
182 case 'h':
183 cflags = DP_C_SHORT;
184 ch = *format++;
185 break;
186 case 'l':
187 if (*format == 'l') {
188 cflags = DP_C_LLONG;
189 format++;
190 } else
191 cflags = DP_C_LONG;
192 ch = *format++;
193 break;
194 case 'q':
195 case 'j':
196 cflags = DP_C_LLONG;
197 ch = *format++;
198 break;
199 case 'L':
200 cflags = DP_C_LDOUBLE;
201 ch = *format++;
202 break;
203 case 'z':
204 cflags = DP_C_SIZE;
205 ch = *format++;
206 break;
207 default:
208 break;
209 }
210 state = DP_S_CONV;
211 break;
212 case DP_S_CONV:
213 switch (ch) {
214 case 'd':
215 case 'i':
216 switch (cflags) {
217 case DP_C_SHORT:
218 value = (short int)va_arg(args, int);
219 break;
220 case DP_C_LONG:
221 value = va_arg(args, long int);
222 break;
223 case DP_C_LLONG:
224 value = va_arg(args, int64_t);
225 break;
226 case DP_C_SIZE:
227 value = va_arg(args, ossl_ssize_t);
228 break;
229 default:
230 value = va_arg(args, int);
231 break;
232 }
233 if (!fmtint(sbuffer, buffer, &currlen, maxlen, value, 10, min,
234 max, flags))
235 return 0;
236 break;
237 case 'X':
238 flags |= DP_F_UP;
239 /* FALLTHROUGH */
240 case 'x':
241 case 'o':
242 case 'u':
243 flags |= DP_F_UNSIGNED;
244 switch (cflags) {
245 case DP_C_SHORT:
246 value = (unsigned short int)va_arg(args, unsigned int);
247 break;
248 case DP_C_LONG:
249 value = va_arg(args, unsigned long int);
250 break;
251 case DP_C_LLONG:
252 value = va_arg(args, uint64_t);
253 break;
254 case DP_C_SIZE:
255 value = va_arg(args, size_t);
256 break;
257 default:
258 value = va_arg(args, unsigned int);
259 break;
260 }
261 if (!fmtint(sbuffer, buffer, &currlen, maxlen, value,
262 ch == 'o' ? 8 : (ch == 'u' ? 10 : 16),
263 min, max, flags))
264 return 0;
265 break;
266 case 'f':
267 if (cflags == DP_C_LDOUBLE)
268 fvalue = va_arg(args, LDOUBLE);
269 else
270 fvalue = va_arg(args, double);
271 if (!fmtfp(sbuffer, buffer, &currlen, maxlen, fvalue, min, max,
272 flags, F_FORMAT))
273 return 0;
274 break;
275 case 'E':
276 flags |= DP_F_UP;
277 /* fall thru */
278 case 'e':
279 if (cflags == DP_C_LDOUBLE)
280 fvalue = va_arg(args, LDOUBLE);
281 else
282 fvalue = va_arg(args, double);
283 if (!fmtfp(sbuffer, buffer, &currlen, maxlen, fvalue, min, max,
284 flags, E_FORMAT))
285 return 0;
286 break;
287 case 'G':
288 flags |= DP_F_UP;
289 /* fall thru */
290 case 'g':
291 if (cflags == DP_C_LDOUBLE)
292 fvalue = va_arg(args, LDOUBLE);
293 else
294 fvalue = va_arg(args, double);
295 if (!fmtfp(sbuffer, buffer, &currlen, maxlen, fvalue, min, max,
296 flags, G_FORMAT))
297 return 0;
298 break;
299 case 'c':
300 if (!doapr_outch(sbuffer, buffer, &currlen, maxlen,
301 va_arg(args, int)))
302 return 0;
303 break;
304 case 's':
305 strvalue = va_arg(args, char *);
306 if (max < 0) {
307 if (buffer)
308 max = INT_MAX;
309 else
310 max = *maxlen;
311 }
312 if (!fmtstr(sbuffer, buffer, &currlen, maxlen, strvalue,
313 flags, min, max))
314 return 0;
315 break;
316 case 'p':
317 value = (size_t)va_arg(args, void *);
318 if (!fmtint(sbuffer, buffer, &currlen, maxlen,
319 value, 16, min, max, flags | DP_F_NUM))
320 return 0;
321 break;
322 case 'n':
323 {
324 int *num;
325 num = va_arg(args, int *);
326 *num = currlen;
327 }
328 break;
329 case '%':
330 if (!doapr_outch(sbuffer, buffer, &currlen, maxlen, ch))
331 return 0;
332 break;
333 case 'w':
334 /* not supported yet, treat as next char */
335 ch = *format++;
336 break;
337 default:
338 /* unknown, skip */
339 break;
340 }
341 ch = *format++;
342 state = DP_S_DEFAULT;
343 flags = cflags = min = 0;
344 max = -1;
345 break;
346 case DP_S_DONE:
347 break;
348 default:
349 break;
350 }
351 }
352 /*
353 * We have to truncate if there is no dynamic buffer and we have filled the
354 * static buffer.
355 */
356 if (buffer == NULL) {
357 *truncated = (currlen > *maxlen - 1);
358 if (*truncated)
359 currlen = *maxlen - 1;
360 }
361 if (!doapr_outch(sbuffer, buffer, &currlen, maxlen, '\0'))
362 return 0;
363 *retlen = currlen - 1;
364 return 1;
365}
366
367static int
368fmtstr(char **sbuffer,
369 char **buffer,
370 size_t *currlen,
371 size_t *maxlen, const char *value, int flags, int min, int max)
372{
373 int padlen;
374 size_t strln;
375 int cnt = 0;
376
377 if (value == 0)
378 value = "<NULL>";
379
380 strln = OPENSSL_strnlen(value, max < 0 ? SIZE_MAX : (size_t)max);
381
382 padlen = min - strln;
383 if (min < 0 || padlen < 0)
384 padlen = 0;
385 if (max >= 0) {
386 /*
387 * Calculate the maximum output including padding.
388 * Make sure max doesn't overflow into negativity
389 */
390 if (max < INT_MAX - padlen)
391 max += padlen;
392 else
393 max = INT_MAX;
394 }
395 if (flags & DP_F_MINUS)
396 padlen = -padlen;
397
398 while ((padlen > 0) && (max < 0 || cnt < max)) {
399 if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' '))
400 return 0;
401 --padlen;
402 ++cnt;
403 }
404 while (strln > 0 && (max < 0 || cnt < max)) {
405 if (!doapr_outch(sbuffer, buffer, currlen, maxlen, *value++))
406 return 0;
407 --strln;
408 ++cnt;
409 }
410 while ((padlen < 0) && (max < 0 || cnt < max)) {
411 if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' '))
412 return 0;
413 ++padlen;
414 ++cnt;
415 }
416 return 1;
417}
418
419static int
420fmtint(char **sbuffer,
421 char **buffer,
422 size_t *currlen,
423 size_t *maxlen, int64_t value, int base, int min, int max, int flags)
424{
425 int signvalue = 0;
426 const char *prefix = "";
427 uint64_t uvalue;
428 char convert[DECIMAL_SIZE(value) + 3];
429 int place = 0;
430 int spadlen = 0;
431 int zpadlen = 0;
432 int caps = 0;
433
434 if (max < 0)
435 max = 0;
436 uvalue = value;
437 if (!(flags & DP_F_UNSIGNED)) {
438 if (value < 0) {
439 signvalue = '-';
440 uvalue = 0 - (uint64_t)value;
441 } else if (flags & DP_F_PLUS)
442 signvalue = '+';
443 else if (flags & DP_F_SPACE)
444 signvalue = ' ';
445 }
446 if (flags & DP_F_NUM) {
447 if (base == 8)
448 prefix = "0";
449 if (base == 16)
450 prefix = "0x";
451 }
452 if (flags & DP_F_UP)
453 caps = 1;
454 do {
455 convert[place++] = (caps ? "0123456789ABCDEF" : "0123456789abcdef")
456 [uvalue % (unsigned)base];
457 uvalue = (uvalue / (unsigned)base);
458 } while (uvalue && (place < (int)sizeof(convert)));
459 if (place == sizeof(convert))
460 place--;
461 convert[place] = 0;
462
463 zpadlen = max - place;
464 spadlen =
465 min - OSSL_MAX(max, place) - (signvalue ? 1 : 0) - strlen(prefix);
466 if (zpadlen < 0)
467 zpadlen = 0;
468 if (spadlen < 0)
469 spadlen = 0;
470 if (flags & DP_F_ZERO) {
471 zpadlen = OSSL_MAX(zpadlen, spadlen);
472 spadlen = 0;
473 }
474 if (flags & DP_F_MINUS)
475 spadlen = -spadlen;
476
477 /* spaces */
478 while (spadlen > 0) {
479 if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' '))
480 return 0;
481 --spadlen;
482 }
483
484 /* sign */
485 if (signvalue)
486 if (!doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue))
487 return 0;
488
489 /* prefix */
490 while (*prefix) {
491 if (!doapr_outch(sbuffer, buffer, currlen, maxlen, *prefix))
492 return 0;
493 prefix++;
494 }
495
496 /* zeros */
497 if (zpadlen > 0) {
498 while (zpadlen > 0) {
499 if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '0'))
500 return 0;
501 --zpadlen;
502 }
503 }
504 /* digits */
505 while (place > 0) {
506 if (!doapr_outch(sbuffer, buffer, currlen, maxlen, convert[--place]))
507 return 0;
508 }
509
510 /* left justified spaces */
511 while (spadlen < 0) {
512 if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' '))
513 return 0;
514 ++spadlen;
515 }
516 return 1;
517}
518
519static LDOUBLE abs_val(LDOUBLE value)
520{
521 LDOUBLE result = value;
522 if (value < 0)
523 result = -value;
524 return result;
525}
526
527static LDOUBLE pow_10(int in_exp)
528{
529 LDOUBLE result = 1;
530 while (in_exp) {
531 result *= 10;
532 in_exp--;
533 }
534 return result;
535}
536
537static long roundv(LDOUBLE value)
538{
539 long intpart;
540 intpart = (long)value;
541 value = value - intpart;
542 if (value >= 0.5)
543 intpart++;
544 return intpart;
545}
546
547static int
548fmtfp(char **sbuffer,
549 char **buffer,
550 size_t *currlen,
551 size_t *maxlen, LDOUBLE fvalue, int min, int max, int flags, int style)
552{
553 int signvalue = 0;
554 LDOUBLE ufvalue;
555 LDOUBLE tmpvalue;
556 char iconvert[20];
557 char fconvert[20];
558 char econvert[20];
559 int iplace = 0;
560 int fplace = 0;
561 int eplace = 0;
562 int padlen = 0;
563 int zpadlen = 0;
564 long exp = 0;
565 unsigned long intpart;
566 unsigned long fracpart;
567 unsigned long max10;
568 int realstyle;
569
570 if (max < 0)
571 max = 6;
572
573 if (fvalue < 0)
574 signvalue = '-';
575 else if (flags & DP_F_PLUS)
576 signvalue = '+';
577 else if (flags & DP_F_SPACE)
578 signvalue = ' ';
579
580 /*
581 * G_FORMAT sometimes prints like E_FORMAT and sometimes like F_FORMAT
582 * depending on the number to be printed. Work out which one it is and use
583 * that from here on.
584 */
585 if (style == G_FORMAT) {
586 if (fvalue == 0.0) {
587 realstyle = F_FORMAT;
588 } else if (fvalue < 0.0001) {
589 realstyle = E_FORMAT;
590 } else if ((max == 0 && fvalue >= 10)
591 || (max > 0 && fvalue >= pow_10(max))) {
592 realstyle = E_FORMAT;
593 } else {
594 realstyle = F_FORMAT;
595 }
596 } else {
597 realstyle = style;
598 }
599
600 if (style != F_FORMAT) {
601 tmpvalue = fvalue;
602 /* Calculate the exponent */
603 if (fvalue != 0.0) {
604 while (tmpvalue < 1) {
605 tmpvalue *= 10;
606 exp--;
607 }
608 while (tmpvalue > 10) {
609 tmpvalue /= 10;
610 exp++;
611 }
612 }
613 if (style == G_FORMAT) {
614 /*
615 * In G_FORMAT the "precision" represents significant digits. We
616 * always have at least 1 significant digit.
617 */
618 if (max == 0)
619 max = 1;
620 /* Now convert significant digits to decimal places */
621 if (realstyle == F_FORMAT) {
622 max -= (exp + 1);
623 if (max < 0) {
624 /*
625 * Should not happen. If we're in F_FORMAT then exp < max?
626 */
627 return 0;
628 }
629 } else {
630 /*
631 * In E_FORMAT there is always one significant digit in front
632 * of the decimal point, so:
633 * significant digits == 1 + decimal places
634 */
635 max--;
636 }
637 }
638 if (realstyle == E_FORMAT)
639 fvalue = tmpvalue;
640 }
641 ufvalue = abs_val(fvalue);
642 if (ufvalue > ULONG_MAX) {
643 /* Number too big */
644 return 0;
645 }
646 intpart = (unsigned long)ufvalue;
647
648 /*
649 * sorry, we only support 9 digits past the decimal because of our
650 * conversion method
651 */
652 if (max > 9)
653 max = 9;
654
655 /*
656 * we "cheat" by converting the fractional part to integer by multiplying
657 * by a factor of 10
658 */
659 max10 = roundv(pow_10(max));
660 fracpart = roundv(pow_10(max) * (ufvalue - intpart));
661
662 if (fracpart >= max10) {
663 intpart++;
664 fracpart -= max10;
665 }
666
667 /* convert integer part */
668 do {
669 iconvert[iplace++] = "0123456789"[intpart % 10];
670 intpart = (intpart / 10);
671 } while (intpart && (iplace < (int)sizeof(iconvert)));
672 if (iplace == sizeof(iconvert))
673 iplace--;
674 iconvert[iplace] = 0;
675
676 /* convert fractional part */
677 while (fplace < max) {
678 if (style == G_FORMAT && fplace == 0 && (fracpart % 10) == 0) {
679 /* We strip trailing zeros in G_FORMAT */
680 max--;
681 fracpart = fracpart / 10;
682 if (fplace < max)
683 continue;
684 break;
685 }
686 fconvert[fplace++] = "0123456789"[fracpart % 10];
687 fracpart = (fracpart / 10);
688 }
689
690 if (fplace == sizeof(fconvert))
691 fplace--;
692 fconvert[fplace] = 0;
693
694 /* convert exponent part */
695 if (realstyle == E_FORMAT) {
696 int tmpexp;
697 if (exp < 0)
698 tmpexp = -exp;
699 else
700 tmpexp = exp;
701
702 do {
703 econvert[eplace++] = "0123456789"[tmpexp % 10];
704 tmpexp = (tmpexp / 10);
705 } while (tmpexp > 0 && eplace < (int)sizeof(econvert));
706 /* Exponent is huge!! Too big to print */
707 if (tmpexp > 0)
708 return 0;
709 /* Add a leading 0 for single digit exponents */
710 if (eplace == 1)
711 econvert[eplace++] = '0';
712 }
713
714 /*
715 * -1 for decimal point (if we have one, i.e. max > 0),
716 * another -1 if we are printing a sign
717 */
718 padlen = min - iplace - max - (max > 0 ? 1 : 0) - ((signvalue) ? 1 : 0);
719 /* Take some off for exponent prefix "+e" and exponent */
720 if (realstyle == E_FORMAT)
721 padlen -= 2 + eplace;
722 zpadlen = max - fplace;
723 if (zpadlen < 0)
724 zpadlen = 0;
725 if (padlen < 0)
726 padlen = 0;
727 if (flags & DP_F_MINUS)
728 padlen = -padlen;
729
730 if ((flags & DP_F_ZERO) && (padlen > 0)) {
731 if (signvalue) {
732 if (!doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue))
733 return 0;
734 --padlen;
735 signvalue = 0;
736 }
737 while (padlen > 0) {
738 if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '0'))
739 return 0;
740 --padlen;
741 }
742 }
743 while (padlen > 0) {
744 if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' '))
745 return 0;
746 --padlen;
747 }
748 if (signvalue && !doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue))
749 return 0;
750
751 while (iplace > 0) {
752 if (!doapr_outch(sbuffer, buffer, currlen, maxlen, iconvert[--iplace]))
753 return 0;
754 }
755
756 /*
757 * Decimal point. This should probably use locale to find the correct
758 * char to print out.
759 */
760 if (max > 0 || (flags & DP_F_NUM)) {
761 if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '.'))
762 return 0;
763
764 while (fplace > 0) {
765 if (!doapr_outch(sbuffer, buffer, currlen, maxlen,
766 fconvert[--fplace]))
767 return 0;
768 }
769 }
770 while (zpadlen > 0) {
771 if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '0'))
772 return 0;
773 --zpadlen;
774 }
775 if (realstyle == E_FORMAT) {
776 char ech;
777
778 if ((flags & DP_F_UP) == 0)
779 ech = 'e';
780 else
781 ech = 'E';
782 if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ech))
783 return 0;
784 if (exp < 0) {
785 if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '-'))
786 return 0;
787 } else {
788 if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '+'))
789 return 0;
790 }
791 while (eplace > 0) {
792 if (!doapr_outch(sbuffer, buffer, currlen, maxlen,
793 econvert[--eplace]))
794 return 0;
795 }
796 }
797
798 while (padlen < 0) {
799 if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' '))
800 return 0;
801 ++padlen;
802 }
803 return 1;
804}
805
806#define BUFFER_INC 1024
807
808static int
809doapr_outch(char **sbuffer,
810 char **buffer, size_t *currlen, size_t *maxlen, int c)
811{
812 /* If we haven't at least one buffer, someone has done a big booboo */
813 if (!ossl_assert(*sbuffer != NULL || buffer != NULL))
814 return 0;
815
816 /* |currlen| must always be <= |*maxlen| */
817 if (!ossl_assert(*currlen <= *maxlen))
818 return 0;
819
820 if (buffer && *currlen == *maxlen) {
821 if (*maxlen > INT_MAX - BUFFER_INC)
822 return 0;
823
824 *maxlen += BUFFER_INC;
825 if (*buffer == NULL) {
826 if ((*buffer = OPENSSL_malloc(*maxlen)) == NULL) {
827 BIOerr(BIO_F_DOAPR_OUTCH, ERR_R_MALLOC_FAILURE);
828 return 0;
829 }
830 if (*currlen > 0) {
831 if (!ossl_assert(*sbuffer != NULL))
832 return 0;
833 memcpy(*buffer, *sbuffer, *currlen);
834 }
835 *sbuffer = NULL;
836 } else {
837 char *tmpbuf;
838 tmpbuf = OPENSSL_realloc(*buffer, *maxlen);
839 if (tmpbuf == NULL)
840 return 0;
841 *buffer = tmpbuf;
842 }
843 }
844
845 if (*currlen < *maxlen) {
846 if (*sbuffer)
847 (*sbuffer)[(*currlen)++] = (char)c;
848 else
849 (*buffer)[(*currlen)++] = (char)c;
850 }
851
852 return 1;
853}
854
855/***************************************************************************/
856
857int BIO_printf(BIO *bio, const char *format, ...)
858{
859 va_list args;
860 int ret;
861
862 va_start(args, format);
863
864 ret = BIO_vprintf(bio, format, args);
865
866 va_end(args);
867 return ret;
868}
869
870int BIO_vprintf(BIO *bio, const char *format, va_list args)
871{
872 int ret;
873 size_t retlen;
874 char hugebuf[1024 * 2]; /* Was previously 10k, which is unreasonable
875 * in small-stack environments, like threads
876 * or DOS programs. */
877 char *hugebufp = hugebuf;
878 size_t hugebufsize = sizeof(hugebuf);
879 char *dynbuf = NULL;
880 int ignored;
881
882 dynbuf = NULL;
883 if (!_dopr(&hugebufp, &dynbuf, &hugebufsize, &retlen, &ignored, format,
884 args)) {
885 OPENSSL_free(dynbuf);
886 return -1;
887 }
888 if (dynbuf) {
889 ret = BIO_write(bio, dynbuf, (int)retlen);
890 OPENSSL_free(dynbuf);
891 } else {
892 ret = BIO_write(bio, hugebuf, (int)retlen);
893 }
894 return ret;
895}
896
897/*
898 * As snprintf is not available everywhere, we provide our own
899 * implementation. This function has nothing to do with BIOs, but it's
900 * closely related to BIO_printf, and we need *some* name prefix ... (XXX the
901 * function should be renamed, but to what?)
902 */
903int BIO_snprintf(char *buf, size_t n, const char *format, ...)
904{
905 va_list args;
906 int ret;
907
908 va_start(args, format);
909
910 ret = BIO_vsnprintf(buf, n, format, args);
911
912 va_end(args);
913 return ret;
914}
915
916int BIO_vsnprintf(char *buf, size_t n, const char *format, va_list args)
917{
918 size_t retlen;
919 int truncated;
920
921 if (!_dopr(&buf, NULL, &n, &retlen, &truncated, format, args))
922 return -1;
923
924 if (truncated)
925 /*
926 * In case of truncation, return -1 like traditional snprintf.
927 * (Current drafts for ISO/IEC 9899 say snprintf should return the
928 * number of characters that would have been written, had the buffer
929 * been large enough.)
930 */
931 return -1;
932 else
933 return (retlen <= INT_MAX) ? (int)retlen : -1;
934}
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette