Coverage Report

Created: 2025-12-31 06:58

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/openssl36/crypto/bio/bio_print.c
Line
Count
Source
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
62.3M
#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 eob_ok(struct pr_desc *desc, long long left);
51
static int _dopr(char **sbuffer, char **buffer,
52
    size_t *maxlen, size_t *retlen, int *truncated,
53
    const char *format, va_list args);
54
55
/* format read states */
56
383M
#define DP_S_DEFAULT 0
57
277M
#define DP_S_FLAGS 1
58
283M
#define DP_S_MIN 2
59
234M
#define DP_S_DOT 3
60
16.5k
#define DP_S_MAX 4
61
234M
#define DP_S_MOD 5
62
234M
#define DP_S_CONV 6
63
1.13G
#define DP_S_DONE 7
64
65
/* format flags - Bits */
66
/* left-aligned padding */
67
116M
#define DP_F_MINUS (1 << 0)
68
/* print an explicit '+' for a value with positive sign */
69
9.08M
#define DP_F_PLUS (1 << 1)
70
/* print an explicit ' ' for a value with positive sign */
71
9.08M
#define DP_F_SPACE (1 << 2)
72
/* print 0/0x prefix for octal/hex and decimal point for floating point */
73
50.0M
#define DP_F_NUM (1 << 3)
74
/* print leading zeroes */
75
86.2M
#define DP_F_ZERO (1 << 4)
76
/* print HEX in UPPERcase */
77
65.9M
#define DP_F_UP (1 << 5)
78
/* treat value as unsigned */
79
91.0M
#define DP_F_UNSIGNED (1 << 6)
80
81
/* conversion flags */
82
0
#define DP_C_CHAR 1
83
0
#define DP_C_SHORT 2
84
16.6M
#define DP_C_LONG 3
85
0
#define DP_C_LDOUBLE 4
86
53.9k
#define DP_C_LLONG 5
87
0
#define DP_C_SIZE 6
88
0
#define DP_C_PTRDIFF 7
89
90
/* Floating point formats */
91
0
#define F_FORMAT 0
92
0
#define E_FORMAT 1
93
0
#define G_FORMAT 2
94
95
/* some handy macros */
96
48.6M
#define char_to_int(p) (p - '0')
97
100M
#define OSSL_MAX(p, q) ((p >= q) ? p : q)
98
99
static int
100
_dopr(char **sbuffer,
101
    char **buffer,
102
    size_t *maxlen,
103
    size_t *retlen, int *truncated, const char *format, va_list args)
