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