Fix some issues in b_print.c code
[openssl.git] / crypto / bio / b_print.c
1 /*
2  * Copyright 1995-2016 The OpenSSL Project Authors. All Rights Reserved.
3  *
4  * Licensed under the OpenSSL license (the "License").  You may not use
5  * this file except in compliance with the License.  You can obtain a copy
6  * in the file LICENSE in the source distribution or at
7  * https://www.openssl.org/source/license.html
8  */
9
10 #include <stdio.h>
11 #include <string.h>
12 #include <ctype.h>
13 #include <limits.h>
14 #include "internal/cryptlib.h"
15 #ifndef NO_SYS_TYPES_H
16 # include <sys/types.h>
17 #endif
18 #include <openssl/bn.h>         /* To get BN_LLONG properly defined */
19 #include <openssl/bio.h>
20
21 #if defined(BN_LLONG) || defined(SIXTY_FOUR_BIT)
22 # ifndef HAVE_LONG_LONG
23 #  define HAVE_LONG_LONG 1
24 # endif
25 #endif
26
27 /*
28  * Copyright Patrick Powell 1995
29  * This code is based on code written by Patrick Powell <papowell@astart.com>
30  * It may be used for any purpose as long as this notice remains intact
31  * on all source code distributions.
32  */
33
34 #ifdef HAVE_LONG_DOUBLE
35 # define LDOUBLE long double
36 #else
37 # define LDOUBLE double
38 #endif
39
40 #ifdef HAVE_LONG_LONG
41 # if defined(_WIN32) && !defined(__GNUC__)
42 #  define LLONG __int64
43 # else
44 #  define LLONG long long
45 # endif
46 #else
47 # define LLONG long
48 #endif
49
50 static int fmtstr(char **, char **, size_t *, size_t *,
51                   const char *, int, int, int);
52 static int fmtint(char **, char **, size_t *, size_t *,
53                   LLONG, int, int, int, int);
54 static int fmtfp(char **, char **, size_t *, size_t *,
55                  LDOUBLE, int, int, int);
56 static int doapr_outch(char **, char **, size_t *, size_t *, int);
57 static int _dopr(char **sbuffer, char **buffer,
58                  size_t *maxlen, size_t *retlen, int *truncated,
59                  const char *format, va_list args);
60
61 /* format read states */
62 #define DP_S_DEFAULT    0
63 #define DP_S_FLAGS      1
64 #define DP_S_MIN        2
65 #define DP_S_DOT        3
66 #define DP_S_MAX        4
67 #define DP_S_MOD        5
68 #define DP_S_CONV       6
69 #define DP_S_DONE       7
70
71 /* format flags - Bits */
72 /* left-aligned padding */
73 #define DP_F_MINUS      (1 << 0)
74 /* print an explicit '+' for a value with positive sign */
75 #define DP_F_PLUS       (1 << 1)
76 /* print an explicit ' ' for a value with positive sign */
77 #define DP_F_SPACE      (1 << 2)
78 /* print 0/0x prefix for octal/hex and decimal point for floating point */
79 #define DP_F_NUM        (1 << 3)
80 /* print leading zeroes */
81 #define DP_F_ZERO       (1 << 4)
82 /* print HEX in UPPPERcase */
83 #define DP_F_UP         (1 << 5)
84 /* treat value as unsigned */
85 #define DP_F_UNSIGNED   (1 << 6)
86
87 /* conversion flags */
88 #define DP_C_SHORT      1
89 #define DP_C_LONG       2
90 #define DP_C_LDOUBLE    3
91 #define DP_C_LLONG      4
92
93 /* some handy macros */
94 #define char_to_int(p) (p - '0')
95 #define OSSL_MAX(p,q) ((p >= q) ? p : q)
96
97 static int
98 _dopr(char **sbuffer,
99       char **buffer,
100       size_t *maxlen,
101       size_t *retlen, int *truncated, const char *format, va_list args)
102 {
103     char ch;
104     LLONG value;
105     LDOUBLE fvalue;
106     char *strvalue;
107     int min;
108     int max;
109     int state;
110     int flags;
111     int cflags;
112     size_t currlen;
113
114     state = DP_S_DEFAULT;
115     flags = currlen = cflags = min = 0;
116     max = -1;
117     ch = *format++;
118
119     while (state != DP_S_DONE) {
120         if (ch == '\0' || (buffer == NULL && currlen >= *maxlen))
121             state = DP_S_DONE;
122
123         switch (state) {
124         case DP_S_DEFAULT:
125             if (ch == '%')
126                 state = DP_S_FLAGS;
127             else
128                 if(!doapr_outch(sbuffer, buffer, &currlen, maxlen, ch))
129                     return 0;
130             ch = *format++;
131             break;
132         case DP_S_FLAGS:
133             switch (ch) {
134             case '-':
135                 flags |= DP_F_MINUS;
136                 ch = *format++;
137                 break;
138             case '+':
139                 flags |= DP_F_PLUS;
140                 ch = *format++;
141                 break;
142             case ' ':
143                 flags |= DP_F_SPACE;
144                 ch = *format++;
145                 break;
146             case '#':
147                 flags |= DP_F_NUM;
148                 ch = *format++;
149                 break;
150             case '0':
151                 flags |= DP_F_ZERO;
152                 ch = *format++;
153                 break;
154             default:
155                 state = DP_S_MIN;
156                 break;
157             }
158             break;
159         case DP_S_MIN:
160             if (isdigit((unsigned char)ch)) {
161                 min = 10 * min + char_to_int(ch);
162                 ch = *format++;
163             } else if (ch == '*') {
164                 min = va_arg(args, int);
165                 ch = *format++;
166                 state = DP_S_DOT;
167             } else
168                 state = DP_S_DOT;
169             break;
170         case DP_S_DOT:
171             if (ch == '.') {
172                 state = DP_S_MAX;
173                 ch = *format++;
174             } else
175                 state = DP_S_MOD;
176             break;
177         case DP_S_MAX:
178             if (isdigit((unsigned char)ch)) {
179                 if (max < 0)
180                     max = 0;
181                 max = 10 * max + char_to_int(ch);
182                 ch = *format++;
183             } else if (ch == '*') {
184                 max = va_arg(args, int);
185                 ch = *format++;
186                 state = DP_S_MOD;
187             } else
188                 state = DP_S_MOD;
189             break;
190         case DP_S_MOD:
191             switch (ch) {
192             case 'h':
193                 cflags = DP_C_SHORT;
194                 ch = *format++;
195                 break;
196             case 'l':
197                 if (*format == 'l') {
198                     cflags = DP_C_LLONG;
199                     format++;
200                 } else
201                     cflags = DP_C_LONG;
202                 ch = *format++;
203                 break;
204             case 'q':
205                 cflags = DP_C_LLONG;
206                 ch = *format++;
207                 break;
208             case 'L':
209                 cflags = DP_C_LDOUBLE;
210                 ch = *format++;
211                 break;
212             default:
213                 break;
214             }
215             state = DP_S_CONV;
216             break;
217         case DP_S_CONV:
218             switch (ch) {
219             case 'd':
220             case 'i':
221                 switch (cflags) {
222                 case DP_C_SHORT:
223                     value = (short int)va_arg(args, int);
224                     break;
225                 case DP_C_LONG:
226                     value = va_arg(args, long int);
227                     break;
228                 case DP_C_LLONG:
229                     value = va_arg(args, LLONG);
230                     break;
231                 default:
232                     value = va_arg(args, int);
233                     break;
234                 }
235                 if (!fmtint(sbuffer, buffer, &currlen, maxlen, value, 10, min,
236                             max, flags))
237                     return 0;
238                 break;
239             case 'X':
240                 flags |= DP_F_UP;
241                 /* FALLTHROUGH */
242             case 'x':
243             case 'o':
244             case 'u':
245                 flags |= DP_F_UNSIGNED;
246                 switch (cflags) {
247                 case DP_C_SHORT:
248                     value = (unsigned short int)va_arg(args, unsigned int);
249                     break;
250                 case DP_C_LONG:
251                     value = (LLONG) va_arg(args, unsigned long int);
252                     break;
253                 case DP_C_LLONG:
254                     value = va_arg(args, unsigned LLONG);
255                     break;
256                 default:
257                     value = (LLONG) va_arg(args, unsigned int);
258                     break;
259                 }
260                 if (!fmtint(sbuffer, buffer, &currlen, maxlen, value,
261                             ch == 'o' ? 8 : (ch == 'u' ? 10 : 16),
262                             min, max, flags))
263                     return 0;
264                 break;
265             case 'f':
266                 if (cflags == DP_C_LDOUBLE)
267                     fvalue = va_arg(args, LDOUBLE);
268                 else
269                     fvalue = va_arg(args, double);
270                 if (!fmtfp(sbuffer, buffer, &currlen, maxlen, fvalue, min, max,
271                            flags))
272                     return 0;
273                 break;
274             case 'E':
275                 flags |= DP_F_UP;
276             case 'e':
277                 if (cflags == DP_C_LDOUBLE)
278                     fvalue = va_arg(args, LDOUBLE);
279                 else
280                     fvalue = va_arg(args, double);
281                 if (!fmtfp(sbuffer, buffer, &currlen, maxlen, fvalue, min, max,
282                            flags))
283                     return 0;
284                 break;
285             case 'G':
286                 flags |= DP_F_UP;
287             case 'g':
288                 if (cflags == DP_C_LDOUBLE)
289                     fvalue = va_arg(args, LDOUBLE);
290                 else
291                     fvalue = va_arg(args, double);
292                 if (!fmtfp(sbuffer, buffer, &currlen, maxlen, fvalue, min, max,
293                            flags))
294                     return 0;
295                 break;
296             case 'c':
297                 if(!doapr_outch(sbuffer, buffer, &currlen, maxlen,
298                             va_arg(args, int)))
299                     return 0;
300                 break;
301             case 's':
302                 strvalue = va_arg(args, char *);
303                 if (max < 0) {
304                     if (buffer)
305                         max = INT_MAX;
306                     else
307                         max = *maxlen;
308                 }
309                 if (!fmtstr(sbuffer, buffer, &currlen, maxlen, strvalue,
310                             flags, min, max))
311                     return 0;
312                 break;
313             case 'p':
314                 value = (size_t)va_arg(args, void *);
315                 if (!fmtint(sbuffer, buffer, &currlen, maxlen,
316                             value, 16, min, max, flags | DP_F_NUM))
317                     return 0;
318                 break;
319             case 'n':          /* XXX */
320                 if (cflags == DP_C_SHORT) {
321                     short int *num;
322                     num = va_arg(args, short int *);
323                     *num = currlen;
324                 } else if (cflags == DP_C_LONG) { /* XXX */
325                     long int *num;
326                     num = va_arg(args, long int *);
327                     *num = (long int)currlen;
328                 } else if (cflags == DP_C_LLONG) { /* XXX */
329                     LLONG *num;
330                     num = va_arg(args, LLONG *);
331                     *num = (LLONG) currlen;
332                 } else {
333                     int *num;
334                     num = va_arg(args, int *);
335                     *num = currlen;
336                 }
337                 break;
338             case '%':
339                 if(!doapr_outch(sbuffer, buffer, &currlen, maxlen, ch))
340                     return 0;
341                 break;
342             case 'w':
343                 /* not supported yet, treat as next char */
344                 ch = *format++;
345                 break;
346             default:
347                 /* unknown, skip */
348                 break;
349             }
350             ch = *format++;
351             state = DP_S_DEFAULT;
352             flags = cflags = min = 0;
353             max = -1;
354             break;
355         case DP_S_DONE:
356             break;
357         default:
358             break;
359         }
360     }
361     *truncated = (currlen > *maxlen - 1);
362     if (*truncated)
363         currlen = *maxlen - 1;
364     if(!doapr_outch(sbuffer, buffer, &currlen, maxlen, '\0'))
365         return 0;
366     *retlen = currlen - 1;
367     return 1;
368 }
369
370 static int
371 fmtstr(char **sbuffer,
372        char **buffer,
373        size_t *currlen,
374        size_t *maxlen, const char *value, int flags, int min, int max)
375 {
376     int padlen;
377     size_t strln;
378     int cnt = 0;
379
380     if (value == 0)
381         value = "<NULL>";
382
383     strln = strlen(value);
384     if (strln > INT_MAX)
385         strln = INT_MAX;
386
387     padlen = min - strln;
388     if (min < 0 || padlen < 0)
389         padlen = 0;
390     if (flags & DP_F_MINUS)
391         padlen = -padlen;
392
393     while ((padlen > 0) && (cnt < max)) {
394         if(!doapr_outch(sbuffer, buffer, currlen, maxlen, ' '))
395             return 0;
396         --padlen;
397         ++cnt;
398     }
399     while (*value && (cnt < max)) {
400         if(!doapr_outch(sbuffer, buffer, currlen, maxlen, *value++))
401             return 0;
402         ++cnt;
403     }
404     while ((padlen < 0) && (cnt < max)) {
405         if(!doapr_outch(sbuffer, buffer, currlen, maxlen, ' '))
406             return 0;
407         ++padlen;
408         ++cnt;
409     }
410     return 1;
411 }
412
413 static int
414 fmtint(char **sbuffer,
415        char **buffer,
416        size_t *currlen,
417        size_t *maxlen, LLONG value, int base, int min, int max, int flags)
418 {
419     int signvalue = 0;
420     const char *prefix = "";
421     unsigned LLONG uvalue;
422     char convert[DECIMAL_SIZE(value) + 3];
423     int place = 0;
424     int spadlen = 0;
425     int zpadlen = 0;
426     int caps = 0;
427
428     if (max < 0)
429         max = 0;
430     uvalue = value;
431     if (!(flags & DP_F_UNSIGNED)) {
432         if (value < 0) {
433             signvalue = '-';
434             uvalue = -value;
435         } else if (flags & DP_F_PLUS)
436             signvalue = '+';
437         else if (flags & DP_F_SPACE)
438             signvalue = ' ';
439     }
440     if (flags & DP_F_NUM) {
441         if (base == 8)
442             prefix = "0";
443         if (base == 16)
444             prefix = "0x";
445     }
446     if (flags & DP_F_UP)
447         caps = 1;
448     do {
449         convert[place++] = (caps ? "0123456789ABCDEF" : "0123456789abcdef")
450             [uvalue % (unsigned)base];
451         uvalue = (uvalue / (unsigned)base);
452     } while (uvalue && (place < (int)sizeof(convert)));
453     if (place == sizeof(convert))
454         place--;
455     convert[place] = 0;
456
457     zpadlen = max - place;
458     spadlen =
459         min - OSSL_MAX(max, place) - (signvalue ? 1 : 0) - strlen(prefix);
460     if (zpadlen < 0)
461         zpadlen = 0;
462     if (spadlen < 0)
463         spadlen = 0;
464     if (flags & DP_F_ZERO) {
465         zpadlen = OSSL_MAX(zpadlen, spadlen);
466         spadlen = 0;
467     }
468     if (flags & DP_F_MINUS)
469         spadlen = -spadlen;
470
471     /* spaces */
472     while (spadlen > 0) {
473         if(!doapr_outch(sbuffer, buffer, currlen, maxlen, ' '))
474             return 0;
475         --spadlen;
476     }
477
478     /* sign */
479     if (signvalue)
480         if(!doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue))
481             return 0;
482
483     /* prefix */
484     while (*prefix) {
485         if(!doapr_outch(sbuffer, buffer, currlen, maxlen, *prefix))
486             return 0;
487         prefix++;
488     }
489
490     /* zeros */
491     if (zpadlen > 0) {
492         while (zpadlen > 0) {
493             if(!doapr_outch(sbuffer, buffer, currlen, maxlen, '0'))
494                 return 0;
495             --zpadlen;
496         }
497     }
498     /* digits */
499     while (place > 0) {
500         if (!doapr_outch(sbuffer, buffer, currlen, maxlen, convert[--place]))
501             return 0;
502     }
503
504     /* left justified spaces */
505     while (spadlen < 0) {
506         if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' '))
507             return 0;
508         ++spadlen;
509     }
510     return 1;
511 }
512
513 static LDOUBLE abs_val(LDOUBLE value)
514 {
515     LDOUBLE result = value;
516     if (value < 0)
517         result = -value;
518     return result;
519 }
520
521 static LDOUBLE pow_10(int in_exp)
522 {
523     LDOUBLE result = 1;
524     while (in_exp) {
525         result *= 10;
526         in_exp--;
527     }
528     return result;
529 }
530
531 static long roundv(LDOUBLE value)
532 {
533     long intpart;
534     intpart = (long)value;
535     value = value - intpart;
536     if (value >= 0.5)
537         intpart++;
538     return intpart;
539 }
540
541 static int
542 fmtfp(char **sbuffer,
543       char **buffer,
544       size_t *currlen,
545       size_t *maxlen, LDOUBLE fvalue, int min, int max, int flags)
546 {
547     int signvalue = 0;
548     LDOUBLE ufvalue;
549     char iconvert[20];
550     char fconvert[20];
551     int iplace = 0;
552     int fplace = 0;
553     int padlen = 0;
554     int zpadlen = 0;
555     long intpart;
556     long fracpart;
557     long max10;
558
559     if (max < 0)
560         max = 6;
561     ufvalue = abs_val(fvalue);
562     if (fvalue < 0)
563         signvalue = '-';
564     else if (flags & DP_F_PLUS)
565         signvalue = '+';
566     else if (flags & DP_F_SPACE)
567         signvalue = ' ';
568
569     intpart = (long)ufvalue;
570
571     /*
572      * sorry, we only support 9 digits past the decimal because of our
573      * conversion method
574      */
575     if (max > 9)
576         max = 9;
577
578     /*
579      * we "cheat" by converting the fractional part to integer by multiplying
580      * by a factor of 10
581      */
582     max10 = roundv(pow_10(max));
583     fracpart = roundv(pow_10(max) * (ufvalue - intpart));
584
585     if (fracpart >= max10) {
586         intpart++;
587         fracpart -= max10;
588     }
589
590     /* convert integer part */
591     do {
592         iconvert[iplace++] = "0123456789"[intpart % 10];
593         intpart = (intpart / 10);
594     } while (intpart && (iplace < (int)sizeof(iconvert)));
595     if (iplace == sizeof iconvert)
596         iplace--;
597     iconvert[iplace] = 0;
598
599     /* convert fractional part */
600     do {
601         fconvert[fplace++] = "0123456789"[fracpart % 10];
602         fracpart = (fracpart / 10);
603     } while (fplace < max);
604     if (fplace == sizeof fconvert)
605         fplace--;
606     fconvert[fplace] = 0;
607
608     /* -1 for decimal point, another -1 if we are printing a sign */
609     padlen = min - iplace - max - 1 - ((signvalue) ? 1 : 0);
610     zpadlen = max - fplace;
611     if (zpadlen < 0)
612         zpadlen = 0;
613     if (padlen < 0)
614         padlen = 0;
615     if (flags & DP_F_MINUS)
616         padlen = -padlen;
617
618     if ((flags & DP_F_ZERO) && (padlen > 0)) {
619         if (signvalue) {
620             if (!doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue))
621                 return 0;
622             --padlen;
623             signvalue = 0;
624         }
625         while (padlen > 0) {
626             if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '0'))
627                 return 0;
628             --padlen;
629         }
630     }
631     while (padlen > 0) {
632         if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' '))
633             return 0;
634         --padlen;
635     }
636     if (signvalue && !doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue))
637         return 0;
638
639     while (iplace > 0) {
640         if (!doapr_outch(sbuffer, buffer, currlen, maxlen, iconvert[--iplace]))
641             return 0;
642     }
643
644     /*
645      * Decimal point. This should probably use locale to find the correct
646      * char to print out.
647      */
648     if (max > 0 || (flags & DP_F_NUM)) {
649         if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '.'))
650             return 0;
651
652         while (fplace > 0) {
653             if(!doapr_outch(sbuffer, buffer, currlen, maxlen,
654                             fconvert[--fplace]))
655                 return 0;
656         }
657     }
658     while (zpadlen > 0) {
659         if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '0'))
660             return 0;
661         --zpadlen;
662     }
663
664     while (padlen < 0) {
665         if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' '))
666             return 0;
667         ++padlen;
668     }
669     return 1;
670 }
671
672 #define BUFFER_INC  1024
673
674 static int
675 doapr_outch(char **sbuffer,
676             char **buffer, size_t *currlen, size_t *maxlen, int c)
677 {
678     /* If we haven't at least one buffer, someone has doe a big booboo */
679     OPENSSL_assert(*sbuffer != NULL || buffer != NULL);
680
681     /* |currlen| must always be <= |*maxlen| */
682     OPENSSL_assert(*currlen <= *maxlen);
683
684     if (buffer && *currlen == *maxlen) {
685         if (*maxlen > INT_MAX - BUFFER_INC)
686             return 0;
687
688         *maxlen += BUFFER_INC;
689         if (*buffer == NULL) {
690             *buffer = OPENSSL_malloc(*maxlen);
691             if (*buffer == NULL)
692                 return 0;
693             if (*currlen > 0) {
694                 OPENSSL_assert(*sbuffer != NULL);
695                 memcpy(*buffer, *sbuffer, *currlen);
696             }
697             *sbuffer = NULL;
698         } else {
699             char *tmpbuf;
700             tmpbuf = OPENSSL_realloc(*buffer, *maxlen);
701             if (tmpbuf == NULL)
702                 return 0;
703             *buffer = tmpbuf;
704         }
705     }
706
707     if (*currlen < *maxlen) {
708         if (*sbuffer)
709             (*sbuffer)[(*currlen)++] = (char)c;
710         else
711             (*buffer)[(*currlen)++] = (char)c;
712     }
713
714     return 1;
715 }
716
717 /***************************************************************************/
718
719 int BIO_printf(BIO *bio, const char *format, ...)
720 {
721     va_list args;
722     int ret;
723
724     va_start(args, format);
725
726     ret = BIO_vprintf(bio, format, args);
727
728     va_end(args);
729     return (ret);
730 }
731
732 int BIO_vprintf(BIO *bio, const char *format, va_list args)
733 {
734     int ret;
735     size_t retlen;
736     char hugebuf[1024 * 2];     /* Was previously 10k, which is unreasonable
737                                  * in small-stack environments, like threads
738                                  * or DOS programs. */
739     char *hugebufp = hugebuf;
740     size_t hugebufsize = sizeof(hugebuf);
741     char *dynbuf = NULL;
742     int ignored;
743
744     dynbuf = NULL;
745     if (!_dopr(&hugebufp, &dynbuf, &hugebufsize, &retlen, &ignored, format,
746                 args)) {
747         OPENSSL_free(dynbuf);
748         return -1;
749     }
750     if (dynbuf) {
751         ret = BIO_write(bio, dynbuf, (int)retlen);
752         OPENSSL_free(dynbuf);
753     } else {
754         ret = BIO_write(bio, hugebuf, (int)retlen);
755     }
756     return (ret);
757 }
758
759 /*
760  * As snprintf is not available everywhere, we provide our own
761  * implementation. This function has nothing to do with BIOs, but it's
762  * closely related to BIO_printf, and we need *some* name prefix ... (XXX the
763  * function should be renamed, but to what?)
764  */
765 int BIO_snprintf(char *buf, size_t n, const char *format, ...)
766 {
767     va_list args;
768     int ret;
769
770     va_start(args, format);
771
772     ret = BIO_vsnprintf(buf, n, format, args);
773
774     va_end(args);
775     return (ret);
776 }
777
778 int BIO_vsnprintf(char *buf, size_t n, const char *format, va_list args)
779 {
780     size_t retlen;
781     int truncated;
782
783     if(!_dopr(&buf, NULL, &n, &retlen, &truncated, format, args))
784         return -1;
785
786     if (truncated)
787         /*
788          * In case of truncation, return -1 like traditional snprintf.
789          * (Current drafts for ISO/IEC 9899 say snprintf should return the
790          * number of characters that would have been written, had the buffer
791          * been large enough.)
792          */
793         return -1;
794     else
795         return (retlen <= INT_MAX) ? (int)retlen : -1;
796 }