104
62.3M
{
105
62.3M
    char ch;
106
62.3M
    int64_t value;
107
62.3M
#ifndef OPENSSL_SYS_UEFI
108
62.3M
    LDOUBLE fvalue;
109
62.3M
#endif
110
62.3M
    char *strvalue;
111
62.3M
    int min;
112
62.3M
    int max;
113
62.3M
    int state;
114
62.3M
    int flags;
115
62.3M
    int cflags;
116
62.3M
    struct pr_desc desc = { *sbuffer, buffer, 0, *maxlen, 0 };
117
62.3M
    int ret = 0;
118
119
62.3M
    state = DP_S_DEFAULT;
120
62.3M
    flags = cflags = min = 0;
121
62.3M
    max = -1;
122
62.3M
    ch = *format++;
123
124
1.00G
    while (state != DP_S_DONE) {
125
944M
        if (ch == '\0')
126
62.3M
            state = DP_S_DONE;
127
128
944M
        switch (state) {
129
204M
        case DP_S_DEFAULT:
130
204M
            if (ch == '%')
131
117M
                state = DP_S_FLAGS;
132
86.7M
            else if (!doapr_outch(&desc, ch))
133
0
                goto out;
134
204M
            ch = *format++;
135
204M
            break;
136
159M
        case DP_S_FLAGS:
137
159M
            switch (ch) {
138
4.16M
            case '-':
139
4.16M
                flags |= DP_F_MINUS;
140
4.16M
                ch = *format++;
141
4.16M
                break;
142
8
            case '+':
143
8
                flags |= DP_F_PLUS;
144
8
                ch = *format++;
145
8
                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
38.2M
            case '0':
155
38.2M
                flags |= DP_F_ZERO;
156
38.2M
                ch = *format++;
157
38.2M
                break;
158
117M
            default:
159
117M
                state = DP_S_MIN;
160
117M
                break;
161
159M
            }
162
159M
            break;
163
165M
        case DP_S_MIN: /* width */
164
165M
            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
48.6M
                if (min < INT_MAX / 10)
171
48.6M
                    min = 10 * min + char_to_int(ch);
172
0
                else
173
0
                    goto out;
174
48.6M
                ch = *format++;
175
117M
            } else if (ch == '*') {
176
4.93M
                min = va_arg(args, int);
177
4.93M
                if (min < 0) {
178
0
                    flags |= DP_F_MINUS;
179
0
                    min = -min;
180
0
                }
181
4.93M
                ch = *format++;
182
4.93M
                state = DP_S_DOT;
183
4.93M
            } else
184
112M
                state = DP_S_DOT;
185
165M
            break;
186
165M
        case DP_S_DOT:
187
117M
            if (ch == '.') {
188
5.97k
                state = DP_S_MAX;
189
5.97k
                ch = *format++;
190
5.97k
            } else
191
117M
                state = DP_S_MOD;
192
117M
            break;
193
10.5k
        case DP_S_MAX: /* precision */
194
10.5k
            if (ossl_isdigit(ch)) {
195
4.62k
                if (max < 0)
196
2.31k
                    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
4.62k
                if (max < INT_MAX / 10)
203
4.62k
                    max = 10 * max + char_to_int(ch);
204
0
                else
205
0
                    goto out;
206
4.62k
                ch = *format++;
207
5.97k
            } else if (ch == '*') {
208
3.65k
                max = va_arg(args, int);
209
3.65k
                ch = *format++;
210
3.65k
                state = DP_S_MOD;
211
3.65k
            } else {
212
2.31k
                if (max < 0)
213
0
                    max = 0;
214
2.31k
                state = DP_S_MOD;
215
2.31k
            }
216
10.5k
            break;
217
117M
        case DP_S_MOD:
218
117M
            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
8.31M
            case 'l':
229
8.31M
                if (*format == 'l') {
230
14.9k
                    cflags = DP_C_LLONG;
231
14.9k
                    format++;
232
14.9k
                } else
233
8.30M
                    cflags = DP_C_LONG;
234
8.31M
                ch = *format++;
235
8.31M
                break;
236
0
            case 'q':
237
12.0k
            case 'j':
238
12.0k
                cflags = DP_C_LLONG;
239
12.0k
                ch = *format++;
240
12.0k
                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
109M
            default:
254
109M
                break;
255
117M
            }
256
117M
            state = DP_S_CONV;
257
117M
            break;
258
117M
        case DP_S_CONV:
259
117M
            switch (ch) {
260
9.09M
            case 'd':
261
9.09M
            case 'i':
262
9.09M
                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
6.14M
                case DP_C_LONG:
270
6.14M
                    value = va_arg(args, long int);
271
6.14M
                    break;
272
1.85k
                case DP_C_LLONG:
273
1.85k
                    value = va_arg(args, int64_t);
274
1.85k
                    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
2.94M
                default:
282
2.94M
                    value = va_arg(args, int);
283
2.94M
                    break;
284
9.09M
                }
285
9.09M
                if (!fmtint(&desc, value, 10, min, max, flags))
286
0
                    goto out;
287
9.09M
                break;
288
15.9M
            case 'X':
289
15.9M
                flags |= DP_F_UP;
290
                /* FALLTHROUGH */
291
38.7M
            case 'x':
292
38.7M
            case 'o':
293
40.9M
            case 'u':
294
40.9M
                flags |= DP_F_UNSIGNED;
295
40.9M
                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
2.15M
                case DP_C_LONG:
303
2.15M
                    value = va_arg(args, unsigned long int);
304
2.15M
                    break;
305
25.1k
                case DP_C_LLONG:
306
25.1k
                    value = va_arg(args, uint64_t);
307
25.1k
                    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
38.7M
                default:
323
38.7M
                    value = va_arg(args, unsigned int);
324
38.7M
                    break;
325
40.9M
                }
326
40.9M
                if (!fmtint(&desc, value,
327
40.9M
                        ch == 'o' ? 8 : (ch == 'u' ? 10 : 16),
328
40.9M
                        min, max, flags))
329
0
                    goto out;
330
40.9M
                break;
331
40.9M
#ifndef OPENSSL_SYS_UEFI
332
40.9M
            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
36.3M
            case 'c':
373
36.3M
                if (!doapr_outch(&desc, va_arg(args, int)))
374
0
                    goto out;
375
36.3M
                break;
376
36.3M
            case 's':
377
30.9M
                strvalue = va_arg(args, char *);
378
30.9M
                if (max < 0)
