Coverage Report

Created: 2018-08-29 13:53

/src/openssl/crypto/bio/b_print.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright 1995-2018 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 "internal/cryptlib.h"
13
#include "internal/ctype.h"
14
#include "internal/numbers.h"
15
#include <openssl/bio.h>
16
17
/*
18
 * Copyright Patrick Powell 1995
19
 * This code is based on code written by Patrick Powell <papowell@astart.com>
20
 * It may be used for any purpose as long as this notice remains intact
21
 * on all source code distributions.
22
 */
23
24
#ifdef HAVE_LONG_DOUBLE
25
# define LDOUBLE long double
26
#else
27
305k
# define LDOUBLE double
28
#endif
29
30
static int fmtstr(char **, char **, size_t *, size_t *,
31
                  const char *, int, int, int);
32
static int fmtint(char **, char **, size_t *, size_t *,
33
                  int64_t, int, int, int, int);
34
static int fmtfp(char **, char **, size_t *, size_t *,
35
                 LDOUBLE, int, int, int, int);
36
static int doapr_outch(char **, char **, size_t *, size_t *, int);
37
static int _dopr(char **sbuffer, char **buffer,
38
                 size_t *maxlen, size_t *retlen, int *truncated,
39
                 const char *format, va_list args);
40
41
/* format read states */
42
1.05M
#define DP_S_DEFAULT    0
43
747k
#define DP_S_FLAGS      1
44
883k
#define DP_S_MIN        2
45
610k
#define DP_S_DOT        3
46
0
#define DP_S_MAX        4
47
610k
#define DP_S_MOD        5
48
610k
#define DP_S_CONV       6
49
3.60M
#define DP_S_DONE       7
50
51
/* format flags - Bits */
52
/* left-aligned padding */
53
305k
#define DP_F_MINUS      (1 << 0)
54
/* print an explicit '+' for a value with positive sign */
55
0
#define DP_F_PLUS       (1 << 1)
56
/* print an explicit ' ' for a value with positive sign */
57
0
#define DP_F_SPACE      (1 << 2)
58
/* print 0/0x prefix for octal/hex and decimal point for floating point */
59
305k
#define DP_F_NUM        (1 << 3)
60
/* print leading zeroes */
61
441k
#define DP_F_ZERO       (1 << 4)
62
/* print HEX in UPPPERcase */
63
305k
#define DP_F_UP         (1 << 5)
64
/* treat value as unsigned */
65
610k
#define DP_F_UNSIGNED   (1 << 6)
66
67
/* conversion flags */
68
0
#define DP_C_SHORT      1
69
610k
#define DP_C_LONG       2
70
0
#define DP_C_LDOUBLE    3
71
0
#define DP_C_LLONG      4
72
0
#define DP_C_SIZE       5
73
74
/* Floating point formats */
75
0
#define F_FORMAT        0
76
0
#define E_FORMAT        1
77
0
#define G_FORMAT        2
78
79
/* some handy macros */
80
273k
#define char_to_int(p) (p - '0')
81
441k
#define OSSL_MAX(p,q) ((p >= q) ? p : q)
82
83
static int
84
_dopr(char **sbuffer,
85
      char **buffer,
86
      size_t *maxlen,
87
      size_t *retlen, int *truncated, const char *format, va_list args)
