sizeof() updated to cover coding style
[openssl.git] / crypto / bio / b_print.c
1 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
2  * All rights reserved.
3  *
4  * This package is an SSL implementation written
5  * by Eric Young (eay@cryptsoft.com).
6  * The implementation was written so as to conform with Netscapes SSL.
7  *
8  * This library is free for commercial and non-commercial use as long as
9  * the following conditions are aheared to.  The following conditions
10  * apply to all code found in this distribution, be it the RC4, RSA,
11  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
12  * included with this distribution is covered by the same copyright terms
13  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
14  *
15  * Copyright remains Eric Young's, and as such any Copyright notices in
16  * the code are not to be removed.
17  * If this package is used in a product, Eric Young should be given attribution
18  * as the author of the parts of the library used.
19  * This can be in the form of a textual message at program startup or
20  * in documentation (online or textual) provided with the package.
21  *
22  * Redistribution and use in source and binary forms, with or without
23  * modification, are permitted provided that the following conditions
24  * are met:
25  * 1. Redistributions of source code must retain the copyright
26  *    notice, this list of conditions and the following disclaimer.
27  * 2. Redistributions in binary form must reproduce the above copyright
28  *    notice, this list of conditions and the following disclaimer in the
29  *    documentation and/or other materials provided with the distribution.
30  * 3. All advertising materials mentioning features or use of this software
31  *    must display the following acknowledgement:
32  *    "This product includes cryptographic software written by
33  *     Eric Young (eay@cryptsoft.com)"
34  *    The word 'cryptographic' can be left out if the rouines from the library
35  *    being used are not cryptographic related :-).
36  * 4. If you include any Windows specific code (or a derivative thereof) from
37  *    the apps directory (application code) you must include an acknowledgement:
38  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
39  *
40  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
41  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
42  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
43  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
44  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
45  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
46  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
48  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
49  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
50  * SUCH DAMAGE.
51  *
52  * The licence and distribution terms for any publically available version or
53  * derivative of this code cannot be changed.  i.e. this code cannot simply be
54  * copied and put under another distribution licence
55  * [including the GNU Public Licence.]
56  */
57
58 /* disable assert() unless BIO_DEBUG has been defined */
59 #ifndef BIO_DEBUG
60 # ifndef NDEBUG
61 #  define NDEBUG
62 # endif
63 #endif
64
65 /*
66  * Stolen from tjh's ssl/ssl_trc.c stuff.
67  */
68
69 #include <stdio.h>
70 #include <string.h>
71 #include <ctype.h>
72 #include <assert.h>
73 #include <limits.h>
74 #include "internal/cryptlib.h"
75 #ifndef NO_SYS_TYPES_H
76 # include <sys/types.h>
77 #endif
78 #include <openssl/bn.h>         /* To get BN_LLONG properly defined */
79 #include <openssl/bio.h>
80
81 #if defined(BN_LLONG) || defined(SIXTY_FOUR_BIT)
82 # ifndef HAVE_LONG_LONG
83 #  define HAVE_LONG_LONG 1
84 # endif
85 #endif
86
87 /***************************************************************************/
88
89 /*
90  * Copyright Patrick Powell 1995
91  * This code is based on code written by Patrick Powell <papowell@astart.com>
92  * It may be used for any purpose as long as this notice remains intact
93  * on all source code distributions.
94  */
95
96 /*-
97  * This code contains numerious changes and enhancements which were
98  * made by lots of contributors over the last years to Patrick Powell's
99  * original code:
100  *
101  * o Patrick Powell <papowell@astart.com>      (1995)
102  * o Brandon Long <blong@fiction.net>          (1996, for Mutt)
103  * o Thomas Roessler <roessler@guug.de>        (1998, for Mutt)
104  * o Michael Elkins <me@cs.hmc.edu>            (1998, for Mutt)
105  * o Andrew Tridgell <tridge@samba.org>        (1998, for Samba)
106  * o Luke Mewburn <lukem@netbsd.org>           (1999, for LukemFTP)
107  * o Ralf S. Engelschall <rse@engelschall.com> (1999, for Pth)
108  * o ...                                       (for OpenSSL)
109  */
110
111 #ifdef HAVE_LONG_DOUBLE
112 # define LDOUBLE long double
113 #else
114 # define LDOUBLE double
115 #endif
116
117 #ifdef HAVE_LONG_LONG
118 # if defined(_WIN32) && !defined(__GNUC__)
119 #  define LLONG __int64
120 # else
121 #  define LLONG long long
122 # endif
123 #else
124 # define LLONG long
125 #endif
126
127 static int fmtstr(char **, char **, size_t *, size_t *,
128                   const char *, int, int, int);
129 static int fmtint(char **, char **, size_t *, size_t *,
130                   LLONG, int, int, int, int);
131 static int fmtfp(char **, char **, size_t *, size_t *,
132                  LDOUBLE, int, int, int);
133 static int doapr_outch(char **, char **, size_t *, size_t *, int);
134 static int _dopr(char **sbuffer, char **buffer,
135                  size_t *maxlen, size_t *retlen, int *truncated,
136                  const char *format, va_list args);
137
138 /* format read states */
139 #define DP_S_DEFAULT    0
140 #define DP_S_FLAGS      1
141 #define DP_S_MIN        2
142 #define DP_S_DOT        3
143 #define DP_S_MAX        4
144 #define DP_S_MOD        5
145 #define DP_S_CONV       6
146 #define DP_S_DONE       7
147
148 /* format flags - Bits */
149 #define DP_F_MINUS      (1 << 0)
150 #define DP_F_PLUS       (1 << 1)
151 #define DP_F_SPACE      (1 << 2)
152 #define DP_F_NUM        (1 << 3)
153 #define DP_F_ZERO       (1 << 4)
154 #define DP_F_UP         (1 << 5)
155 #define DP_F_UNSIGNED   (1 << 6)
156
157 /* conversion flags */
158 #define DP_C_SHORT      1
159 #define DP_C_LONG       2
160 #define DP_C_LDOUBLE    3
161 #define DP_C_LLONG      4
162
163 /* some handy macros */
164 #define char_to_int(p) (p - '0')
165 #define OSSL_MAX(p,q) ((p >= q) ? p : q)
166
167 static int
168 _dopr(char **sbuffer,
169       char **buffer,
170       size_t *maxlen,
171       size_t *retlen, int *truncated, const char *format, va_list args)
172 {
173     char ch;
174     LLONG value;
175     LDOUBLE fvalue;
176     char *strvalue;
177     int min;
178     int max;
179     int state;
180     int flags;
181     int cflags;
182     size_t currlen;
183
184     state = DP_S_DEFAULT;
185     flags = currlen = cflags = min = 0;
186     max = -1;
187     ch = *format++;
188
189     while (state != DP_S_DONE) {
190         if (ch == '\0' || (buffer == NULL && currlen >= *maxlen))
191             state = DP_S_DONE;
192
193         switch (state) {
194         case DP_S_DEFAULT:
195             if (ch == '%')
196                 state = DP_S_FLAGS;
197             else
198                 if(!doapr_outch(sbuffer, buffer, &currlen, maxlen, ch))
199                     return 0;
200             ch = *format++;
201             break;
202         case DP_S_FLAGS:
203             switch (ch) {
204             case '-':
205                 flags |= DP_F_MINUS;
206                 ch = *format++;
207                 break;
208             case '+':
209                 flags |= DP_F_PLUS;
210                 ch = *format++;
211                 break;
212             case ' ':
213                 flags |= DP_F_SPACE;
214                 ch = *format++;
215                 break;
216             case '#':
217                 flags |= DP_F_NUM;
218                 ch = *format++;
219                 break;
220             case '0':
221                 flags |= DP_F_ZERO;
222                 ch = *format++;
223                 break;
224             default:
225                 state = DP_S_MIN;
226                 break;
227             }
228             break;
229         case DP_S_MIN:
230             if (isdigit((unsigned char)ch)) {
231                 min = 10 * min + char_to_int(ch);
232                 ch = *format++;
233             } else if (ch == '*') {
234                 min = va_arg(args, int);
235                 ch = *format++;
236                 state = DP_S_DOT;
237             } else
238                 state = DP_S_DOT;
239             break;
240         case DP_S_DOT:
241             if (ch == '.') {
242                 state = DP_S_MAX;
243                 ch = *format++;
244             } else
245                 state = DP_S_MOD;
246             break;
247         case DP_S_MAX:
248             if (isdigit((unsigned char)ch)) {
249                 if (max < 0)
250                     max = 0;
251                 max = 10 * max + char_to_int(ch);
252                 ch = *format++;
253             } else if (ch == '*') {
254                 max = va_arg(args, int);
255                 ch = *format++;
256                 state = DP_S_MOD;
257             } else
258                 state = DP_S_MOD;
259             break;
260         case DP_S_MOD:
261             switch (ch) {
262             case 'h':
263                 cflags = DP_C_SHORT;
264                 ch = *format++;
265                 break;
266             case 'l':
267                 if (*format == 'l') {
268                     cflags = DP_C_LLONG;
269                     format++;
270                 } else
271                     cflags = DP_C_LONG;
272                 ch = *format++;
273                 break;
274             case 'q':
275                 cflags = DP_C_LLONG;
276                 ch = *format++;
277                 break;
278             case 'L':
279                 cflags = DP_C_LDOUBLE;
280                 ch = *format++;
281                 break;
282             default:
283                 break;
284             }
285             state = DP_S_CONV;
286             break;
287         case DP_S_CONV:
288             switch (ch) {
289             case 'd':
290             case 'i':
291                 switch (cflags) {
292                 case DP_C_SHORT:
293                     value = (short int)va_arg(args, int);
294                     break;
295                 case DP_C_LONG:
296                     value = va_arg(args, long int);
297                     break;
298                 case DP_C_LLONG:
299                     value = va_arg(args, LLONG);
300                     break;
301                 default:
302                     value = va_arg(args, int);
303                     break;
304                 }
305                 if (!fmtint(sbuffer, buffer, &currlen, maxlen, value, 10, min,
306                             max, flags))
307                     return 0;
308                 break;
309             case 'X':
310                 flags |= DP_F_UP;
311                 /* FALLTHROUGH */
312             case 'x':
313             case 'o':
314             case 'u':
315                 flags |= DP_F_UNSIGNED;
316                 switch (cflags) {
317                 case DP_C_SHORT:
318                     value = (unsigned short int)va_arg(args, unsigned int);
319                     break;
320                 case DP_C_LONG:
321                     value = (LLONG) va_arg(args, unsigned long int);
322                     break;
323                 case DP_C_LLONG:
324                     value = va_arg(args, unsigned LLONG);
325                     break;
326                 default:
327                     value = (LLONG) va_arg(args, unsigned int);
328                     break;
329                 }
330                 if (!fmtint(sbuffer, buffer, &currlen, maxlen, value,
331                             ch == 'o' ? 8 : (ch == 'u' ? 10 : 16),
332                             min, max, flags))
333                     return 0;
334                 break;
335             case 'f':
336                 if (cflags == DP_C_LDOUBLE)
337                     fvalue = va_arg(args, LDOUBLE);
338                 else
339                     fvalue = va_arg(args, double);
340                 if (!fmtfp(sbuffer, buffer, &currlen, maxlen, fvalue, min, max,
341                            flags))
342                     return 0;
343                 break;
344             case 'E':
345                 flags |= DP_F_UP;
346             case 'e':
347                 if (cflags == DP_C_LDOUBLE)
348                     fvalue = va_arg(args, LDOUBLE);
349                 else
350                     fvalue = va_arg(args, double);
351                 break;
352             case 'G':
353                 flags |= DP_F_UP;
354             case 'g':
355                 if (cflags == DP_C_LDOUBLE)
356                     fvalue = va_arg(args, LDOUBLE);
357                 else
358                     fvalue = va_arg(args, double);
359                 break;
360             case 'c':
361                 if(!doapr_outch(sbuffer, buffer, &currlen, maxlen,
362                             va_arg(args, int)))
363                     return 0;
364                 break;
365             case 's':
366                 strvalue = va_arg(args, char *);
367                 if (max < 0) {
368                     if (buffer)
369                         max = INT_MAX;
370                     else
371                         max = *maxlen;
372                 }
373                 if (!fmtstr(sbuffer, buffer, &currlen, maxlen, strvalue,
374                             flags, min, max))
375                     return 0;
376                 break;
377             case 'p':
378                 value = (size_t)va_arg(args, void *);
379                 if (!fmtint(sbuffer, buffer, &currlen, maxlen,
380                             value, 16, min, max, flags | DP_F_NUM))
381                     return 0;
382                 break;
383             case 'n':          /* XXX */
384                 if (cflags == DP_C_SHORT) {
385                     short int *num;
386                     num = va_arg(args, short int *);
387                     *num = currlen;
388                 } else if (cflags == DP_C_LONG) { /* XXX */
389                     long int *num;
390                     num = va_arg(args, long int *);
391                     *num = (long int)currlen;
392                 } else if (cflags == DP_C_LLONG) { /* XXX */
393                     LLONG *num;
394                     num = va_arg(args, LLONG *);
395                     *num = (LLONG) currlen;
396                 } else {
397                     int *num;
398                     num = va_arg(args, int *);
399                     *num = currlen;
400                 }
401                 break;
402             case '%':
403                 if(!doapr_outch(sbuffer, buffer, &currlen, maxlen, ch))
404                     return 0;
405                 break;
406             case 'w':
407                 /* not supported yet, treat as next char */
408                 ch = *format++;
409                 break;
410             default:
411                 /* unknown, skip */
412                 break;
413             }
414             ch = *format++;
415             state = DP_S_DEFAULT;
416             flags = cflags = min = 0;
417             max = -1;
418             break;
419         case DP_S_DONE:
420             break;
421         default:
422             break;
423         }
424     }
425     *truncated = (currlen > *maxlen - 1);
426     if (*truncated)
427         currlen = *maxlen - 1;
428     if(!doapr_outch(sbuffer, buffer, &currlen, maxlen, '\0'))
429         return 0;
430     *retlen = currlen - 1;
431     return 1;
432 }
433
434 static int
435 fmtstr(char **sbuffer,
436        char **buffer,
437        size_t *currlen,
438        size_t *maxlen, const char *value, int flags, int min, int max)
439 {
440     int padlen;
441     size_t strln;
442     int cnt = 0;
443
444     if (value == 0)
445         value = "<NULL>";
446
447     strln = strlen(value);
448     if (strln > INT_MAX)
449         strln = INT_MAX;
450
451     padlen = min - strln;
452     if (min < 0 || padlen < 0)
453         padlen = 0;
454     if (flags & DP_F_MINUS)
455         padlen = -padlen;
456
457     while ((padlen > 0) && (cnt < max)) {
458         if(!doapr_outch(sbuffer, buffer, currlen, maxlen, ' '))
459             return 0;
460         --padlen;
461         ++cnt;
462     }
463     while (*value && (cnt < max)) {
464         if(!doapr_outch(sbuffer, buffer, currlen, maxlen, *value++))
465             return 0;
466         ++cnt;
467     }
468     while ((padlen < 0) && (cnt < max)) {
469         if(!doapr_outch(sbuffer, buffer, currlen, maxlen, ' '))
470             return 0;
471         ++padlen;
472         ++cnt;
473     }
474     return 1;
475 }
476
477 static int
478 fmtint(char **sbuffer,
479        char **buffer,
480        size_t *currlen,
481        size_t *maxlen, LLONG value, int base, int min, int max, int flags)
482 {
483     int signvalue = 0;
484     const char *prefix = "";
485     unsigned LLONG uvalue;
486     char convert[DECIMAL_SIZE(value) + 3];
487     int place = 0;
488     int spadlen = 0;
489     int zpadlen = 0;
490     int caps = 0;
491
492     if (max < 0)
493         max = 0;
494     uvalue = value;
495     if (!(flags & DP_F_UNSIGNED)) {
496         if (value < 0) {
497             signvalue = '-';
498             uvalue = -value;
499         } else if (flags & DP_F_PLUS)
500             signvalue = '+';
501         else if (flags & DP_F_SPACE)
502             signvalue = ' ';
503     }
504     if (flags & DP_F_NUM) {
505         if (base == 8)
506             prefix = "0";
507         if (base == 16)
508             prefix = "0x";
509     }
510     if (flags & DP_F_UP)
511         caps = 1;
512     do {
513         convert[place++] = (caps ? "0123456789ABCDEF" : "0123456789abcdef")
514             [uvalue % (unsigned)base];
515         uvalue = (uvalue / (unsigned)base);
516     } while (uvalue && (place < (int)sizeof(convert)));
517     if (place == sizeof(convert))
518         place--;
519     convert[place] = 0;
520
521     zpadlen = max - place;
522     spadlen =
523         min - OSSL_MAX(max, place) - (signvalue ? 1 : 0) - strlen(prefix);
524     if (zpadlen < 0)
525         zpadlen = 0;
526     if (spadlen < 0)
527         spadlen = 0;
528     if (flags & DP_F_ZERO) {
529         zpadlen = OSSL_MAX(zpadlen, spadlen);
530         spadlen = 0;
531     }
532     if (flags & DP_F_MINUS)
533         spadlen = -spadlen;
534
535     /* spaces */
536     while (spadlen > 0) {
537         if(!doapr_outch(sbuffer, buffer, currlen, maxlen, ' '))
538             return 0;
539         --spadlen;
540     }
541
542     /* sign */
543     if (signvalue)
544         if(!doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue))
545             return 0;
546
547     /* prefix */
548     while (*prefix) {
549         if(!doapr_outch(sbuffer, buffer, currlen, maxlen, *prefix))
550             return 0;
551         prefix++;
552     }
553
554     /* zeros */
555     if (zpadlen > 0) {
556         while (zpadlen > 0) {
557             if(!doapr_outch(sbuffer, buffer, currlen, maxlen, '0'))
558                 return 0;
559             --zpadlen;
560         }
561     }
562     /* digits */
563     while (place > 0) {
564         if (!doapr_outch(sbuffer, buffer, currlen, maxlen, convert[--place]))
565             return 0;
566     }
567
568     /* left justified spaces */
569     while (spadlen < 0) {
570         if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' '))
571             return 0;
572         ++spadlen;
573     }
574     return 1;
575 }
576
577 static LDOUBLE abs_val(LDOUBLE value)
578 {
579     LDOUBLE result = value;
580     if (value < 0)
581         result = -value;
582     return result;
583 }
584
585 static LDOUBLE pow_10(int in_exp)
586 {
587     LDOUBLE result = 1;
588     while (in_exp) {
589         result *= 10;
590         in_exp--;
591     }
592     return result;
593 }
594
595 static long roundv(LDOUBLE value)
596 {
597     long intpart;
598     intpart = (long)value;
599     value = value - intpart;
600     if (value >= 0.5)
601         intpart++;
602     return intpart;
603 }
604
605 static int
606 fmtfp(char **sbuffer,
607       char **buffer,
608       size_t *currlen,
609       size_t *maxlen, LDOUBLE fvalue, int min, int max, int flags)
610 {
611     int signvalue = 0;
612     LDOUBLE ufvalue;
613     char iconvert[20];
614     char fconvert[20];
615     int iplace = 0;
616     int fplace = 0;
617     int padlen = 0;
618     int zpadlen = 0;
619     long intpart;
620     long fracpart;
621     long max10;
622
623     if (max < 0)
624         max = 6;
625     ufvalue = abs_val(fvalue);
626     if (fvalue < 0)
627         signvalue = '-';
628     else if (flags & DP_F_PLUS)
629         signvalue = '+';
630     else if (flags & DP_F_SPACE)
631         signvalue = ' ';
632
633     intpart = (long)ufvalue;
634
635     /*
636      * sorry, we only support 9 digits past the decimal because of our
637      * conversion method
638      */
639     if (max > 9)
640         max = 9;
641
642     /*
643      * we "cheat" by converting the fractional part to integer by multiplying
644      * by a factor of 10
645      */
646     max10 = roundv(pow_10(max));
647     fracpart = roundv(pow_10(max) * (ufvalue - intpart));
648
649     if (fracpart >= max10) {
650         intpart++;
651         fracpart -= max10;
652     }
653
654     /* convert integer part */
655     do {
656         iconvert[iplace++] = "0123456789"[intpart % 10];
657         intpart = (intpart / 10);
658     } while (intpart && (iplace < (int)sizeof(iconvert)));
659     if (iplace == sizeof iconvert)
660         iplace--;
661     iconvert[iplace] = 0;
662
663     /* convert fractional part */
664     do {
665         fconvert[fplace++] = "0123456789"[fracpart % 10];
666         fracpart = (fracpart / 10);
667     } while (fplace < max);
668     if (fplace == sizeof fconvert)
669         fplace--;
670     fconvert[fplace] = 0;
671
672     /* -1 for decimal point, another -1 if we are printing a sign */
673     padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0);
674     zpadlen = max - fplace;
675     if (zpadlen < 0)
676         zpadlen = 0;
677     if (padlen < 0)
678         padlen = 0;
679     if (flags & DP_F_MINUS)
680         padlen = -padlen;
681
682     if ((flags & DP_F_ZERO) && (padlen > 0)) {
683         if (signvalue) {
684             if (!doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue))
685                 return 0;
686             --padlen;
687             signvalue = 0;
688         }
689         while (padlen > 0) {
690             if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '0'))
691                 return 0;
692             --padlen;
693         }
694     }
695     while (padlen > 0) {
696         if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' '))
697             return 0;
698         --padlen;
699     }
700     if (signvalue && !doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue))
701         return 0;
702
703     while (iplace > 0) {
704         if (!doapr_outch(sbuffer, buffer, currlen, maxlen, iconvert[--iplace]))
705             return 0;
706     }
707
708     /*
709      * Decimal point. This should probably use locale to find the correct
710      * char to print out.
711      */
712     if (max > 0 || (flags & DP_F_NUM)) {
713         if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '.'))
714             return 0;
715
716         while (fplace > 0) {
717             if(!doapr_outch(sbuffer, buffer, currlen, maxlen,
718                             fconvert[--fplace]))
719                 return 0;
720         }
721     }
722     while (zpadlen > 0) {
723         if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '0'))
724             return 0;
725         --zpadlen;
726     }
727
728     while (padlen < 0) {
729         if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' '))
730             return 0;
731         ++padlen;
732     }
733     return 1;
734 }
735
736 #define BUFFER_INC  1024
737
738 static int
739 doapr_outch(char **sbuffer,
740             char **buffer, size_t *currlen, size_t *maxlen, int c)
741 {
742     /* If we haven't at least one buffer, someone has doe a big booboo */
743     assert(*sbuffer != NULL || buffer != NULL);
744
745     /* |currlen| must always be <= |*maxlen| */
746     assert(*currlen <= *maxlen);
747
748     if (buffer && *currlen == *maxlen) {
749         if (*maxlen > INT_MAX - BUFFER_INC)
750             return 0;
751
752         *maxlen += BUFFER_INC;
753         if (*buffer == NULL) {
754             *buffer = OPENSSL_malloc(*maxlen);
755             if (*buffer == NULL)
756                 return 0;
757             if (*currlen > 0) {
758                 assert(*sbuffer != NULL);
759                 memcpy(*buffer, *sbuffer, *currlen);
760             }
761             *sbuffer = NULL;
762         } else {
763             char *tmpbuf;
764             tmpbuf = OPENSSL_realloc(*buffer, *maxlen);
765             if (tmpbuf == NULL)
766                 return 0;
767             *buffer = tmpbuf;
768         }
769     }
770
771     if (*currlen < *maxlen) {
772         if (*sbuffer)
773             (*sbuffer)[(*currlen)++] = (char)c;
774         else
775             (*buffer)[(*currlen)++] = (char)c;
776     }
777
778     return 1;
779 }
780
781 /***************************************************************************/
782
783 int BIO_printf(BIO *bio, const char *format, ...)
784 {
785     va_list args;
786     int ret;
787
788     va_start(args, format);
789
790     ret = BIO_vprintf(bio, format, args);
791
792     va_end(args);
793     return (ret);
794 }
795
796 int BIO_vprintf(BIO *bio, const char *format, va_list args)
797 {
798     int ret;
799     size_t retlen;
800     char hugebuf[1024 * 2];     /* Was previously 10k, which is unreasonable
801                                  * in small-stack environments, like threads
802                                  * or DOS programs. */
803     char *hugebufp = hugebuf;
804     size_t hugebufsize = sizeof(hugebuf);
805     char *dynbuf = NULL;
806     int ignored;
807
808     dynbuf = NULL;
809     if (!_dopr(&hugebufp, &dynbuf, &hugebufsize, &retlen, &ignored, format,
810                 args)) {
811         OPENSSL_free(dynbuf);
812         return -1;
813     }
814     if (dynbuf) {
815         ret = BIO_write(bio, dynbuf, (int)retlen);
816         OPENSSL_free(dynbuf);
817     } else {
818         ret = BIO_write(bio, hugebuf, (int)retlen);
819     }
820     return (ret);
821 }
822
823 /*
824  * As snprintf is not available everywhere, we provide our own
825  * implementation. This function has nothing to do with BIOs, but it's
826  * closely related to BIO_printf, and we need *some* name prefix ... (XXX the
827  * function should be renamed, but to what?)
828  */
829 int BIO_snprintf(char *buf, size_t n, const char *format, ...)
830 {
831     va_list args;
832     int ret;
833
834     va_start(args, format);
835
836     ret = BIO_vsnprintf(buf, n, format, args);
837
838     va_end(args);
839     return (ret);
840 }
841
842 int BIO_vsnprintf(char *buf, size_t n, const char *format, va_list args)
843 {
844     size_t retlen;
845     int truncated;
846
847     if(!_dopr(&buf, NULL, &n, &retlen, &truncated, format, args))
848         return -1;
849
850     if (truncated)
851         /*
852          * In case of truncation, return -1 like traditional snprintf.
853          * (Current drafts for ISO/IEC 9899 say snprintf should return the
854          * number of characters that would have been written, had the buffer
855          * been large enough.)
856          */
857         return -1;
858     else
859         return (retlen <= INT_MAX) ? (int)retlen : -1;
860 }