379
30.9M
                    max = INT_MAX;
380
30.9M
                if (!fmtstr(&desc, strvalue, flags, min, max))
381
0
                    goto out;
382
30.9M
                break;
383
30.9M
            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
117M
            }
433
117M
            ch = *format++;
434
117M
            state = DP_S_DEFAULT;
435
117M
            flags = cflags = min = 0;
436
117M
            max = -1;
437
117M
            break;
438
62.3M
        case DP_S_DONE:
439
62.3M
            break;
440
0
        default:
441
0
            break;
442
944M
        }
443
944M
    }
444
62.3M
    ret = 1;
445
446
62.3M
out:
447
    /*
448
     * We have to truncate if there is no dynamic buffer and we have filled the
449
     * static buffer.
450
     */
451
62.3M
    if (buffer == NULL) {
452
21.4M
        *truncated = (desc.currlen > desc.maxlen - 1);
453
21.4M
        if (*truncated)
454
469
            desc.currlen = desc.maxlen - 1;
455
21.4M
    }
456
457
62.3M
    if (!doapr_outch(&desc, '\0'))
458
0
        ret = 0;
459
460
62.3M
    *retlen = desc.currlen - 1;
461
62.3M
    *sbuffer = desc.sbuffer;
462
62.3M
    *maxlen = desc.maxlen;
463
464
62.3M
    return ret;
465
62.3M
}
466
467
static int
468
fmtstr(struct pr_desc *desc, const char *value, int flags, int min, int max)
469
30.9M
{
470
30.9M
    int padlen = 0;
471
30.9M
    size_t strln;
472
30.9M
    int cnt = 0;
473
474
30.9M
    if (value == 0)
475
988
        value = "<NULL>";
476
477
30.9M
    strln = OPENSSL_strnlen(value, max < 0 ? SIZE_MAX : (size_t)max);
478
479
30.9M
    if (min >= 0 && strln < INT_MAX) {
480
30.9M
        padlen = min - (int)strln;
481
30.9M
        if (padlen < 0)
482
22.6M
            padlen = 0;
483
30.9M
    }
484
30.9M
    if (max >= 0) {
485
        /*
486
         * Calculate the maximum output including padding.
487
         * Make sure max doesn't overflow into negativity
488
         */
489
30.9M
        if (max < INT_MAX - padlen)
490
5.97k
            max += padlen;
491
30.9M
        else
492
30.9M
            max = INT_MAX;
493
30.9M
    }
494
495
30.9M
    if (!(flags & DP_F_MINUS) && padlen > 0) {
496
        /* cap padlen to max so we can pass it as-is to eob_ok() */
497
4.08M
        if (max >= 0) {
498
4.08M
            if (padlen > max)
499
0
                padlen = max;
500
4.08M
            cnt = padlen;
501
4.08M
        }
502
31.4M
        while (padlen > 0 && eob_ok(desc, padlen)) {
503
27.3M
            if (!doapr_outch(desc, ' '))
504
0
                return 0;
505
27.3M
            --padlen;
506
27.3M
        }
507
4.08M
    }
508
30.9M
    if (max >= 0) {
509
        /* cap strln to (max - cnt) so we can pass it as-is to eob_ok() */
510
30.9M
        if (strln > INT_MAX || (int)strln > max - cnt)
511
0
            strln = max - cnt;
512
30.9M
        cnt += (int)strln;
513
30.9M
    }
514
113M
    while (strln > 0 && eob_ok(desc, strln)) {
515
82.5M
        if (!doapr_outch(desc, *value++))
516
0
            return 0;
517
82.5M
        --strln;
518
82.5M
    }
519
30.9M
    if ((flags & DP_F_MINUS) && padlen > 0) {
520
        /* cap padlen to (max - cnt) so we can pass it as-is to eob_ok() */
521
2.07M
        if (max >= 0) {
522
2.07M
            if (padlen > max - cnt)
523
0
                padlen = max - cnt;
524
2.07M
        }
525
25.6M
        while (padlen > 0 && eob_ok(desc, padlen)) {
526
23.6M
            if (!doapr_outch(desc, ' '))
527
0
                return 0;
528
23.6M
            --padlen;
529
23.6M
        }
530
2.07M
    }
531
30.9M
    return 1;
532
30.9M
}
533
534
static int
535
fmtint(struct pr_desc *desc,
536
    int64_t value, int base, int min, int max, int flags)