88
305k
{
89
305k
    char ch;
90
305k
    int64_t value;
91
305k
    LDOUBLE fvalue;
92
305k
    char *strvalue;
93
305k
    int min;
94
305k
    int max;
95
305k
    int state;
96
305k
    int flags;
97
305k
    int cflags;
98
305k
    size_t currlen;
99
305k
100
305k
    state = DP_S_DEFAULT;
101
305k
    flags = currlen = cflags = min = 0;
102
305k
    max = -1;
103
305k
    ch = *format++;
104
305k
105
2.99M
    while (state != DP_S_DONE) {
106
2.68M
        if (ch == '\0' || (buffer == NULL && currlen >= *maxlen))
107
305k
            state = DP_S_DONE;
108
2.68M
109
2.68M
        switch (state) {
110
2.68M
        case DP_S_DEFAULT:
111
443k
            if (ch == '%')
112
305k
                state = DP_S_FLAGS;
113
443k
            else
114
443k
                if (!doapr_outch(sbuffer, buffer, &currlen, maxlen, ch))
115
0
                    return 0;
116
443k
            ch = *format++;
117
443k
            break;
118
443k
        case DP_S_FLAGS:
119
441k
            switch (ch) {
120
441k
            case '-':
121
0
                flags |= DP_F_MINUS;
122
0
                ch = *format++;
123
0
                break;
124
441k
            case '+':
125
0
                flags |= DP_F_PLUS;
126
0
                ch = *format++;
127
0
                break;
128
441k
            case ' ':
129
0
                flags |= DP_F_SPACE;
130
0
                ch = *format++;
131
0
                break;
132
441k
            case '#':
133
0
                flags |= DP_F_NUM;
134
0
                ch = *format++;
135
0
                break;
136
441k
            case '0':
137
136k
                flags |= DP_F_ZERO;
138
136k
                ch = *format++;
139
136k
                break;
140
441k
            default:
141
305k
                state = DP_S_MIN;
142
305k
                break;
143
441k
            }
144
441k
            break;
145
578k
        case DP_S_MIN:
146
578k
            if (ossl_isdigit(ch)) {
147
273k
                min = 10 * min + char_to_int(ch);
148
273k
                ch = *format++;
149
305k
            } else if (ch == '*') {
150
0
                min = va_arg(args, int);
151
0
                ch = *format++;
152
0
                state = DP_S_DOT;
153
0
            } else
154
305k
                state = DP_S_DOT;
155
578k
            break;
156
441k
        case DP_S_DOT:
157
305k
            if (ch == '.') {
158
0
                state = DP_S_MAX;
159
0
                ch = *format++;
160
0
            } else
161
305k
                state = DP_S_MOD;
162
305k
            break;
163
441k
        case DP_S_MAX:
164
0
            if (ossl_isdigit(ch)) {
165
0
                if (max < 0)
166
0
                    max = 0;
167
0
                max = 10 * max + char_to_int(ch);
168
0
                ch = *format++;
169
0
            } else if (ch == '*') {
170
0
                max = va_arg(args, int);
171
0
                ch = *format++;
172
0
                state = DP_S_MOD;
173
0
            } else
174
0
                state = DP_S_MOD;
175
0
            break;
176
441k
        case DP_S_MOD:
177
305k
            switch (ch) {
178
305k
            case 'h':
179
0
                cflags = DP_C_SHORT;
180
0
                ch = *format++;
181
0
                break;
182
305k
            case 'l':
183
305k
                if (*format == 'l') {
184
0
                    cflags = DP_C_LLONG;
185
0
                    format++;
186
0
                } else
187
305k
                    cflags = DP_C_LONG;
188
305k
                ch = *format++;
189
305k
                break;
190
305k
            case 'q':
191
0
            case 'j':
192
0
                cflags = DP_C_LLONG;
193
0
                ch = *format++;
194
0
                break;
195
0
            case 'L':
196
0
                cflags = DP_C_LDOUBLE;
197
0
                ch = *format++;
198
0
                break;
199
0
            case 'z':
200
0
                cflags = DP_C_SIZE;
201
0
                ch = *format++;
202
0
                break;
203
0
            default:
204
0
                break;
205
305k
            }
206
305k
            state = DP_S_CONV;
207
305k
            break;
208
305k
        case DP_S_CONV:
209
305k
            switch (ch) {
210
305k
            case 'd':
211
0
            case 'i':
212
0
                switch (cflags) {
213
0
                case DP_C_SHORT:
214
0
                    value = (short int)va_arg(args, int);
215
0
                    break;
216
0
                case DP_C_LONG:
217
0
                    value = va_arg(args, long int);
218
0
                    break;
219
0
                case DP_C_LLONG:
220
0
                    value = va_arg(args, int64_t);
221
0
                    break;
222
0
                case DP_C_SIZE:
223
0
                    value = va_arg(args, ossl_ssize_t);
224
0
                    break;
225
0
                default:
226
0
                    value = va_arg(args, int);
227
0
                    break;
228
0
                }
229
0
                if (!fmtint(sbuffer, buffer, &currlen, maxlen, value, 10, min,
230
0
                            max, flags))
231
0
                    return 0;
232
0
                break;
233
0
            case 'X':
234
0
                flags |= DP_F_UP;
235
0
                /* FALLTHROUGH */
236
305k
            case 'x':
237
305k
            case 'o':
238
305k
            case 'u':
239
305k
                flags |= DP_F_UNSIGNED;
240
305k
                switch (cflags) {
241
305k
                case DP_C_SHORT:
242
0
                    value = (unsigned short int)va_arg(args, unsigned int);
243
0
                    break;
244
305k
                case DP_C_LONG:
245
305k
                    value = va_arg(args, unsigned long int);
246
305k
                    break;
247
305k
                case DP_C_LLONG:
248
0
                    value = va_arg(args, uint64_t);
249
0
                    break;
250
305k
                case DP_C_SIZE:
251
0
                    value = va_arg(args, size_t);
252
0
                    break;
253
305k
                default:
254
0
                    value = va_arg(args, unsigned int);
255
0
                    break;
256
305k
                }
257
305k
                if (!fmtint(sbuffer, buffer, &currlen, maxlen, value,
258
305k
                            ch == 'o' ? 8 : (ch == 'u' ? 10 : 16),
259
305k
                            min, max, flags))
260
0
                    return 0;
261
305k
                break;
262
305k
            case 'f':
263
0
                if (cflags == DP_C_LDOUBLE)
264
0
                    fvalue = va_arg(args, LDOUBLE);
265
0
                else
266
0
                    fvalue = va_arg(args, double);
267
0
                if (!fmtfp(sbuffer, buffer, &currlen, maxlen, fvalue, min, max,
268
0
                           flags, F_FORMAT))
269
0
                    return 0;
270
0
                break;
271
0
            case 'E':
272
0
                flags |= DP_F_UP;
273
0
                /* fall thru */
274
0
            case 'e':
275
0
                if (cflags == DP_C_LDOUBLE)
276
0
                    fvalue = va_arg(args, LDOUBLE);
277
0
                else
278
0
                    fvalue = va_arg(args, double);
279
0
                if (!fmtfp(sbuffer, buffer, &currlen, maxlen, fvalue, min, max,
280
0
                           flags, E_FORMAT))
281
0
                    return 0;
282
0
                break;
283
0
            case 'G':
284
0
                flags |= DP_F_UP;
285
0
                /* fall thru */
286
0
            case 'g':
287
0
                if (cflags == DP_C_LDOUBLE)
288
0
                    fvalue = va_arg(args, LDOUBLE);
289
0
                else
290
0
                    fvalue = va_arg(args, double);
291
0
                if (!fmtfp(sbuffer, buffer, &currlen, maxlen, fvalue, min, max,
292
0
                           flags, G_FORMAT))
293
0
                    return 0;
294
0
                break;
295
0
            case 'c':
296
0
                if (!doapr_outch(sbuffer, buffer, &currlen, maxlen,
297
0
                                 va_arg(args, int)))
298
0
                    return 0;
299
0
                break;
300
0
            case 's':
301
0
                strvalue = va_arg(args, char *);
302
0
                if (max < 0) {
303
0
                    if (buffer)
304
0
                        max = INT_MAX;
305
0
                    else
306
0
                        max = *maxlen;
307
0
                }
308
0
                if (!fmtstr(sbuffer, buffer, &currlen, maxlen, strvalue,
309
0
                            flags, min, max))
310
0
                    return 0;
311
0
                break;
312
0
            case 'p':
313
0
                value = (size_t)va_arg(args, void *);
314
0
                if (!fmtint(sbuffer, buffer, &currlen, maxlen,
315
0
                            value, 16, min, max, flags | DP_F_NUM))
316
0
                    return 0;
317
0
                break;
318
0
            case 'n':
319
0
                {
320
0
                    int *num;
321
0
                    num = va_arg(args, int *);
322
0
                    *num = currlen;
323
0
                }
324
0
                break;
325
0
            case '%':
326
0
                if (!doapr_outch(sbuffer, buffer, &currlen, maxlen, ch))
327
0
                    return 0;
328
0
                break;
329
0
            case 'w':
330
0
                /* not supported yet, treat as next char */
331
0
                ch = *format++;
332
0
                break;
333
0
            default:
334
0
                /* unknown, skip */
335
0
                break;
336
305k
            }
337
305k
            ch = *format++;
338
305k
            state = DP_S_DEFAULT;
339
305k
            flags = cflags = min = 0;
340
305k
            max = -1;
341
305k
            break;
342
305k
        case DP_S_DONE:
343
305k
            break;
344
305k
        default:
345
0
            break;
346
2.68M
        }
347
2.68M
    }
348
305k
    /*
349
305k
     * We have to truncate if there is no dynamic buffer and we have filled the
350
305k
     * static buffer.
351
305k
     */
352
305k
    if (buffer == NULL) {
353
305k
        *truncated = (currlen > *maxlen - 1);
354
305k
        if (*truncated)
355
0
            currlen = *maxlen - 1;
356
305k
    }
357
305k
    if (!doapr_outch(sbuffer, buffer, &currlen, maxlen, '\0'))
358
0
        return 0;
359
305k
    *retlen = currlen - 1;
360
305k
    return 1;
361
305k
}
362
363
static int
364
fmtstr(char **sbuffer,
365
       char **buffer,
366
       size_t *currlen,
367
       size_t *maxlen, const char *value, int flags, int min, int max)
