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 __RCSID("$MirOS: src/lib/libssl/src/crypto/bio/b_print.c,v 1.2 2014/06/05 12:47:57 tg Exp $");
89 
90 /***************************************************************************/
91 
92 /*
93  * Copyright Patrick Powell 1995
94  * This code is based on code written by Patrick Powell <papowell@astart.com>
95  * It may be used for any purpose as long as this notice remains intact
96  * on all source code distributions.
97  */
98 
99 /*
100  * This code contains numerious changes and enhancements which were
101  * made by lots of contributors over the last years to Patrick Powell's
102  * original code:
103  *
104  * o Patrick Powell <papowell@astart.com>      (1995)
105  * o Brandon Long <blong@fiction.net>          (1996, for Mutt)
106  * o Thomas Roessler <roessler@guug.de>        (1998, for Mutt)
107  * o Michael Elkins <me@cs.hmc.edu>            (1998, for Mutt)
108  * o Andrew Tridgell <tridge@samba.org>        (1998, for Samba)
109  * o Luke Mewburn <lukem@netbsd.org>           (1999, for LukemFTP)
110  * o Ralf S. Engelschall <rse@engelschall.com> (1999, for Pth)
111  * o ...                                       (for OpenSSL)
112  */
113 
114 #ifdef HAVE_LONG_DOUBLE
115 #define LDOUBLE long double
116 #else
117 #define LDOUBLE double
118 #endif
119 
120 #if HAVE_LONG_LONG
121 # if defined(OPENSSL_SYS_WIN32) && !defined(__GNUC__)
122 # define LLONG __int64
123 # else
124 # define LLONG long long
125 # endif
126 #else
127 #define LLONG long
128 #endif
129 
130 static void fmtstr     (char **, char **, size_t *, size_t *,
131 			const char *, int, int, int);
132 static void fmtint     (char **, char **, size_t *, size_t *,
133 			LLONG, int, int, int, int);
134 static void fmtfp      (char **, char **, size_t *, size_t *,
135 			LDOUBLE, int, int, int);
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     LDOUBLE fvalue;
183     char *strvalue;
184     int min;
185     int max;
186     int state;
187     int flags;
188     int cflags;
189     size_t currlen;
190 
191     state = DP_S_DEFAULT;
192     flags = currlen = cflags = min = 0;
193     max = -1;
194     ch = *format++;
195 
196     while (state != DP_S_DONE) {
197         if (ch == '\0' || (buffer == NULL && currlen >= *maxlen))
198             state = DP_S_DONE;
199 
200         switch (state) {
201         case DP_S_DEFAULT:
202             if (ch == '%')
203                 state = DP_S_FLAGS;
204             else
205                 doapr_outch(sbuffer,buffer, &currlen, maxlen, ch);
206             ch = *format++;
207             break;
208         case DP_S_FLAGS:
209             switch (ch) {
210             case '-':
211                 flags |= DP_F_MINUS;
212                 ch = *format++;
213                 break;
214             case '+':
215                 flags |= DP_F_PLUS;
216                 ch = *format++;
217                 break;
218             case ' ':
219                 flags |= DP_F_SPACE;
220                 ch = *format++;
221                 break;
222             case '#':
223                 flags |= DP_F_NUM;
224                 ch = *format++;
225                 break;
226             case '0':
227                 flags |= DP_F_ZERO;
228                 ch = *format++;
229                 break;
230             default:
231                 state = DP_S_MIN;
232                 break;
233             }
234             break;
235         case DP_S_MIN:
236             if (isdigit((unsigned char)ch)) {
237                 min = 10 * min + char_to_int(ch);
238                 ch = *format++;
239             } else if (ch == '*') {
240                 min = va_arg(args, int);
241                 ch = *format++;
242                 state = DP_S_DOT;
243             } else
244                 state = DP_S_DOT;
245             break;
246         case DP_S_DOT:
247             if (ch == '.') {
248                 state = DP_S_MAX;
249                 ch = *format++;
250             } else
251                 state = DP_S_MOD;
252             break;
253         case DP_S_MAX:
254             if (isdigit((unsigned char)ch)) {
255                 if (max < 0)
256                     max = 0;
257                 max = 10 * max + char_to_int(ch);
258                 ch = *format++;
259             } else if (ch == '*') {
260                 max = va_arg(args, int);
261                 ch = *format++;
262                 state = DP_S_MOD;
263             } else
264                 state = DP_S_MOD;
265             break;
266         case DP_S_MOD:
267             switch (ch) {
268             case 'h':
269                 cflags = DP_C_SHORT;
270                 ch = *format++;
271                 break;
272             case 'l':
273                 if (*format == 'l') {
274                     cflags = DP_C_LLONG;
275                     format++;
276                 } else
277                     cflags = DP_C_LONG;
278                 ch = *format++;
279                 break;
280             case 'q':
281                 cflags = DP_C_LLONG;
282                 ch = *format++;
283                 break;
284             case 'L':
285                 cflags = DP_C_LDOUBLE;
286                 ch = *format++;
287                 break;
288             default:
289                 break;
290             }
291             state = DP_S_CONV;
292             break;
293         case DP_S_CONV:
294             switch (ch) {
295             case 'd':
296             case 'i':
297                 switch (cflags) {
298                 case DP_C_SHORT:
299                     value = (short int)va_arg(args, int);
300                     break;
301                 case DP_C_LONG:
302                     value = va_arg(args, long int);
303                     break;
304                 case DP_C_LLONG:
305                     value = va_arg(args, LLONG);
306                     break;
307                 default:
308                     value = va_arg(args, int);
309                     break;
310                 }
311                 fmtint(sbuffer, buffer, &currlen, maxlen,
312                        value, 10, min, max, flags);
313                 break;
314             case 'X':
315                 flags |= DP_F_UP;
316                 /* FALLTHROUGH */
317             case 'x':
318             case 'o':
319             case 'u':
320                 flags |= DP_F_UNSIGNED;
321                 switch (cflags) {
322                 case DP_C_SHORT:
323                     value = (unsigned short int)va_arg(args, unsigned int);
324                     break;
325                 case DP_C_LONG:
326                     value = (LLONG) va_arg(args,
327                         unsigned long int);
328                     break;
329                 case DP_C_LLONG:
330                     value = va_arg(args, unsigned LLONG);
331                     break;
332                 default:
333                     value = (LLONG) va_arg(args,
334                         unsigned int);
335                     break;
336                 }
337                 fmtint(sbuffer, buffer, &currlen, maxlen, value,
338                        ch == 'o' ? 8 : (ch == 'u' ? 10 : 16),
339                        min, max, flags);
340                 break;
341             case 'f':
342                 if (cflags == DP_C_LDOUBLE)
343                     fvalue = va_arg(args, LDOUBLE);
344                 else
345                     fvalue = va_arg(args, double);
346                 fmtfp(sbuffer, buffer, &currlen, maxlen,
347                       fvalue, min, max, flags);
348                 break;
349             case 'E':
350                 flags |= DP_F_UP;
351             case 'e':
352                 if (cflags == DP_C_LDOUBLE)
353                     fvalue = va_arg(args, LDOUBLE);
354                 else
355                     fvalue = va_arg(args, double);
356                 break;
357             case 'G':
358                 flags |= DP_F_UP;
359             case 'g':
360                 if (cflags == DP_C_LDOUBLE)
361                     fvalue = va_arg(args, LDOUBLE);
362                 else
363                     fvalue = va_arg(args, double);
364                 break;
365             case 'c':
366                 doapr_outch(sbuffer, buffer, &currlen, maxlen,
367                     va_arg(args, int));
368                 break;
369             case 's':
370                 strvalue = va_arg(args, char *);
371                 if (max < 0) {
372 		    if (buffer)
373 			max = INT_MAX;
374 		    else
375 			max = *maxlen;
376 		}
377                 fmtstr(sbuffer, buffer, &currlen, maxlen, strvalue,
378                        flags, min, max);
379                 break;
380             case 'p':
381                 value = (long)va_arg(args, void *);
382                 fmtint(sbuffer, buffer, &currlen, maxlen,
383                     value, 16, min, max, flags|DP_F_NUM);
384                 break;
385             case 'n': /* XXX */
386                 if (cflags == DP_C_SHORT) {
387                     short int *num;
388                     num = va_arg(args, short int *);
389                     *num = currlen;
390                 } else if (cflags == DP_C_LONG) { /* XXX */
391                     long int *num;
392                     num = va_arg(args, long int *);
393                     *num = (long int) currlen;
394                 } else if (cflags == DP_C_LLONG) { /* XXX */
395                     LLONG *num;
396                     num = va_arg(args, LLONG *);
397                     *num = (LLONG) currlen;
398                 } else {
399                     int    *num;
400                     num = va_arg(args, int *);
401                     *num = currlen;
402                 }
403                 break;
404             case '%':
405                 doapr_outch(sbuffer, buffer, &currlen, maxlen, ch);
406                 break;
407             case 'w':
408                 /* not supported yet, treat as next char */
409                 ch = *format++;
410                 break;
411             default:
412                 /* unknown, skip */
413                 break;
414             }
415             ch = *format++;
416             state = DP_S_DEFAULT;
417             flags = cflags = min = 0;
418             max = -1;
419             break;
420         case DP_S_DONE:
421             break;
422         default:
423             break;
424         }
425     }
426     *truncated = (currlen > *maxlen - 1);
427     if (*truncated)
428         currlen = *maxlen - 1;
429     doapr_outch(sbuffer, buffer, &currlen, maxlen, '\0');
430     *retlen = currlen - 1;
431     return;
432 }
433 
434 static void
fmtstr(char ** sbuffer,char ** buffer,size_t * currlen,size_t * maxlen,const char * value,int flags,int min,int max)435 fmtstr(
436     char **sbuffer,
437     char **buffer,
438     size_t *currlen,
439     size_t *maxlen,
440     const char *value,
441     int flags,
442     int min,
443     int max)
444 {
445     int padlen, strln;
446     int cnt = 0;
447 
448     if (value == 0)
449         value = "<NULL>";
450     for (strln = 0; value[strln]; ++strln)
451         ;
452     padlen = min - strln;
453     if (padlen < 0)
454         padlen = 0;
455     if (flags & DP_F_MINUS)
456         padlen = -padlen;
457 
458     while ((padlen > 0) && (cnt < max)) {
459         doapr_outch(sbuffer, buffer, currlen, maxlen, ' ');
460         --padlen;
461         ++cnt;
462     }
463     while (*value && (cnt < max)) {
464         doapr_outch(sbuffer, buffer, currlen, maxlen, *value++);
465         ++cnt;
466     }
467     while ((padlen < 0) && (cnt < max)) {
468         doapr_outch(sbuffer, buffer, currlen, maxlen, ' ');
469         ++padlen;
470         ++cnt;
471     }
472 }
473 
474 static void
fmtint(char ** sbuffer,char ** buffer,size_t * currlen,size_t * maxlen,LLONG value,int base,int min,int max,int flags)475 fmtint(
476     char **sbuffer,
477     char **buffer,
478     size_t *currlen,
479     size_t *maxlen,
480     LLONG value,
481     int base,
482     int min,
483     int max,
484     int flags)
485 {
486     int signvalue = 0;
487     char *prefix = "";
488     unsigned LLONG uvalue;
489     char convert[DECIMAL_SIZE(value)+3];
490     int place = 0;
491     int spadlen = 0;
492     int zpadlen = 0;
493     int caps = 0;
494 
495     if (max < 0)
496         max = 0;
497     uvalue = value;
498     if (!(flags & DP_F_UNSIGNED)) {
499         if (value < 0) {
500             signvalue = '-';
501             uvalue = -value;
502         } else if (flags & DP_F_PLUS)
503             signvalue = '+';
504         else if (flags & DP_F_SPACE)
505             signvalue = ' ';
506     }
507     if (flags & DP_F_NUM) {
508 	if (base == 8) prefix = "0";
509 	if (base == 16) prefix = "0x";
510     }
511     if (flags & DP_F_UP)
512         caps = 1;
513     do {
514         convert[place++] =
515             (caps ? "0123456789ABCDEF" : "0123456789abcdef")
516             [uvalue % (unsigned) base];
517         uvalue = (uvalue / (unsigned) base);
518     } while (uvalue && (place < sizeof convert));
519     if (place == sizeof convert)
520         place--;
521     convert[place] = 0;
522 
523     zpadlen = max - place;
524     spadlen = min - OSSL_MAX(max, place) - (signvalue ? 1 : 0) - strlen(prefix);
525     if (zpadlen < 0)
526         zpadlen = 0;
527     if (spadlen < 0)
528         spadlen = 0;
529     if (flags & DP_F_ZERO) {
530         zpadlen = OSSL_MAX(zpadlen, spadlen);
531         spadlen = 0;
532     }
533     if (flags & DP_F_MINUS)
534         spadlen = -spadlen;
535 
536     /* spaces */
537     while (spadlen > 0) {
538         doapr_outch(sbuffer, buffer, currlen, maxlen, ' ');
539         --spadlen;
540     }
541 
542     /* sign */
543     if (signvalue)
544         doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue);
545 
546     /* prefix */
547     while (*prefix) {
548 	doapr_outch(sbuffer, buffer, currlen, maxlen, *prefix);
549 	prefix++;
550     }
551 
552     /* zeros */
553     if (zpadlen > 0) {
554         while (zpadlen > 0) {
555             doapr_outch(sbuffer, buffer, currlen, maxlen, '0');
556             --zpadlen;
557         }
558     }
559     /* digits */
560     while (place > 0)
561         doapr_outch(sbuffer, buffer, currlen, maxlen, convert[--place]);
562 
563     /* left justified spaces */
564     while (spadlen < 0) {
565         doapr_outch(sbuffer, buffer, currlen, maxlen, ' ');
566         ++spadlen;
567     }
568     return;
569 }
570 
571 static LDOUBLE
abs_val(LDOUBLE value)572 abs_val(LDOUBLE value)
573 {
574     LDOUBLE result = value;
575     if (value < 0)
576         result = -value;
577     return result;
578 }
579 
580 static LDOUBLE
pow_10(int in_exp)581 pow_10(int in_exp)
582 {
583     LDOUBLE result = 1;
584     while (in_exp) {
585         result *= 10;
586         in_exp--;
587     }
588     return result;
589 }
590 
591 static long
roundv(LDOUBLE value)592 roundv(LDOUBLE value)
593 {
594     long intpart;
595     intpart = (long) value;
596     value = value - intpart;
597     if (value >= 0.5)
598         intpart++;
599     return intpart;
600 }
601 
602 static void
fmtfp(char ** sbuffer,char ** buffer,size_t * currlen,size_t * maxlen,LDOUBLE fvalue,int min,int max,int flags)603 fmtfp(
604     char **sbuffer,
605     char **buffer,
606     size_t *currlen,
607     size_t *maxlen,
608     LDOUBLE fvalue,
609     int min,
610     int max,
611     int flags)
612 {
613     int signvalue = 0;
614     LDOUBLE ufvalue;
615     char iconvert[20];
616     char fconvert[20];
617     int iplace = 0;
618     int fplace = 0;
619     int padlen = 0;
620     int zpadlen = 0;
621     int caps = 0;
622     long intpart;
623     long fracpart;
624 
625     if (max < 0)
626         max = 6;
627     ufvalue = abs_val(fvalue);
628     if (fvalue < 0)
629         signvalue = '-';
630     else if (flags & DP_F_PLUS)
631         signvalue = '+';
632     else if (flags & DP_F_SPACE)
633         signvalue = ' ';
634 
635     intpart = (long)ufvalue;
636 
637     /* sorry, we only support 9 digits past the decimal because of our
638        conversion method */
639     if (max > 9)
640         max = 9;
641 
642     /* we "cheat" by converting the fractional part to integer by
643        multiplying by a factor of 10 */
644     fracpart = roundv((pow_10(max)) * (ufvalue - intpart));
645 
646     if (fracpart >= (long)pow_10(max)) {
647         intpart++;
648         fracpart -= (long)pow_10(max);
649     }
650 
651     /* convert integer part */
652     do {
653         iconvert[iplace++] =
654             (caps ? "0123456789ABCDEF"
655               : "0123456789abcdef")[intpart % 10];
656         intpart = (intpart / 10);
657     } while (intpart && (iplace < sizeof iconvert));
658     if (iplace == sizeof iconvert)
659         iplace--;
660     iconvert[iplace] = 0;
661 
662     /* convert fractional part */
663     do {
664         fconvert[fplace++] =
665             (caps ? "0123456789ABCDEF"
666               : "0123456789abcdef")[fracpart % 10];
667         fracpart = (fracpart / 10);
668     } while (fplace < max);
669     if (fplace == sizeof fconvert)
670         fplace--;
671     fconvert[fplace] = 0;
672 
673     /* -1 for decimal point, another -1 if we are printing a sign */
674     padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0);
675     zpadlen = max - fplace;
676     if (zpadlen < 0)
677         zpadlen = 0;
678     if (padlen < 0)
679         padlen = 0;
680     if (flags & DP_F_MINUS)
681         padlen = -padlen;
682 
683     if ((flags & DP_F_ZERO) && (padlen > 0)) {
684         if (signvalue) {
685             doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue);
686             --padlen;
687             signvalue = 0;
688         }
689         while (padlen > 0) {
690             doapr_outch(sbuffer, buffer, currlen, maxlen, '0');
691             --padlen;
692         }
693     }
694     while (padlen > 0) {
695         doapr_outch(sbuffer, buffer, currlen, maxlen, ' ');
696         --padlen;
697     }
698     if (signvalue)
699         doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue);
700 
701     while (iplace > 0)
702         doapr_outch(sbuffer, buffer, currlen, maxlen, iconvert[--iplace]);
703 
704     /*
705      * Decimal point. This should probably use locale to find the correct
706      * char to print out.
707      */
708     if (max > 0 || (flags & DP_F_NUM)) {
709         doapr_outch(sbuffer, buffer, currlen, maxlen, '.');
710 
711         while (fplace > 0)
712             doapr_outch(sbuffer, buffer, currlen, maxlen, fconvert[--fplace]);
713     }
714     while (zpadlen > 0) {
715         doapr_outch(sbuffer, buffer, currlen, maxlen, '0');
716         --zpadlen;
717     }
718 
719     while (padlen < 0) {
720         doapr_outch(sbuffer, buffer, currlen, maxlen, ' ');
721         ++padlen;
722     }
723 }
724 
725 static void
doapr_outch(char ** sbuffer,char ** buffer,size_t * currlen,size_t * maxlen,int c)726 doapr_outch(
727     char **sbuffer,
728     char **buffer,
729     size_t *currlen,
730     size_t *maxlen,
731     int c)
732 {
733     /* If we haven't at least one buffer, someone has doe a big booboo */
734     assert(*sbuffer != NULL || buffer != NULL);
735 
736     if (buffer) {
737 	while (*currlen >= *maxlen) {
738 	    if (*buffer == NULL) {
739 		if (*maxlen == 0)
740 		    *maxlen = 1024;
741 		*buffer = OPENSSL_malloc(*maxlen);
742 		if (*currlen > 0) {
743 		    assert(*sbuffer != NULL);
744 		    memcpy(*buffer, *sbuffer, *currlen);
745 		}
746 		*sbuffer = NULL;
747 	    } else {
748 		*maxlen += 1024;
749 		*buffer = OPENSSL_realloc(*buffer, *maxlen);
750 	    }
751 	}
752 	/* What to do if *buffer is NULL? */
753 	assert(*sbuffer != NULL || *buffer != NULL);
754     }
755 
756     if (*currlen < *maxlen) {
757 	if (*sbuffer)
758 	    (*sbuffer)[(*currlen)++] = (char)c;
759 	else
760 	    (*buffer)[(*currlen)++] = (char)c;
761     }
762 
763     return;
764 }
765 
766 /***************************************************************************/
767 
BIO_printf(BIO * bio,const char * format,...)768 int BIO_printf (BIO *bio, const char *format, ...)
769 	{
770 	va_list args;
771 	int ret;
772 
773 	va_start(args, format);
774 
775 	ret = BIO_vprintf(bio, format, args);
776 
777 	va_end(args);
778 	return(ret);
779 	}
780 
BIO_vprintf(BIO * bio,const char * format,va_list args)781 int BIO_vprintf (BIO *bio, const char *format, va_list args)
782 	{
783 	int ret;
784 	size_t retlen;
785 	char hugebuf[1024*2];	/* Was previously 10k, which is unreasonable
786 				   in small-stack environments, like threads
787 				   or DOS programs. */
788 	char *hugebufp = hugebuf;
789 	size_t hugebufsize = sizeof(hugebuf);
790 	char *dynbuf = NULL;
791 	int ignored;
792 
793 	dynbuf = NULL;
794 	CRYPTO_push_info("doapr()");
795 	_dopr(&hugebufp, &dynbuf, &hugebufsize,
796 		&retlen, &ignored, format, args);
797 	if (dynbuf)
798 		{
799 		ret=BIO_write(bio, dynbuf, (int)retlen);
800 		OPENSSL_free(dynbuf);
801 		}
802 	else
803 		{
804 		ret=BIO_write(bio, hugebuf, (int)retlen);
805 		}
806 	CRYPTO_pop_info();
807 	return(ret);
808 	}
809 
810 /* As snprintf is not available everywhere, we provide our own implementation.
811  * In case of overflow or error, this returns -1.
812  * This function has nothing to do with BIOs, but it's closely related
813  * to BIO_printf, and we need *some* name prefix ...
814  * (XXX  the function should be renamed, but to what?) */
BIO_snprintf(char * buf,size_t n,const char * format,...)815 int BIO_snprintf(char *buf, size_t n, const char *format, ...)
816 	{
817 	va_list args;
818 	int ret;
819 
820 	va_start(args, format);
821 
822 	ret = BIO_vsnprintf(buf, n, format, args);
823 
824 	va_end(args);
825 	return(ret);
826 	}
827 
BIO_vsnprintf(char * buf,size_t n,const char * format,va_list args)828 int BIO_vsnprintf(char *buf, size_t n, const char *format, va_list args)
829 	{
830 	size_t retlen;
831 	int truncated;
832 
833 	_dopr(&buf, NULL, &n, &retlen, &truncated, format, args);
834 
835 	if (truncated)
836 		/* In case of truncation, return -1 unlike traditional snprintf.
837 		 * (Current drafts for ISO/IEC 9899 say snprintf should return
838 		 * the number of characters that would have been written,
839 		 * had the buffer been large enough, as it did historically.) */
840 		return -1;
841 	else
842 		return (retlen <= INT_MAX) ? (int)retlen : -1;
843 	}
844