]> CyberLeo.Net >> Repos - FreeBSD/releng/9.3.git/blob - crypto/openssl/crypto/bio/b_print.c
Fix multiple OpenSSL vulnerabilities.
[FreeBSD/releng/9.3.git] / crypto / openssl / crypto / bio / b_print.c
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\r
126 #endif\r
127 \r
128 static int fmtstr(char **, char **, size_t *, size_t *,\r
129                    const char *, int, int, int);\r
130 static int fmtint(char **, char **, size_t *, size_t *,\r
131                    LLONG, int, int, int, int);\r
132 static int fmtfp(char **, char **, size_t *, size_t *,\r
133                   LDOUBLE, int, int, int);\r
134 static int doapr_outch(char **, char **, size_t *, size_t *, int);\r
135 static int _dopr(char **sbuffer, char **buffer,\r
136                   size_t *maxlen, size_t *retlen, int *truncated,\r
137                   const char *format, va_list args);\r
138 \r
139 /* format read states */
140 #define DP_S_DEFAULT    0
141 #define DP_S_FLAGS      1
142 #define DP_S_MIN        2
143 #define DP_S_DOT        3
144 #define DP_S_MAX        4
145 #define DP_S_MOD        5
146 #define DP_S_CONV       6
147 #define DP_S_DONE       7
148
149 /* format flags - Bits */
150 #define DP_F_MINUS      (1 << 0)
151 #define DP_F_PLUS       (1 << 1)
152 #define DP_F_SPACE      (1 << 2)
153 #define DP_F_NUM        (1 << 3)
154 #define DP_F_ZERO       (1 << 4)
155 #define DP_F_UP         (1 << 5)
156 #define DP_F_UNSIGNED   (1 << 6)
157
158 /* conversion flags */
159 #define DP_C_SHORT      1
160 #define DP_C_LONG       2
161 #define DP_C_LDOUBLE    3
162 #define DP_C_LLONG      4
163
164 /* some handy macros */
165 #define char_to_int(p) (p - '0')\r
166 #define OSSL_MAX(p,q) ((p >= q) ? p : q)\r
167 \r
168 static int\r
169 _dopr(char **sbuffer,\r
170       char **buffer,\r
171       size_t *maxlen,\r
172       size_t *retlen, int *truncated, const char *format, va_list args)
173 {
174     char ch;
175     LLONG value;
176     LDOUBLE fvalue;
177     char *strvalue;
178     int min;
179     int max;
180     int state;
181     int flags;
182     int cflags;
183     size_t currlen;
184
185     state = DP_S_DEFAULT;
186     flags = currlen = cflags = min = 0;
187     max = -1;
188     ch = *format++;
189
190     while (state != DP_S_DONE) {
191         if (ch == '\0' || (buffer == NULL && currlen >= *maxlen))
192             state = DP_S_DONE;
193
194         switch (state) {
195         case DP_S_DEFAULT:
196             if (ch == '%')\r
197                 state = DP_S_FLAGS;\r
198             else\r
199                 if(!doapr_outch(sbuffer, buffer, &currlen, maxlen, ch))\r
200                     return 0;\r
201             ch = *format++;\r
202             break;\r
203         case DP_S_FLAGS:\r
204             switch (ch) {
205             case '-':
206                 flags |= DP_F_MINUS;
207                 ch = *format++;
208                 break;
209             case '+':
210                 flags |= DP_F_PLUS;
211                 ch = *format++;
212                 break;
213             case ' ':
214                 flags |= DP_F_SPACE;
215                 ch = *format++;
216                 break;
217             case '#':
218                 flags |= DP_F_NUM;
219                 ch = *format++;
220                 break;
221             case '0':
222                 flags |= DP_F_ZERO;
223                 ch = *format++;
224                 break;
225             default:
226                 state = DP_S_MIN;
227                 break;
228             }
229             break;
230         case DP_S_MIN:
231             if (isdigit((unsigned char)ch)) {
232                 min = 10 * min + char_to_int(ch);
233                 ch = *format++;
234             } else if (ch == '*') {
235                 min = va_arg(args, int);
236                 ch = *format++;
237                 state = DP_S_DOT;
238             } else
239                 state = DP_S_DOT;
240             break;
241         case DP_S_DOT:
242             if (ch == '.') {
243                 state = DP_S_MAX;
244                 ch = *format++;
245             } else
246                 state = DP_S_MOD;
247             break;
248         case DP_S_MAX:
249             if (isdigit((unsigned char)ch)) {
250                 if (max < 0)
251                     max = 0;
252                 max = 10 * max + char_to_int(ch);
253                 ch = *format++;
254             } else if (ch == '*') {
255                 max = va_arg(args, int);
256                 ch = *format++;
257                 state = DP_S_MOD;
258             } else
259                 state = DP_S_MOD;
260             break;
261         case DP_S_MOD:
262             switch (ch) {
263             case 'h':
264                 cflags = DP_C_SHORT;
265                 ch = *format++;
266                 break;
267             case 'l':
268                 if (*format == 'l') {
269                     cflags = DP_C_LLONG;
270                     format++;
271                 } else
272                     cflags = DP_C_LONG;
273                 ch = *format++;
274                 break;
275             case 'q':
276                 cflags = DP_C_LLONG;
277                 ch = *format++;
278                 break;
279             case 'L':
280                 cflags = DP_C_LDOUBLE;
281                 ch = *format++;
282                 break;
283             default:
284                 break;
285             }
286             state = DP_S_CONV;
287             break;
288         case DP_S_CONV:
289             switch (ch) {
290             case 'd':
291             case 'i':
292                 switch (cflags) {
293                 case DP_C_SHORT:
294                     value = (short int)va_arg(args, int);
295                     break;
296                 case DP_C_LONG:
297                     value = va_arg(args, long int);
298                     break;
299                 case DP_C_LLONG:
300                     value = va_arg(args, LLONG);
301                     break;
302                 default:
303                     value = va_arg(args, int);\r
304                     break;\r
305                 }\r
306                 if (!fmtint(sbuffer, buffer, &currlen, maxlen, value, 10, min,\r
307                             max, flags))\r
308                     return 0;\r
309                 break;\r
310             case 'X':\r
311                 flags |= DP_F_UP;\r
312                 /* FALLTHROUGH */
313             case 'x':
314             case 'o':
315             case 'u':
316                 flags |= DP_F_UNSIGNED;
317                 switch (cflags) {
318                 case DP_C_SHORT:
319                     value = (unsigned short int)va_arg(args, unsigned int);
320                     break;
321                 case DP_C_LONG:
322                     value = (LLONG) va_arg(args, unsigned long int);
323                     break;
324                 case DP_C_LLONG:
325                     value = va_arg(args, unsigned LLONG);
326                     break;
327                 default:
328                     value = (LLONG) va_arg(args, unsigned int);\r
329                     break;\r
330                 }\r
331                 if (!fmtint(sbuffer, buffer, &currlen, maxlen, value,\r
332                        ch == 'o' ? 8 : (ch == 'u' ? 10 : 16),\r
333                             min, max, flags))\r
334                     return 0;\r
335                 break;\r
336             case 'f':\r
337                 if (cflags == DP_C_LDOUBLE)\r
338                     fvalue = va_arg(args, LDOUBLE);\r
339                 else\r
340                     fvalue = va_arg(args, double);\r
341                 if (!fmtfp(sbuffer, buffer, &currlen, maxlen, fvalue, min, max,\r
342                            flags))\r
343                     return 0;\r
344                 break;\r
345             case 'E':\r
346                 flags |= DP_F_UP;\r
347             case 'e':
348                 if (cflags == DP_C_LDOUBLE)
349                     fvalue = va_arg(args, LDOUBLE);
350                 else
351                     fvalue = va_arg(args, double);
352                 break;
353             case 'G':
354                 flags |= DP_F_UP;
355             case 'g':
356                 if (cflags == DP_C_LDOUBLE)
357                     fvalue = va_arg(args, LDOUBLE);
358                 else
359                     fvalue = va_arg(args, double);\r
360                 break;\r
361             case 'c':\r
362                 if(!doapr_outch(sbuffer, buffer, &currlen, maxlen,\r
363                             va_arg(args, int)))\r
364                     return 0;\r
365                 break;\r
366             case 's':\r
367                 strvalue = va_arg(args, char *);\r
368                 if (max < 0) {
369                     if (buffer)
370                         max = INT_MAX;
371                     else\r
372                         max = *maxlen;\r
373                 }\r
374                 if (!fmtstr(sbuffer, buffer, &currlen, maxlen, strvalue,\r
375                             flags, min, max))\r
376                     return 0;\r
377                 break;\r
378             case 'p':\r
379                 value = (long)va_arg(args, void *);\r
380                 if (!fmtint(sbuffer, buffer, &currlen, maxlen,\r
381                             value, 16, min, max, flags | DP_F_NUM))\r
382                     return 0;\r
383                 break;\r
384             case 'n':          /* XXX */\r
385                 if (cflags == DP_C_SHORT) {\r
386                     short int *num;
387                     num = va_arg(args, short int *);
388                     *num = currlen;
389                 } else if (cflags == DP_C_LONG) { /* XXX */
390                     long int *num;
391                     num = va_arg(args, long int *);
392                     *num = (long int)currlen;
393                 } else if (cflags == DP_C_LLONG) { /* XXX */
394                     LLONG *num;
395                     num = va_arg(args, LLONG *);
396                     *num = (LLONG) currlen;
397                 } else {
398                     int *num;
399                     num = va_arg(args, int *);
400                     *num = currlen;
401                 }\r
402                 break;\r
403             case '%':\r
404                 if(!doapr_outch(sbuffer, buffer, &currlen, maxlen, ch))\r
405                     return 0;\r
406                 break;\r
407             case 'w':\r
408                 /* not supported yet, treat as next char */\r
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);\r
427     if (*truncated)\r
428         currlen = *maxlen - 1;\r
429     if(!doapr_outch(sbuffer, buffer, &currlen, maxlen, '\0'))\r
430         return 0;\r
431     *retlen = currlen - 1;\r
432     return 1;\r
433 }\r
434 \r
435 static int\r
436 fmtstr(char **sbuffer,\r
437        char **buffer,\r
438        size_t *currlen,\r
439        size_t *maxlen, const char *value, int flags, int min, int max)\r
440 {\r
441     int padlen;\r
442     size_t strln;\r
443     int cnt = 0;\r
444 \r
445     if (value == 0)\r
446         value = "<NULL>";\r
447 \r
448     strln = strlen(value);\r
449     if (strln > INT_MAX)\r
450         strln = INT_MAX;\r
451 \r
452     padlen = min - strln;\r
453     if (min < 0 || padlen < 0)\r
454         padlen = 0;\r
455     if (flags & DP_F_MINUS)\r
456         padlen = -padlen;\r
457 \r
458     while ((padlen > 0) && (cnt < max)) {\r
459         if(!doapr_outch(sbuffer, buffer, currlen, maxlen, ' '))\r
460             return 0;\r
461         --padlen;\r
462         ++cnt;\r
463     }\r
464     while (*value && (cnt < max)) {\r
465         if(!doapr_outch(sbuffer, buffer, currlen, maxlen, *value++))\r
466             return 0;\r
467         ++cnt;\r
468     }\r
469     while ((padlen < 0) && (cnt < max)) {\r
470         if(!doapr_outch(sbuffer, buffer, currlen, maxlen, ' '))\r
471             return 0;\r
472         ++padlen;\r
473         ++cnt;\r
474     }\r
475     return 1;\r
476 }\r
477 \r
478 static int\r
479 fmtint(char **sbuffer,\r
480        char **buffer,\r
481        size_t *currlen,\r
482        size_t *maxlen, LLONG value, int base, int min, int max, int flags)
483 {
484     int signvalue = 0;
485     const char *prefix = "";
486     unsigned LLONG uvalue;
487     char convert[DECIMAL_SIZE(value) + 3];
488     int place = 0;
489     int spadlen = 0;
490     int zpadlen = 0;
491     int caps = 0;
492
493     if (max < 0)
494         max = 0;
495     uvalue = value;
496     if (!(flags & DP_F_UNSIGNED)) {
497         if (value < 0) {
498             signvalue = '-';
499             uvalue = -value;
500         } else if (flags & DP_F_PLUS)
501             signvalue = '+';
502         else if (flags & DP_F_SPACE)
503             signvalue = ' ';
504     }
505     if (flags & DP_F_NUM) {
506         if (base == 8)
507             prefix = "0";
508         if (base == 16)
509             prefix = "0x";
510     }
511     if (flags & DP_F_UP)
512         caps = 1;
513     do {
514         convert[place++] = (caps ? "0123456789ABCDEF" : "0123456789abcdef")
515             [uvalue % (unsigned)base];
516         uvalue = (uvalue / (unsigned)base);
517     } while (uvalue && (place < (int)sizeof(convert)));
518     if (place == sizeof(convert))
519         place--;
520     convert[place] = 0;
521
522     zpadlen = max - place;
523     spadlen =
524         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 \r
536     /* spaces */\r
537     while (spadlen > 0) {\r
538         if(!doapr_outch(sbuffer, buffer, currlen, maxlen, ' '))\r
539             return 0;\r
540         --spadlen;\r
541     }\r
542 \r
543     /* sign */\r
544     if (signvalue)\r
545         if(!doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue))\r
546             return 0;\r
547 \r
548     /* prefix */\r
549     while (*prefix) {\r
550         if(!doapr_outch(sbuffer, buffer, currlen, maxlen, *prefix))\r
551             return 0;\r
552         prefix++;\r
553     }\r
554 \r
555     /* zeros */\r
556     if (zpadlen > 0) {\r
557         while (zpadlen > 0) {\r
558             if(!doapr_outch(sbuffer, buffer, currlen, maxlen, '0'))\r
559                 return 0;\r
560             --zpadlen;\r
561         }\r
562     }\r
563     /* digits */\r
564     while (place > 0) {\r
565         if (!doapr_outch(sbuffer, buffer, currlen, maxlen, convert[--place]))\r
566             return 0;\r
567     }\r
568 \r
569     /* left justified spaces */\r
570     while (spadlen < 0) {\r
571         if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' '))\r
572             return 0;\r
573         ++spadlen;\r
574     }\r
575     return 1;\r
576 }\r
577 \r
578 static LDOUBLE abs_val(LDOUBLE value)\r
579 {
580     LDOUBLE result = value;
581     if (value < 0)
582         result = -value;
583     return result;
584 }
585
586 static LDOUBLE 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 {
598     long intpart;
599     intpart = (long)value;
600     value = value - intpart;
601     if (value >= 0.5)
602         intpart++;
603     return intpart;\r
604 }\r
605 \r
606 static int\r
607 fmtfp(char **sbuffer,\r
608       char **buffer,\r
609       size_t *currlen,\r
610       size_t *maxlen, LDOUBLE fvalue, int min, int max, int flags)
611 {
612     int signvalue = 0;
613     LDOUBLE ufvalue;
614     char iconvert[20];
615     char fconvert[20];
616     int iplace = 0;
617     int fplace = 0;
618     int padlen = 0;
619     int zpadlen = 0;
620     int caps = 0;
621     long intpart;
622     long fracpart;
623     long max10;
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     /*
638      * sorry, we only support 9 digits past the decimal because of our
639      * conversion method
640      */
641     if (max > 9)
642         max = 9;
643
644     /*
645      * we "cheat" by converting the fractional part to integer by multiplying
646      * by a factor of 10
647      */
648     max10 = roundv(pow_10(max));
649     fracpart = roundv(pow_10(max) * (ufvalue - intpart));
650
651     if (fracpart >= max10) {
652         intpart++;
653         fracpart -= max10;
654     }
655
656     /* convert integer part */
657     do {
658         iconvert[iplace++] =
659             (caps ? "0123456789ABCDEF" : "0123456789abcdef")[intpart % 10];
660         intpart = (intpart / 10);
661     } while (intpart && (iplace < (int)sizeof(iconvert)));
662     if (iplace == sizeof iconvert)
663         iplace--;
664     iconvert[iplace] = 0;
665
666     /* convert fractional part */
667     do {
668         fconvert[fplace++] =
669             (caps ? "0123456789ABCDEF" : "0123456789abcdef")[fracpart % 10];
670         fracpart = (fracpart / 10);
671     } while (fplace < max);
672     if (fplace == sizeof fconvert)
673         fplace--;
674     fconvert[fplace] = 0;
675
676     /* -1 for decimal point, another -1 if we are printing a sign */
677     padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0);
678     zpadlen = max - fplace;
679     if (zpadlen < 0)
680         zpadlen = 0;
681     if (padlen < 0)
682         padlen = 0;
683     if (flags & DP_F_MINUS)
684         padlen = -padlen;
685 \r
686     if ((flags & DP_F_ZERO) && (padlen > 0)) {\r
687         if (signvalue) {\r
688             if (!doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue))\r
689                 return 0;\r
690             --padlen;\r
691             signvalue = 0;\r
692         }\r
693         while (padlen > 0) {\r
694             if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '0'))\r
695                 return 0;\r
696             --padlen;\r
697         }\r
698     }\r
699     while (padlen > 0) {\r
700         if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' '))\r
701             return 0;\r
702         --padlen;\r
703     }\r
704     if (signvalue && !doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue))\r
705         return 0;\r
706 \r
707     while (iplace > 0) {\r
708         if (!doapr_outch(sbuffer, buffer, currlen, maxlen, iconvert[--iplace]))\r
709             return 0;\r
710     }\r
711 \r
712     /*\r
713      * Decimal point. This should probably use locale to find the correct\r
714      * char to print out.\r
715      */\r
716     if (max > 0 || (flags & DP_F_NUM)) {\r
717         if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '.'))\r
718             return 0;\r
719 \r
720         while (fplace > 0) {\r
721             if(!doapr_outch(sbuffer, buffer, currlen, maxlen,\r
722                             fconvert[--fplace]))\r
723                 return 0;\r
724         }\r
725     }\r
726     while (zpadlen > 0) {\r
727         if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '0'))\r
728             return 0;\r
729         --zpadlen;\r
730     }\r
731 \r
732     while (padlen < 0) {\r
733         if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' '))\r
734             return 0;\r
735         ++padlen;\r
736     }\r
737     return 1;\r
738 }\r
739 \r
740 #define BUFFER_INC  1024\r
741 \r
742 static int\r
743 doapr_outch(char **sbuffer,\r
744             char **buffer, size_t *currlen, size_t *maxlen, int c)\r
745 {\r
746     /* If we haven't at least one buffer, someone has doe a big booboo */\r
747     assert(*sbuffer != NULL || buffer != NULL);\r
748 \r
749     /* |currlen| must always be <= |*maxlen| */\r
750     assert(*currlen <= *maxlen);\r
751 \r
752     if (buffer && *currlen == *maxlen) {\r
753         if (*maxlen > INT_MAX - BUFFER_INC)\r
754             return 0;\r
755 \r
756         *maxlen += BUFFER_INC;\r
757             if (*buffer == NULL) {\r
758                 *buffer = OPENSSL_malloc(*maxlen);\r
759                 if (*buffer == NULL)\r
760                     return 0;\r
761                 if (*currlen > 0) {\r
762                     assert(*sbuffer != NULL);\r
763                     memcpy(*buffer, *sbuffer, *currlen);\r
764                 }\r
765                 *sbuffer = NULL;\r
766             } else {\r
767                 char *tmpbuf;\r
768                 tmpbuf = OPENSSL_realloc(*buffer, *maxlen);\r
769                 if (tmpbuf == NULL)\r
770                     return 0;\r
771                 *buffer = tmpbuf;\r
772             }\r
773         }\r
774 \r
775     if (*currlen < *maxlen) {\r
776         if (*sbuffer)\r
777             (*sbuffer)[(*currlen)++] = (char)c;
778         else
779             (*buffer)[(*currlen)++] = (char)c;\r
780     }\r
781 \r
782     return 1;\r
783 }\r
784 \r
785 /***************************************************************************/\r
786
787 int BIO_printf(BIO *bio, const char *format, ...)
788 {
789     va_list args;
790     int ret;
791
792     va_start(args, format);
793
794     ret = BIO_vprintf(bio, format, args);
795
796     va_end(args);
797     return (ret);
798 }
799
800 int BIO_vprintf(BIO *bio, const char *format, va_list args)
801 {
802     int ret;
803     size_t retlen;
804     char hugebuf[1024 * 2];     /* Was previously 10k, which is unreasonable
805                                  * in small-stack environments, like threads
806                                  * or DOS programs. */
807     char *hugebufp = hugebuf;
808     size_t hugebufsize = sizeof(hugebuf);
809     char *dynbuf = NULL;
810     int ignored;
811 \r
812     dynbuf = NULL;\r
813     CRYPTO_push_info("doapr()");\r
814     if (!_dopr(&hugebufp, &dynbuf, &hugebufsize, &retlen, &ignored, format,\r
815                 args)) {\r
816         OPENSSL_free(dynbuf);\r
817         return -1;\r
818     }\r
819     if (dynbuf) {\r
820         ret = BIO_write(bio, dynbuf, (int)retlen);\r
821         OPENSSL_free(dynbuf);\r
822     } else {
823         ret = BIO_write(bio, hugebuf, (int)retlen);
824     }
825     CRYPTO_pop_info();
826     return (ret);
827 }
828
829 /*
830  * As snprintf is not available everywhere, we provide our own
831  * implementation. This function has nothing to do with BIOs, but it's
832  * closely related to BIO_printf, and we need *some* name prefix ... (XXX the
833  * function should be renamed, but to what?)
834  */
835 int BIO_snprintf(char *buf, size_t n, const char *format, ...)
836 {
837     va_list args;
838     int ret;
839
840     va_start(args, format);
841
842     ret = BIO_vsnprintf(buf, n, format, args);
843
844     va_end(args);
845     return (ret);
846 }
847
848 int BIO_vsnprintf(char *buf, size_t n, const char *format, va_list args)
849 {
850     size_t retlen;\r
851     int truncated;\r
852 \r
853     if(!_dopr(&buf, NULL, &n, &retlen, &truncated, format, args))\r
854         return -1;\r
855 \r
856     if (truncated)\r
857         /*\r
858          * In case of truncation, return -1 like traditional snprintf.
859          * (Current drafts for ISO/IEC 9899 say snprintf should return the
860          * number of characters that would have been written, had the buffer
861          * been large enough.)
862          */
863         return -1;
864     else
865         return (retlen <= INT_MAX) ? (int)retlen : -1;
866 }