368
0
{
369
0
    int padlen;
370
0
    size_t strln;
371
0
    int cnt = 0;
372
0
373
0
    if (value == 0)
374
0
        value = "<NULL>";
375
0
376
0
    strln = OPENSSL_strnlen(value, max < 0 ? SIZE_MAX : (size_t)max);
377
0
378
0
    padlen = min - strln;
379
0
    if (min < 0 || padlen < 0)
380
0
        padlen = 0;
381
0
    if (max >= 0) {
382
0
        /*
383
0
         * Calculate the maximum output including padding.
384
0
         * Make sure max doesn't overflow into negativity
385
0
         */
386
0
        if (max < INT_MAX - padlen)
387
0
            max += padlen;
388
0
        else
389
0
            max = INT_MAX;
390
0
    }
391
0
    if (flags & DP_F_MINUS)
392
0
        padlen = -padlen;
393
0
394
0
    while ((padlen > 0) && (max < 0 || cnt < max)) {
395
0
        if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' '))
396
0
            return 0;
397
0
        --padlen;
398
0
        ++cnt;
399
0
    }
400
0
    while (strln > 0 && (max < 0 || cnt < max)) {
401
0
        if (!doapr_outch(sbuffer, buffer, currlen, maxlen, *value++))
402
0
            return 0;
403
0
        --strln;
404
0
        ++cnt;
405
0
    }