537
50.0M
{
538
50.0M
    static const char oct_prefix[] = "0";
539
540
50.0M
    int signvalue = 0;
541
50.0M
    const char *prefix = "";
542
50.0M
    uint64_t uvalue;
543
50.0M
    char convert[DECIMAL_SIZE(value) + 3];
544
50.0M
    int place = 0;
545
50.0M
    int spadlen = 0;
546
50.0M
    int zpadlen = 0;
547
50.0M
    int caps = 0;
548
549
50.0M
    if (max < 0) {
550
        /* A negative precision is taken as if the precision were omitted. */
551
50.0M
        max = 1;
552
50.0M
    } else {
553
        /*
554
         * If a precision is given with an integer conversion,
555
         * the 0 flag is ignored.
556
         */
557
0
        flags &= ~DP_F_ZERO;
558
0
    }
559
50.0M
    uvalue = value;
560
50.0M
    if (!(flags & DP_F_UNSIGNED)) {
561
9.09M
        if (value < 0) {
562
16.2k
            signvalue = '-';
563
16.2k
            uvalue = 0 - (uint64_t)value;
564
9.08M
        } else if (flags & DP_F_PLUS)
565
6
            signvalue = '+';
566
9.08M
        else if (flags & DP_F_SPACE)
567
0
            signvalue = ' ';
568
9.09M
    }
569
50.0M
    if (flags & DP_F_NUM) {
570
0
        if (base == 8)
571
0
            prefix = oct_prefix;
572
0
        if (value != 0) {
573
0
            if (base == 16)
574
0
                prefix = flags & DP_F_UP ? "0X" : "0x";
575
0
        }
576
0
    }
577
50.0M
    if (flags & DP_F_UP)
578
15.9M
        caps = 1;
579
    /* When 0 is printed with an explicit precision 0, the output is empty. */
580
117M
    while (uvalue && (place < (int)sizeof(convert))) {
581
67.7M
        convert[place++] = (caps ? "0123456789ABCDEF" : "0123456789abcdef")
582
67.7M
            [uvalue % (unsigned)base];
583
67.7M
        uvalue = (uvalue / (unsigned)base);
584
67.7M
    }
585
50.0M
    if (place == sizeof(convert))
586
0
        place--;
587
50.0M
    convert[place] = 0;
588
589
    /*
590
     * "#" (alternative form):
591
     *   - For o conversion, it shall increase the precision, if and only
592
     *     if necessary, to force the first digit of the result to be a zero
593
     */
594
50.0M
    zpadlen = max - place - (prefix == oct_prefix);
595
50.0M
    if (zpadlen < 0)
596
22.5M
        zpadlen = 0;
597
50.0M
    spadlen = min - OSSL_MAX(max, place + zpadlen + (signvalue ? 1 : 0) + (int)strlen(prefix));
598
50.0M
    if (spadlen < 0)
599
6.41M
        spadlen = 0;
600
50.0M
    if (flags & DP_F_MINUS) {
601
2.08M
        spadlen = -spadlen;
602
47.9M
    } else if (flags & DP_F_ZERO) {
603
38.2M
        zpadlen = zpadlen + spadlen;
604
38.2M
        spadlen = 0;
605
38.2M
    }
606
607
    /* spaces */
608
59.6M
    while (spadlen > 0 && eob_ok(desc, spadlen)) {
609
9.59M
        if (!doapr_outch(desc, ' '))
610
0
            return 0;
611
9.59M
        --spadlen;
612
9.59M
    }
613
614
    /* sign */
615
50.0M
    if (signvalue)
616
16.2k
        if (!doapr_outch(desc, signvalue))
617
0
            return 0;
618
619
    /* prefix */
620
50.0M
    while (*prefix) {
621
0
        if (!doapr_outch(desc, *prefix))
622
0
            return 0;
623
0
        prefix++;
624
0
    }
625
626
    /* zeros */
627
50.0M
    if (zpadlen > 0) {
628
56.4M
        while (zpadlen > 0 && eob_ok(desc, zpadlen)) {
629
34.4M
            if (!doapr_outch(desc, '0'))
630
0
                return 0;
631
34.4M
            --zpadlen;
632
34.4M
        }
633
21.9M
    }
634
    /* digits */
635
117M
    while (place > 0) {
636
67.7M
        if (!doapr_outch(desc, convert[--place]))
637
0
            return 0;
638
67.7M
    }
639
640
    /* left justified spaces */
641
50.0M
    if (spadlen < 0) {
642
1.95M
        spadlen = -spadlen;
643
644
3.91M
        while (spadlen > 0 && eob_ok(desc, spadlen)) {
645
1.95M
            if (!doapr_outch(desc, ' '))
646
0
                return 0;
647
1.95M
            --spadlen;
648
1.95M
        }
649
1.95M
    }
650
50.0M
    return 1;
651
50.0M
}
652
653
#ifndef OPENSSL_SYS_UEFI
654
655
static LDOUBLE abs_val(LDOUBLE value)
656
0
{
657
0
    LDOUBLE result = value;
658
0
    if (value < 0)
659
0
        result = -value;
660
0
    if (result > 0 && result / 2 == result) /* INF */
661
0
        result = 0;
662
0
    else if (result != result) /* NAN */
663
0
        result = 0;
664
0
    return result;
665
0
}
666
667
static LDOUBLE pow_10(int in_exp)
668
0
{
669
0
    LDOUBLE result = 1;
670
0
    while (in_exp) {
671
0
        result *= 10;
672
0
        in_exp--;
673
0
    }
674
0
    return result;
675
0
}
676
677
static long roundv(LDOUBLE value)
678
0
{
679
0
    long intpart;
680
0
    intpart = (long)value;
681
0
    value = value - intpart;
682
0
    if (value >= 0.5)
683
0
        intpart++;
684
0
    return intpart;
685
0
}
686
687
static int
688
fmtfp(struct pr_desc *desc,
689
    LDOUBLE fvalue, int min, int max, int flags, int style)
