Coverage Report

Created: 2025-09-05 07:01

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