406
0
    while ((padlen < 0) && (max < 0 || cnt < max)) {
407
0
        if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' '))
408
0
            return 0;
409
0
        ++padlen;
410
0
        ++cnt;
411
0
    }
412
0
    return 1;
413
0
}
414
415
static int
416
fmtint(char **sbuffer,
417
       char **buffer,
418
       size_t *currlen,
419
       size_t *maxlen, int64_t value, int base, int min, int max, int flags)
420
305k
{
421
305k
    int signvalue = 0;
422
305k
    const char *prefix = "";
423
305k
    uint64_t uvalue;
424
305k
    char convert[DECIMAL_SIZE(value) + 3];
425
305k
    int place = 0;
426
305k
    int spadlen = 0;
427
305k
    int zpadlen = 0;
428
305k
    int caps = 0;
429
305k
430
305k
    if (max < 0)
431
305k
        max = 0;
432
305k
    uvalue = value;
433
305k
    if (!(flags & DP_F_UNSIGNED)) {
434
0
        if (value < 0) {
435
0
            signvalue = '-';
436
0
            uvalue = 0 - (uint64_t)value;
437
0
        } else if (flags & DP_F_PLUS)
438
0
            signvalue = '+';
439
0
        else if (flags & DP_F_SPACE)
440
0
            signvalue = ' ';
441
0
    }
442
305k
    if (flags & DP_F_NUM) {
443
0
        if (base == 8)
444
0
            prefix = "0";
445
0
        if (base == 16)
446
0
            prefix = "0x";
447
0
    }
448
305k
    if (flags & DP_F_UP)
449
305k
        caps = 1;
450
3.25M
    do {
451
3.25M
        convert[place++] = (caps ? "0123456789ABCDEF" : "0123456789abcdef")
452
3.25M
            [uvalue % (unsigned)base];
453
3.25M
        uvalue = (uvalue / (unsigned)base);
454
3.25M
    } while (uvalue && (place < (int)sizeof(convert)));
455
305k
    if (place == sizeof(convert))
456
0
        place--;
457
305k
    convert[place] = 0;
458
305k
459
305k
    zpadlen = max - place;
460
305k
    spadlen =
461
305k
        min - OSSL_MAX(max, place) - (signvalue ? 1 : 0) - strlen(prefix);
462
305k
    if (zpadlen < 0)
463
305k
        zpadlen = 0;
464
305k
    if (spadlen < 0)
465
168k
        spadlen = 0;
466
305k
    if (flags & DP_F_ZERO) {
467
136k
        zpadlen = OSSL_MAX(zpadlen, spadlen);
468
136k
        spadlen = 0;
469
136k
    }
470
305k
    if (flags & DP_F_MINUS)
471
305k
        spadlen = -spadlen;
472
305k
473
305k
    /* spaces */
474
305k
    while (spadlen > 0) {
475
0
        if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' '))