690
0
{
691
0
    int signvalue = 0;
692
0
    LDOUBLE ufvalue;
693
0
    LDOUBLE tmpvalue;
694
0
    char iconvert[20];
695
0
    char fconvert[20];
696
0
    char econvert[20];
697
0
    int iplace = 0;
698
0
    int fplace = 0;
699
0
    int eplace = 0;
700
0
    int padlen = 0;
701
0
    int zpadlen = 0;
702
0
    long exp = 0;
703
0
    unsigned long intpart;
704
0
    unsigned long fracpart;
705
0
    unsigned long max10;
706
0
    int realstyle;
707
708
0
    if (max < 0)
709
0
        max = 6;
710
711
0
    if (fvalue < 0)
712
0
        signvalue = '-';
713
0
    else if (flags & DP_F_PLUS)
714
0
        signvalue = '+';
715
0
    else if (flags & DP_F_SPACE)
716
0
        signvalue = ' ';
717
0
    ufvalue = abs_val(fvalue);
718
0
    if (ufvalue == 0 && fvalue != 0) /* INF or NAN? */
719
0
        signvalue = '?';
720
721
    /*
722
     * G_FORMAT sometimes prints like E_FORMAT and sometimes like F_FORMAT
723
     * depending on the number to be printed. Work out which one it is and use
724
     * that from here on.
725
     */
726
0
    if (style == G_FORMAT) {
727
0
        if (ufvalue == 0.0) {
728
0
            realstyle = F_FORMAT;
729
0
        } else if (ufvalue < 0.0001) {
730
0
            realstyle = E_FORMAT;
731
0
        } else if ((max == 0 && ufvalue >= 10)
732
0
            || (max > 0 && ufvalue >= pow_10(max))) {
733
0
            realstyle = E_FORMAT;
734
0
        } else {
735
0
            realstyle = F_FORMAT;
736
0
        }
737
0
    } else {
738
0
        realstyle = style;
739
0
    }
740
741
0
    if (style != F_FORMAT) {
742
0
        tmpvalue = ufvalue;
743
        /* Calculate the exponent */
744
0
        if (ufvalue != 0.0) {
745
0
            while (tmpvalue < 1) {
746
0
                tmpvalue *= 10;
747
0
                exp--;
748
0
            }
749
0
            while (tmpvalue > 10) {
750
0
                tmpvalue /= 10;
751
0
                exp++;
752
0
            }
753
0
        }
754
0
        if (style == G_FORMAT) {
755
            /*
756
             * In G_FORMAT the "precision" represents significant digits. We
757
             * always have at least 1 significant digit.
758
             */
759
0
            if (max == 0)
760
0
                max = 1;
761
            /* Now convert significant digits to decimal places */
762
0
            if (realstyle == F_FORMAT) {
763
0
                max -= (exp + 1);
764
0
                if (max < 0) {
765
                    /*
766
                     * Should not happen. If we're in F_FORMAT then exp < max?
767
                     */
768
0
                    (void)doapr_outch(desc, '\0');
769
0
                    return 0;
770
0
                }
771
0
            } else {
772
                /*
773
                 * In E_FORMAT there is always one significant digit in front
774
                 * of the decimal point, so:
775
                 * significant digits == 1 + decimal places
776
                 */
777
0
                max--;
778
0
            }
779
0
        }
780
0
        if (realstyle == E_FORMAT)
781
0
            ufvalue = tmpvalue;
782
0
    }
783
784
    /*
785
     * By subtracting 65535 (2^16-1) we cancel the low order 15 bits
786
     * of ULONG_MAX to avoid using imprecise floating point values.
787
     */
788
0
    if (ufvalue >= (double)(ULONG_MAX - 65535) + 65536.0) {
789
        /* Number too big */
790
0
        (void)doapr_outch(desc, '\0');
791
0
        return 0;
792
0
    }
793
0
    intpart = (unsigned long)ufvalue;
794
795
    /*
796
     * sorry, we only support 9 digits past the decimal because of our
797
     * conversion method
798
     */
799
0
    if (max > 9)
800
0
        max = 9;
801
802
    /*
803
     * we "cheat" by converting the fractional part to integer by multiplying
804
     * by a factor of 10
805
     */
806
0
    max10 = roundv(pow_10(max));
807
0
    fracpart = roundv(pow_10(max) * (ufvalue - intpart));
808
809
0
    if (fracpart >= max10) {
810
0
        intpart++;
811
0
        fracpart -= max10;
812
0
    }
813
814
    /* convert integer part */
815
0
    do {
816
0
        iconvert[iplace++] = "0123456789"[intpart % 10];
817
0
        intpart = (intpart / 10);
818
0
    } while (intpart && (iplace < (int)sizeof(iconvert)));
819
0
    if (iplace == sizeof(iconvert))
820
0
        iplace--;
821
0
    iconvert[iplace] = 0;
822
823
    /* convert fractional part */
824
0
    while (fplace < max) {
825
0
        if (style == G_FORMAT && fplace == 0 && (fracpart % 10) == 0) {
826
            /* We strip trailing zeros in G_FORMAT */
827
0
            max--;
828
0
            fracpart = fracpart / 10;
829
0
            if (fplace < max)
830
0
                continue;
831
0
            break;
832
0
        }
833
0
        fconvert[fplace++] = "0123456789"[fracpart % 10];
834
0
        fracpart = (fracpart / 10);
835
0
    }
836
837
0
    fconvert[fplace] = 0;
838
839
    /* convert exponent part */
840
0
    if (realstyle == E_FORMAT) {
841
0
        int tmpexp;
842
0
        if (exp < 0)
843
0
            tmpexp = -exp;
844
0
        else
845
0
            tmpexp = exp;
846
847
0
        do {
848
0
            econvert[eplace++] = "0123456789"[tmpexp % 10];
849
0
            tmpexp = (tmpexp / 10);
850
0
        } while (tmpexp > 0 && eplace < (int)sizeof(econvert));
851
        /* Exponent is huge!! Too big to print */
852
0
        if (tmpexp > 0) {
853
0
            (void)doapr_outch(desc, '\0');
854
0
            return 0;
855
0
        }
856
        /* Add a leading 0 for single digit exponents */
857
0
        if (eplace == 1)
858
0
            econvert[eplace++] = '0';
859
0
    }
860
861
    /*
862
     * -1 for decimal point (if we have one, i.e. max > 0),
863
     * another -1 if we are printing a sign
864
     */
865
0
    padlen = min - iplace - max - (max > 0 ? 1 : 0) - ((signvalue) ? 1 : 0);
866
    /* Take some off for exponent prefix "+e" and exponent */
867
0
    if (realstyle == E_FORMAT)
868
0
        padlen -= 2 + eplace;
869
0
    zpadlen = max - fplace;
870
0
    if (zpadlen < 0)
871
0
        zpadlen = 0;
872
0
    if (padlen < 0)
873
0
        padlen = 0;
874
0
    if (flags & DP_F_MINUS)
875
0
        padlen = -padlen;
876
877
0
    if ((flags & DP_F_ZERO) && (padlen > 0)) {
878
0
        if (signvalue) {
879
0
            if (!doapr_outch(desc, signvalue))
880
0
                return 0;
881
0
            --padlen;
882
0
            signvalue = 0;
883
0
        }
884
0
        while (padlen > 0 && eob_ok(desc, padlen)) {
885
0
            if (!doapr_outch(desc, '0'))
886
0
                return 0;
887
0
            --padlen;
888
0
        }
889
0
        padlen = 0;
890
0
    }
891
0
    while (padlen > 0 && eob_ok(desc, padlen)) {
892
0
        if (!doapr_outch(desc, ' '))
893
0
            return 0;
894
0
        --padlen;
895
0
    }
896
0
    padlen = 0;
897
0
    if (signvalue && !doapr_outch(desc, signvalue))
898
0
        return 0;
899
900
0
    while (iplace > 0) {
901
0
        if (!doapr_outch(desc, iconvert[--iplace]))
902
0
            return 0;
903
0
    }
904
905
    /*
906
     * Decimal point. This should probably use locale to find the correct
907
     * char to print out.
908
     */
909
0
    if (max > 0 || (flags & DP_F_NUM)) {
910
0
        if (!doapr_outch(desc, '.'))
911
0
            return 0;
912
913
0
        while (fplace > 0) {
914
0
            if (!doapr_outch(desc, fconvert[--fplace]))
915
0
                return 0;
916
0
        }
917
0
    }
918
0
    while (zpadlen > 0 && eob_ok(desc, zpadlen)) {
919
0
        if (!doapr_outch(desc, '0'))
920
0
            return 0;
921
0
        --zpadlen;
922
0
    }
923
0
    if (realstyle == E_FORMAT) {
924
0
        char ech;
925
926
0
        if ((flags & DP_F_UP) == 0)
927
0
            ech = 'e';
928
0
        else
929
0
            ech = 'E';
930
0
        if (!doapr_outch(desc, ech))
931
0
            return 0;
932
0
        if (exp < 0) {
933
0
            if (!doapr_outch(desc, '-'))
934
0
                return 0;
935
0
        } else {
936
0
            if (!doapr_outch(desc, '+'))
937
0
                return 0;
938
0
        }
939
0
        while (eplace > 0) {
940
0
            if (!doapr_outch(desc, econvert[--eplace]))
941
0
                return 0;
942
0
        }
943
0
    }
944
945
0
    if (padlen < 0) {
946
0
        padlen = -padlen;
947
948
0
        while (padlen > 0 && eob_ok(desc, padlen)) {
949
0
            if (!doapr_outch(desc, ' '))
950
0
                return 0;
951
0
            --padlen;
952
0
        }
953
0
    }
954
0
    return 1;
955
0
}
956
957
#endif /* OPENSSL_SYS_UEFI */
958
959
3.54k
#define BUFFER_INC 1024
960
961
static int
962
doapr_outch(struct pr_desc *desc, int c)
963
432M
{
964
    /* If we haven't at least one buffer, someone has done a big booboo */
965
432M
    if (!ossl_assert(desc->sbuffer != NULL || desc->buffer != NULL))
966
0
        return 0;
967
968
    /* |currlen| must always be <= |*maxlen| */
969
432M
    if (!ossl_assert(desc->currlen <= desc->maxlen))
970
0
        return 0;
971
972
432M
    if (desc->buffer != NULL && desc->currlen == desc->maxlen) {
973
1.77k
        if (desc->maxlen > INT_MAX - BUFFER_INC)
974
0
            return 0;
975
976
1.77k
        desc->maxlen += BUFFER_INC;
977
1.77k
        if (*(desc->buffer) == NULL) {
978
54
            if ((*(desc->buffer) = OPENSSL_malloc(desc->maxlen)) == NULL)
979
0
                return 0;
980
54
            if (desc->currlen > 0) {
981
54
                if (!ossl_assert(desc->sbuffer != NULL))
982
0
                    return 0;
983
54
                memcpy(*(desc->buffer), desc->sbuffer, desc->currlen);
984
54
            }
985
54
            desc->sbuffer = NULL;
986
1.71k
        } else {
987
1.71k
            char *tmpbuf;
988
989
1.71k
            tmpbuf = OPENSSL_realloc(*(desc->buffer), desc->maxlen);
990
1.71k
            if (tmpbuf == NULL)
991
0
                return 0;
992
1.71k
            *(desc->buffer) = tmpbuf;
993
1.71k
        }
994
1.77k
    }
995
996
432M
    if (desc->currlen < desc->maxlen) {
997
432M
        if (desc->sbuffer)
998
431M
            (desc->sbuffer)[(desc->currlen)++] = (char)c;
999
1.77M
        else
1000
1.77M
            (*(desc->buffer))[(desc->currlen)++] = (char)c;
1001
432M
    }
1002
1003
432M
    if (desc->pos < LLONG_MAX)
1004
432M
        desc->pos++;
1005
1006
432M
    return 1;
1007
432M
}
1008
1009
/**
1010
 * Checks if we reached an end of a non-extandable buffer (sbuffer) and updates
1011
 * desc->pos by adding the amount of bytes left if the end of buffer is reached.
1012
 * That allow quickly short-circuiting long loops with unreasonably long paddings
1013
 * and widths.
1014
 *
1015
 * @param desc Pointer to a print descriptor.
1016
 * @param left Bytes left in the chunk caller is currently processing.
1017
 * @return 0 - end of buffer is reached, no need to continue;
1018
 *         1 - there is still space in the buffer, the caller may continue to
1019
 *         try to output bytes in the buffer with doapr_outch().
1020
 */
