VirtualBox

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

Last change on this file since 91772 was 91772, checked in by vboxsync, 3 years ago

openssl-1.1.1l: Applied and adjusted our OpenSSL changes to 1.1.1l. bugref:10126

File size: 25.8 KB
Line 
1/*
2 * Copyright 1995-2020 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 /*
643 * By subtracting 65535 (2^16-1) we cancel the low order 15 bits
644 * of ULONG_MAX to avoid using imprecise floating point values.
645 */
646 if (ufvalue >= (double)(ULONG_MAX - 65535) + 65536.0) {
647 /* Number too big */
648 return 0;
649 }
650 intpart = (unsigned long)ufvalue;
651
652 /*
653 * sorry, we only support 9 digits past the decimal because of our
654 * conversion method
655 */
656 if (max > 9)
657 max = 9;
658
659 /*
660 * we "cheat" by converting the fractional part to integer by multiplying
661 * by a factor of 10
662 */
663 max10 = roundv(pow_10(max));
664 fracpart = roundv(pow_10(max) * (ufvalue - intpart));
665
666 if (fracpart >= max10) {
667 intpart++;
668 fracpart -= max10;
669 }
670
671 /* convert integer part */
672 do {
673 iconvert[iplace++] = "0123456789"[intpart % 10];
674 intpart = (intpart / 10);
675 } while (intpart && (iplace < (int)sizeof(iconvert)));
676 if (iplace == sizeof(iconvert))
677 iplace--;
678 iconvert[iplace] = 0;
679
680 /* convert fractional part */
681 while (fplace < max) {
682 if (style == G_FORMAT && fplace == 0 && (fracpart % 10) == 0) {
683 /* We strip trailing zeros in G_FORMAT */
684 max--;
685 fracpart = fracpart / 10;
686 if (fplace < max)
687 continue;
688 break;
689 }
690 fconvert[fplace++] = "0123456789"[fracpart % 10];
691 fracpart = (fracpart / 10);
692 }
693
694 if (fplace == sizeof(fconvert))
695 fplace--;
696 fconvert[fplace] = 0;
697
698 /* convert exponent part */
699 if (realstyle == E_FORMAT) {
700 int tmpexp;
701 if (exp < 0)
702 tmpexp = -exp;
703 else
704 tmpexp = exp;
705
706 do {
707 econvert[eplace++] = "0123456789"[tmpexp % 10];
708 tmpexp = (tmpexp / 10);
709 } while (tmpexp > 0 && eplace < (int)sizeof(econvert));
710 /* Exponent is huge!! Too big to print */
711 if (tmpexp > 0)
712 return 0;
713 /* Add a leading 0 for single digit exponents */
714 if (eplace == 1)
715 econvert[eplace++] = '0';
716 }
717
718 /*
719 * -1 for decimal point (if we have one, i.e. max > 0),
720 * another -1 if we are printing a sign
721 */
722 padlen = min - iplace - max - (max > 0 ? 1 : 0) - ((signvalue) ? 1 : 0);
723 /* Take some off for exponent prefix "+e" and exponent */
724 if (realstyle == E_FORMAT)
725 padlen -= 2 + eplace;
726 zpadlen = max - fplace;
727 if (zpadlen < 0)
728 zpadlen = 0;
729 if (padlen < 0)
730 padlen = 0;
731 if (flags & DP_F_MINUS)
732 padlen = -padlen;
733
734 if ((flags & DP_F_ZERO) && (padlen > 0)) {
735 if (signvalue) {
736 if (!doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue))
737 return 0;
738 --padlen;
739 signvalue = 0;
740 }
741 while (padlen > 0) {
742 if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '0'))
743 return 0;
744 --padlen;
745 }
746 }
747 while (padlen > 0) {
748 if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' '))
749 return 0;
750 --padlen;
751 }
752 if (signvalue && !doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue))
753 return 0;
754
755 while (iplace > 0) {
756 if (!doapr_outch(sbuffer, buffer, currlen, maxlen, iconvert[--iplace]))
757 return 0;
758 }
759
760 /*
761 * Decimal point. This should probably use locale to find the correct
762 * char to print out.
763 */
764 if (max > 0 || (flags & DP_F_NUM)) {
765 if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '.'))
766 return 0;
767
768 while (fplace > 0) {
769 if (!doapr_outch(sbuffer, buffer, currlen, maxlen,
770 fconvert[--fplace]))
771 return 0;
772 }
773 }
774 while (zpadlen > 0) {
775 if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '0'))
776 return 0;
777 --zpadlen;
778 }
779 if (realstyle == E_FORMAT) {
780 char ech;
781
782 if ((flags & DP_F_UP) == 0)
783 ech = 'e';
784 else
785 ech = 'E';
786 if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ech))
787 return 0;
788 if (exp < 0) {
789 if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '-'))
790 return 0;
791 } else {
792 if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '+'))
793 return 0;
794 }
795 while (eplace > 0) {
796 if (!doapr_outch(sbuffer, buffer, currlen, maxlen,
797 econvert[--eplace]))
798 return 0;
799 }
800 }
801
802 while (padlen < 0) {
803 if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' '))
804 return 0;
805 ++padlen;
806 }
807 return 1;
808}
809
810#define BUFFER_INC 1024
811
812static int
813doapr_outch(char **sbuffer,
814 char **buffer, size_t *currlen, size_t *maxlen, int c)
815{
816 /* If we haven't at least one buffer, someone has done a big booboo */
817 if (!ossl_assert(*sbuffer != NULL || buffer != NULL))
818 return 0;
819
820 /* |currlen| must always be <= |*maxlen| */
821 if (!ossl_assert(*currlen <= *maxlen))
822 return 0;
823
824 if (buffer && *currlen == *maxlen) {
825 if (*maxlen > INT_MAX - BUFFER_INC)
826 return 0;
827
828 *maxlen += BUFFER_INC;
829 if (*buffer == NULL) {
830 if ((*buffer = OPENSSL_malloc(*maxlen)) == NULL) {
831 BIOerr(BIO_F_DOAPR_OUTCH, ERR_R_MALLOC_FAILURE);
832 return 0;
833 }
834 if (*currlen > 0) {
835 if (!ossl_assert(*sbuffer != NULL))
836 return 0;
837 memcpy(*buffer, *sbuffer, *currlen);
838 }
839 *sbuffer = NULL;
840 } else {
841 char *tmpbuf;
842 tmpbuf = OPENSSL_realloc(*buffer, *maxlen);
843 if (tmpbuf == NULL)
844 return 0;
845 *buffer = tmpbuf;
846 }
847 }
848
849 if (*currlen < *maxlen) {
850 if (*sbuffer)
851 (*sbuffer)[(*currlen)++] = (char)c;
852 else
853 (*buffer)[(*currlen)++] = (char)c;
854 }
855
856 return 1;
857}
858
859/***************************************************************************/
860
861int BIO_printf(BIO *bio, const char *format, ...)
862{
863 va_list args;
864 int ret;
865
866 va_start(args, format);
867
868 ret = BIO_vprintf(bio, format, args);
869
870 va_end(args);
871 return ret;
872}
873
874int BIO_vprintf(BIO *bio, const char *format, va_list args)
875{
876 int ret;
877 size_t retlen;
878 char hugebuf[1024 * 2]; /* Was previously 10k, which is unreasonable
879 * in small-stack environments, like threads
880 * or DOS programs. */
881 char *hugebufp = hugebuf;
882 size_t hugebufsize = sizeof(hugebuf);
883 char *dynbuf = NULL;
884 int ignored;
885
886 dynbuf = NULL;
887 if (!_dopr(&hugebufp, &dynbuf, &hugebufsize, &retlen, &ignored, format,
888 args)) {
889 OPENSSL_free(dynbuf);
890 return -1;
891 }
892 if (dynbuf) {
893 ret = BIO_write(bio, dynbuf, (int)retlen);
894 OPENSSL_free(dynbuf);
895 } else {
896 ret = BIO_write(bio, hugebuf, (int)retlen);
897 }
898 return ret;
899}
900
901/*
902 * As snprintf is not available everywhere, we provide our own
903 * implementation. This function has nothing to do with BIOs, but it's
904 * closely related to BIO_printf, and we need *some* name prefix ... (XXX the
905 * function should be renamed, but to what?)
906 */
907int BIO_snprintf(char *buf, size_t n, const char *format, ...)
908{
909 va_list args;
910 int ret;
911
912 va_start(args, format);
913
914 ret = BIO_vsnprintf(buf, n, format, args);
915
916 va_end(args);
917 return ret;
918}
919
920int BIO_vsnprintf(char *buf, size_t n, const char *format, va_list args)
921{
922 size_t retlen;
923 int truncated;
924
925 if (!_dopr(&buf, NULL, &n, &retlen, &truncated, format, args))
926 return -1;
927
928 if (truncated)
929 /*
930 * In case of truncation, return -1 like traditional snprintf.
931 * (Current drafts for ISO/IEC 9899 say snprintf should return the
932 * number of characters that would have been written, had the buffer
933 * been large enough.)
934 */
935 return -1;
936 else
937 return (retlen <= INT_MAX) ? (int)retlen : -1;
938}
Note: See TracBrowser for help on using the repository browser.

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