476
0
            return 0;
477
0
        --spadlen;
478
0
    }
479
305k
480
305k
    /* sign */
481
305k
    if (signvalue)
482
0
        if (!doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue))
483
0
            return 0;
484
305k
485
305k
    /* prefix */
486
305k
    while (*prefix) {
487
0
        if (!doapr_outch(sbuffer, buffer, currlen, maxlen, *prefix))
488
0
            return 0;
489
0
        prefix++;
490
0
    }
491
305k
492
305k
    /* zeros */
493
305k
    if (zpadlen > 0) {
494
34.4k
        while (zpadlen > 0) {
495
18.5k
            if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '0'))
496
0
                return 0;
497
18.5k
            --zpadlen;
498
18.5k
        }
499
15.8k
    }
500
305k
    /* digits */
501
3.56M
    while (place > 0) {
502
3.25M
        if (!doapr_outch(sbuffer, buffer, currlen, maxlen, convert[--place]))
503
0
            return 0;
504
3.25M
    }
505
305k
506
305k
    /* left justified spaces */
507
305k
    while (spadlen < 0) {
508
0
        if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' '))
509
0
            return 0;
510
0
        ++spadlen;
511
0
    }
512
305k
    return 1;
513
305k
}
514
515
static LDOUBLE abs_val(LDOUBLE value)
516
0
{
517
0
    LDOUBLE result = value;
518
0
    if (value < 0)
519
0
        result = -value;
520
0
    return result;
521
0
}
522
523
static LDOUBLE pow_10(int in_exp)
524
0
{
525
0
    LDOUBLE result = 1;
526
0
    while (in_exp) {
527
0
        result *= 10;
528
0
        in_exp--;
529
0
    }
530
0
    return result;
531
0
}
532
533
static long roundv(LDOUBLE value)
534
0
{
535
0
    long intpart;
536
0
    intpart = (long)value;
537
0
    value = value - intpart;
538
0
    if (value >= 0.5)
539
0
        intpart++;
540
0
    return intpart;
541
0
}
542
543
static int
544
fmtfp(char **sbuffer,
545
      char **buffer,
546
      size_t *currlen,
547
      size_t *maxlen, LDOUBLE fvalue, int min, int max, int flags, int style)