1021
static int eob_ok(struct pr_desc *desc, long long left)
1022
179M
{
1023
    /*
1024
     * desc->buffer is auto-sizeable, so we are never supposed to reach the end
1025
     * of it.
1026
     */
1027
179M
    if (desc->buffer != NULL)
1028
108M
        return 1;
1029
1030
71.0M
    if (desc->currlen >= desc->maxlen) {
1031
599
        if (left > 0) {
1032
599
            if (desc->pos < LLONG_MAX - left) {
1033
599
                desc->pos += left;
1034
599
            } else {
1035
0
                desc->pos = LLONG_MAX;
1036
0
            }
1037
599
        }
1038
1039
599
        return 0;
1040
599
    }
1041
1042
71.0M
    return 1;
1043
71.0M
}
1044
1045
/***************************************************************************/
1046
1047
int BIO_printf(BIO *bio, const char *format, ...)
1048
344M
{
1049
344M
    va_list args;
1050
344M
    int ret;
1051
1052
344M
    va_start(args, format);
1053
1054
344M
    ret = BIO_vprintf(bio, format, args);
1055
1056
344M
    va_end(args);
1057
344M
    return ret;
1058
344M
}
1059
1060
int BIO_vprintf(BIO *bio, const char *format, va_list args)
1061
275M
{
1062
275M
    int ret;
1063
275M
    size_t retlen;
1064
275M
    char hugebuf[1024 * 2]; /* Was previously 10k, which is unreasonable
1065
                             * in small-stack environments, like threads
1066
                             * or DOS programs. */
1067
275M
    char *hugebufp = hugebuf;
1068
275M
    size_t hugebufsize = sizeof(hugebuf);
1069
275M
    char *dynbuf = NULL;
1070
275M
    int ignored;
1071
1072
275M
    dynbuf = NULL;
1073
275M
    if (!_dopr(&hugebufp, &dynbuf, &hugebufsize, &retlen, &ignored, format,
1074
275M
            args)) {
1075
0
        OPENSSL_free(dynbuf);
1076
0
        return -1;
1077
0
    }
1078
275M
    if (dynbuf) {
1079
720
        ret = BIO_write(bio, dynbuf, (int)retlen);
1080
720
        OPENSSL_free(dynbuf);
1081
275M
    } else {
1082
275M
        ret = BIO_write(bio, hugebuf, (int)retlen);
1083
275M
    }
1084
275M
    return ret;
1085
275M
}
1086
1087
/*
1088
 * As snprintf is not available everywhere, we provide our own
1089
 * implementation. This function has nothing to do with BIOs, but it's
1090
 * closely related to BIO_printf, and we need *some* name prefix ... (XXX the
1091
 * function should be renamed, but to what?)
1092
 */
1093
int BIO_snprintf(char *buf, size_t n, const char *format, ...)
1094
121M
{
1095
121M
    va_list args;
1096
121M
    int ret;
1097
1098
121M
    va_start(args, format);
1099
1100
121M
    ret = BIO_vsnprintf(buf, n, format, args);
1101
1102
121M
    va_end(args);
1103
121M
    return ret;
1104
121M
}
1105
1106
int BIO_vsnprintf(char *buf, size_t n, const char *format, va_list args)
1107
124M
{
1108
124M
    size_t retlen;
1109
124M
    int truncated;
1110
1111
124M
    if (!_dopr(&buf, NULL, &n, &retlen, &truncated, format, args))
1112
0
        return -1;
1113
1114
124M
    if (truncated)
1115
        /*
1116
         * In case of truncation, return -1 like traditional snprintf.
1117
         * (Current drafts for ISO/IEC 9899 say snprintf should return the
1118
         * number of characters that would have been written, had the buffer
1119
         * been large enough.)
1120
         */
1121
8.83k
        return -1;
1122
124M
    return (retlen <= INT_MAX) ? (int)retlen : -1;
1123
124M
}