548
0
{
549
0
    int signvalue = 0;
550
0
    LDOUBLE ufvalue;
551
0
    LDOUBLE tmpvalue;
552
0
    char iconvert[20];
553
0
    char fconvert[20];
554
0
    char econvert[20];
555
0
    int iplace = 0;
556
0
    int fplace = 0;
557
0
    int eplace = 0;
558
0
    int padlen = 0;
559
0
    int zpadlen = 0;
560
0
    long exp = 0;
561
0
    unsigned long intpart;
562
0
    unsigned long fracpart;
563
0
    unsigned long max10;
564
0
    int realstyle;
565
0
566
0
    if (max < 0)
567
0
        max = 6;
568
0
569
0
    if (fvalue < 0)
570
0
        signvalue = '-';
571
0
    else if (flags & DP_F_PLUS)
572
0
        signvalue = '+';
573
0
    else if (flags & DP_F_SPACE)
574
0
        signvalue = ' ';
575
0
576
0
    /*
577
0
     * G_FORMAT sometimes prints like E_FORMAT and sometimes like F_FORMAT
578
0
     * depending on the number to be printed. Work out which one it is and use
579
0
     * that from here on.
580
0
     */
581
0
    if (style == G_FORMAT) {
582
0
        if (fvalue == 0.0) {
583
0
            realstyle = F_FORMAT;
584
0
        } else if (fvalue < 0.0001) {
585
0
            realstyle = E_FORMAT;
586
0
        } else if ((max == 0 && fvalue >= 10)
587
0
                    || (max > 0 && fvalue >= pow_10(max))) {
588
0
            realstyle = E_FORMAT;
589
0
        } else {
590
0
            realstyle = F_FORMAT;
591
0
        }
592
0
    } else {
593
0
        realstyle = style;
594
0
    }
595
0
596
0
    if (style != F_FORMAT) {
597
0
        tmpvalue = fvalue;
598
0
        /* Calculate the exponent */
599
0
        if (fvalue != 0.0) {
600
0
            while (tmpvalue < 1) {
601
0
                tmpvalue *= 10;
602
0
                exp--;
603
0
            }
604
0
            while (tmpvalue > 10) {
605
0
                tmpvalue /= 10;
606
0
                exp++;
607
0
            }
608
0
        }
609
0
        if (style == G_FORMAT) {
610
0
            /*
611
0
             * In G_FORMAT the "precision" represents significant digits. We
612
0
             * always have at least 1 significant digit.
613
0
             */
614
0
            if (max == 0)
615
0
                max = 1;
616
0
            /* Now convert significant digits to decimal places */
617
0
            if (realstyle == F_FORMAT) {
618
0
                max -= (exp + 1);
619
0
                if (max < 0) {
620
0
                    /*
621
0
                     * Should not happen. If we're in F_FORMAT then exp < max?
622
0
                     */
623
0
                    return 0;
624
0
                }
625
0
            } else {
626
0
                /*
627
0
                 * In E_FORMAT there is always one significant digit in front
628
0
                 * of the decimal point, so:
629
0
                 * significant digits == 1 + decimal places
630
0
                 */
631
0
                max--;
632
0
            }
633
0
        }
634
0
        if (realstyle == E_FORMAT)
635
0
            fvalue = tmpvalue;
636
0
    }
637
0
    ufvalue = abs_val(fvalue);
638
0
    if (ufvalue > ULONG_MAX) {
639
0
        /* Number too big */
640
0
        return 0;
641
0
    }
642
0
    intpart = (unsigned long)ufvalue;
643
0
644
0
    /*
645
0
     * sorry, we only support 9 digits past the decimal because of our
646
0
     * conversion method
647
0
     */
648
0
    if (max > 9)
649
0
        max = 9;
650
0
651
0
    /*
652
0
     * we "cheat" by converting the fractional part to integer by multiplying
653
0
     * by a factor of 10
654
0
     */
655
0
    max10 = roundv(pow_10(max));
656
0
    fracpart = roundv(pow_10(max) * (ufvalue - intpart));
657
0
658
0
    if (fracpart >= max10) {
659
0
        intpart++;
660
0
        fracpart -= max10;
661
0
    }
662
0
663
0
    /* convert integer part */
664
0
    do {
665
0
        iconvert[iplace++] = "0123456789"[intpart % 10];
666
0
        intpart = (intpart / 10);
667
0
    } while (intpart && (iplace < (int)sizeof(iconvert)));
668
0
    if (iplace == sizeof(iconvert))
669
0
        iplace--;
670
0
    iconvert[iplace] = 0;
671
0
672
0
    /* convert fractional part */
673
0
    while (fplace < max) {
674
0
        if (style == G_FORMAT && fplace == 0 && (fracpart % 10) == 0) {
675
0
            /* We strip trailing zeros in G_FORMAT */
676
0
            max--;
677
0
            fracpart = fracpart / 10;
678
0
            if (fplace < max)
679
0
                continue;
680
0
            break;
681
0
        }
682
0
        fconvert[fplace++] = "0123456789"[fracpart % 10];
683
0
        fracpart = (fracpart / 10);
684
0
    }
685
0
686
0
    if (fplace == sizeof(fconvert))
687
0
        fplace--;
688
0
    fconvert[fplace] = 0;
689
0
690
0
    /* convert exponent part */
691
0
    if (realstyle == E_FORMAT) {
692
0
        int tmpexp;
693
0
        if (exp < 0)
694
0
            tmpexp = -exp;
695
0
        else
696
0
            tmpexp = exp;
697
0
698
0
        do {
699
0
            econvert[eplace++] = "0123456789"[tmpexp % 10];
700
0
            tmpexp = (tmpexp / 10);
701
0
        } while (tmpexp > 0 && eplace < (int)sizeof(econvert));
702
0
        /* Exponent is huge!! Too big to print */
703
0
        if (tmpexp > 0)
704
0
            return 0;
705
0
        /* Add a leading 0 for single digit exponents */
706
0
        if (eplace == 1)
707
0
            econvert[eplace++] = '0';
708
0
    }
709
0
710
0
    /*
711
0
     * -1 for decimal point (if we have one, i.e. max > 0),
712
0
     * another -1 if we are printing a sign
713
0
     */
714
0
    padlen = min - iplace - max - (max > 0 ? 1 : 0) - ((signvalue) ? 1 : 0);
715
0
    /* Take some off for exponent prefix "+e" and exponent */
716
0
    if (realstyle == E_FORMAT)
717
0
        padlen -= 2 + eplace;
718
0
    zpadlen = max - fplace;
719
0
    if (zpadlen < 0)
720
0
        zpadlen = 0;
721
0
    if (padlen < 0)
722
0
        padlen = 0;
723
0
    if (flags & DP_F_MINUS)
724
0
        padlen = -padlen;
725
0
726
0
    if ((flags & DP_F_ZERO) && (padlen > 0)) {
727
0
        if (signvalue) {
728
0
            if (!doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue))
729
0
                return 0;
730
0
            --padlen;
731
0
            signvalue = 0;
732
0
        }
733
0
        while (padlen > 0) {
734
0
            if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '0'))
735
0
                return 0;
736
0
            --padlen;
737
0
        }
738
0
    }
739
0
    while (padlen > 0) {
740
0
        if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' '))
741
0
            return 0;
742
0
        --padlen;
743
0
    }
744
0
    if (signvalue && !doapr_outch(sbuffer, buffer, currlen, maxlen, signvalue))
745
0
        return 0;
746
0
747
0
    while (iplace > 0) {
748
0
        if (!doapr_outch(sbuffer, buffer, currlen, maxlen, iconvert[--iplace]))
749
0
            return 0;
750
0
    }
751
0
752
0
    /*
753
0
     * Decimal point. This should probably use locale to find the correct
754
0
     * char to print out.
755
0
     */
756
0
    if (max > 0 || (flags & DP_F_NUM)) {
757
0
        if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '.'))
758
0
            return 0;
759
0
760
0
        while (fplace > 0) {
761
0
            if (!doapr_outch(sbuffer, buffer, currlen, maxlen,
762
0
                             fconvert[--fplace]))
763
0
                return 0;
764
0
        }
765
0
    }
766
0
    while (zpadlen > 0) {
767
0
        if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '0'))
768
0
            return 0;
769
0
        --zpadlen;
770
0
    }
771
0
    if (realstyle == E_FORMAT) {
772
0
        char ech;
773
0
774
0
        if ((flags & DP_F_UP) == 0)
775
0
            ech = 'e';
776
0
        else
777
0
            ech = 'E';
778
0
        if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ech))
779
0
                return 0;
780
0
        if (exp < 0) {
781
0
            if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '-'))
782
0
                    return 0;
783
0
        } else {
784
0
            if (!doapr_outch(sbuffer, buffer, currlen, maxlen, '+'))
785
0
                    return 0;
786
0
        }
787
0
        while (eplace > 0) {
788
0
            if (!doapr_outch(sbuffer, buffer, currlen, maxlen,
789
0
                             econvert[--eplace]))
790
0
                return 0;
791
0
        }
792
0
    }
793
0
794
0
    while (padlen < 0) {
795
0
        if (!doapr_outch(sbuffer, buffer, currlen, maxlen, ' '))
796
0
            return 0;
797
0
        ++padlen;
798
0
    }
799
0
    return 1;
800
0
}
801
802
0
#define BUFFER_INC  1024
803
804
static int
805
doapr_outch(char **sbuffer,
806
            char **buffer, size_t *currlen, size_t *maxlen, int c)
807
3.71M
{
808
3.71M
    /* If we haven't at least one buffer, someone has done a big booboo */
809
3.71M
    if (!ossl_assert(*sbuffer != NULL || buffer != NULL))
810
3.71M
        return 0;
811
3.71M
812
3.71M
    /* |currlen| must always be <= |*maxlen| */
813
3.71M
    if (!ossl_assert(*currlen <= *maxlen))
814
3.71M
        return 0;
815
3.71M
816
3.71M
    if (buffer && *currlen == *maxlen) {
817
0
        if (*maxlen > INT_MAX - BUFFER_INC)
818
0
            return 0;
819
0
820
0
        *maxlen += BUFFER_INC;
821
0
        if (*buffer == NULL) {
822
0
            if ((*buffer = OPENSSL_malloc(*maxlen)) == NULL) {
823
0
                BIOerr(BIO_F_DOAPR_OUTCH, ERR_R_MALLOC_FAILURE);
824
0
                return 0;
825
0
            }
826
0
            if (*currlen > 0) {
827
0
                if (!ossl_assert(*sbuffer != NULL))
828
0
                    return 0;
829
0
                memcpy(*buffer, *sbuffer, *currlen);
830
0
            }
831
0
            *sbuffer = NULL;
832
0
        } else {
833
0
            char *tmpbuf;
834
0
            tmpbuf = OPENSSL_realloc(*buffer, *maxlen);
835
0
            if (tmpbuf == NULL)
836
0
                return 0;
837
0
            *buffer = tmpbuf;
838
0
        }
839
0
    }
840
3.71M
841
3.71M
    if (*currlen < *maxlen) {
842
3.71M
        if (*sbuffer)
843
3.71M
            (*sbuffer)[(*currlen)++] = (char)c;
844
0
        else
845
0
            (*buffer)[(*currlen)++] = (char)c;
846
3.71M
    }
847
3.71M
848
3.71M
    return 1;
849
3.71M
}
850
851
/***************************************************************************/
852
853
int BIO_printf(BIO *bio, const char *format, ...)
854
0
{
855
0
    va_list args;
856
0
    int ret;
857
0
858
0
    va_start(args, format);
859
0
860
0
    ret = BIO_vprintf(bio, format, args);
861
0
862
0
    va_end(args);
863
0
    return ret;
864
0
}
865
866
int BIO_vprintf(BIO *bio, const char *format, va_list args)
867
0
{
868
0
    int ret;
869
0
    size_t retlen;
870
0
    char hugebuf[1024 * 2];     /* Was previously 10k, which is unreasonable
871
0
                                 * in small-stack environments, like threads
872
0
                                 * or DOS programs. */
873
0
    char *hugebufp = hugebuf;
874
0
    size_t hugebufsize = sizeof(hugebuf);
875
0
    char *dynbuf = NULL;
876
0
    int ignored;
877
0
878
0
    dynbuf = NULL;
879
0
    if (!_dopr(&hugebufp, &dynbuf, &hugebufsize, &retlen, &ignored, format,
880
0
                args)) {
881
0
        OPENSSL_free(dynbuf);
882
0
        return -1;
883
0
    }
884
0
    if (dynbuf) {
885
0
        ret = BIO_write(bio, dynbuf, (int)retlen);
886
0
        OPENSSL_free(dynbuf);
887
0
    } else {
888
0
        ret = BIO_write(bio, hugebuf, (int)retlen);
889
0
    }
890
0
    return ret;
891
0
}
892
893
/*
894
 * As snprintf is not available everywhere, we provide our own
895
 * implementation. This function has nothing to do with BIOs, but it's
896
 * closely related to BIO_printf, and we need *some* name prefix ... (XXX the
897
 * function should be renamed, but to what?)
898
 */
899
int BIO_snprintf(char *buf, size_t n, const char *format, ...)
900
305k
{
901
305k
    va_list args;
902
305k
    int ret;
903
305k
904
305k
    va_start(args, format);
905
305k
906
305k
    ret = BIO_vsnprintf(buf, n, format, args);
907
305k
908
305k
    va_end(args);
909
305k
    return ret;
910
305k
}
911
912
int BIO_vsnprintf(char *buf, size_t n, const char *format, va_list args)
913
305k
{
914
305k
    size_t retlen;
915
305k
    int truncated;
916
305k
917
305k
    if (!_dopr(&buf, NULL, &n, &retlen, &truncated, format, args))
918
0
        return -1;
919
305k
920
305k
    if (truncated)
921
0
        /*
922
0
         * In case of truncation, return -1 like traditional snprintf.
923
0
         * (Current drafts for ISO/IEC 9899 say snprintf should return the
924
0
         * number of characters that would have been written, had the buffer
925
0
         * been large enough.)
926
0
         */
927
0
        return -1;
928
305k
    else
929
305k
        return (retlen <= INT_MAX) ? (int)retlen : -1;
930
305k
}