Coverage Report

Created: 2026-04-01 06:39

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
89.9M
#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
558M
#define DP_S_DEFAULT 0
57
394M
#define DP_S_FLAGS 1
58
403M
#define DP_S_MIN 2
59
332M
#define DP_S_DOT 3
60
74.4k
#define DP_S_MAX 4
61
332M
#define DP_S_MOD 5
62
332M
#define DP_S_CONV 6
63
1.62G
#define DP_S_DONE 7
64
65
/* format flags - Bits */
66
/* left-aligned padding */
67
180M
#define DP_F_MINUS (1 << 0)
68
/* print an explicit '+' for a value with positive sign */
69
12.9M
#define DP_F_PLUS (1 << 1)
70
/* print an explicit ' ' for a value with positive sign */
71
12.9M
#define DP_F_SPACE (1 << 2)
72
/* print 0/0x prefix for octal/hex and decimal point for floating point */
73
73.8M
#define DP_F_NUM (1 << 3)
74
/* print leading zeroes */
75
127M
#define DP_F_ZERO (1 << 4)
76
/* print HEX in UPPERcase */
77
97.4M
#define DP_F_UP (1 << 5)
78
/* treat value as unsigned */
79
134M
#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
23.8M
#define DP_C_LONG 3
85
0
#define DP_C_LDOUBLE 4
86
64.1k
#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
71.5M
#define char_to_int(p) (p - '0')
97
147M
#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
89.9M
{
105
89.9M
    char ch;
106
89.9M
    int64_t value;
107
89.9M
#ifndef OPENSSL_SYS_UEFI
108
89.9M
    LDOUBLE fvalue;
109
89.9M
#endif
110
89.9M
    char *strvalue;
111
89.9M
    int min;
112
89.9M
    int max;
113
89.9M
    int state;
114
89.9M
    int flags;
115
89.9M
    int cflags;
116
89.9M
    struct pr_desc desc = { *sbuffer, buffer, 0, *maxlen, 0 };
117
89.9M
    int ret = 0;
118
119
89.9M
    state = DP_S_DEFAULT;
120
89.9M
    flags = cflags = min = 0;
121
89.9M
    max = -1;
122
89.9M
    ch = *format++;
123
124
1.44G
    while (state != DP_S_DONE) {
125
1.35G
        if (ch == '\0')
126
89.9M
            state = DP_S_DONE;
127
128
1.35G
        switch (state) {
129
302M
        case DP_S_DEFAULT:
130
302M
            if (ch == '%')
131
166M
                state = DP_S_FLAGS;
132
136M
            else if (!doapr_outch(&desc, ch))
133
0
                goto out;
134
302M
            ch = *format++;
135
302M
            break;
136
228M
        case DP_S_FLAGS:
137
228M
            switch (ch) {
138
6.01M
            case '-':
139
6.01M
                flags |= DP_F_MINUS;
140
6.01M
                ch = *format++;
141
6.01M
                break;
142
275
            case '+':
143
275
                flags |= DP_F_PLUS;
144
275
                ch = *format++;
145
275
                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
56.6M
            case '0':
155
56.6M
                flags |= DP_F_ZERO;
156
56.6M
                ch = *format++;
157
56.6M
                break;
158
166M
            default:
159
166M
                state = DP_S_MIN;
160
166M
                break;
161
228M
            }
162
228M
            break;
163
237M
        case DP_S_MIN: /* width */
164
237M
            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
71.4M
                if (min < INT_MAX / 10)
171
71.4M
                    min = 10 * min + char_to_int(ch);
172
0
                else
173
0
                    goto out;
174
71.4M
                ch = *format++;
175
166M
            } else if (ch == '*') {
176
6.94M
                min = va_arg(args, int);
177
6.94M
                if (min < 0) {
178
0
                    flags |= DP_F_MINUS;
179
0
                    min = -min;
180
0
                }
181
6.94M
                ch = *format++;
182
6.94M
                state = DP_S_DOT;
183
6.94M
            } else
184
159M
                state = DP_S_DOT;
185
237M
            break;
186
237M
        case DP_S_DOT:
187
166M
            if (ch == '.') {
188
25.8k
                state = DP_S_MAX;
189
25.8k
                ch = *format++;
190
25.8k
            } else
191
166M
                state = DP_S_MOD;
192
166M
            break;
193
48.6k
        case DP_S_MAX: /* precision */
194
48.6k
            if (ossl_isdigit(ch)) {
195
22.7k
                if (max < 0)
196
11.3k
                    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
22.7k
                if (max < INT_MAX / 10)
203
22.7k
                    max = 10 * max + char_to_int(ch);
204
0
                else
205
0
                    goto out;
206
22.7k
                ch = *format++;
207
25.8k
            } else if (ch == '*') {
208
14.4k
                max = va_arg(args, int);
209
14.4k
                ch = *format++;
210
14.4k
                state = DP_S_MOD;
211
14.4k
            } else {
212
11.3k
                if (max < 0)
213
0
                    max = 0;
214
11.3k
                state = DP_S_MOD;
215
11.3k
            }
216
48.6k
            break;
217
166M
        case DP_S_MOD:
218
166M
            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
11.9M
            case 'l':
229
11.9M
                if (*format == 'l') {
230
16.9k
                    cflags = DP_C_LLONG;
231
16.9k
                    format++;
232
16.9k
                } else
233
11.9M
                    cflags = DP_C_LONG;
234
11.9M
                ch = *format++;
235
11.9M
                break;
236
0
            case 'q':
237
15.1k
            case 'j':
238
15.1k
                cflags = DP_C_LLONG;
239
15.1k
                ch = *format++;
240
15.1k
                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
154M
            default:
254
154M
                break;
255
166M
            }
256
166M
            state = DP_S_CONV;
257
166M
            break;
258
166M
        case DP_S_CONV:
259
166M
            switch (ch) {
260
12.9M
            case 'd':
261
12.9M
            case 'i':
262
12.9M
                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
8.76M
                case DP_C_LONG:
270
8.76M
                    value = va_arg(args, long int);
271
8.76M
                    break;
272
4.57k
                case DP_C_LLONG:
273
4.57k
                    value = va_arg(args, int64_t);
274
4.57k
                    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
4.20M
                default:
282
4.20M
                    value = va_arg(args, int);
283
4.20M
                    break;
284
12.9M
                }
285
12.9M
                if (!fmtint(&desc, value, 10, min, max, flags))
286
0
                    goto out;
287
12.9M
                break;
288
23.5M
            case 'X':
289
23.5M
                flags |= DP_F_UP;
290
                /* FALLTHROUGH */
291
57.7M
            case 'x':
292
57.7M
            case 'o':
293
60.8M
            case 'u':
294
60.8M
                flags |= DP_F_UNSIGNED;
295
60.8M
                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
3.18M
                case DP_C_LONG:
303
3.18M
                    value = va_arg(args, unsigned long int);
304
3.18M
                    break;
305
27.5k
                case DP_C_LLONG:
306
27.5k
                    value = va_arg(args, uint64_t);
307
27.5k
                    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
57.6M
                default:
323
57.6M
                    value = va_arg(args, unsigned int);
324
57.6M
                    break;
325
60.8M
                }
326
60.8M
                if (!fmtint(&desc, value,
327
60.8M
                        ch == 'o' ? 8 : (ch == 'u' ? 10 : 16),
328
60.8M
                        min, max, flags))
329
0
                    goto out;
330
60.8M
                break;
331
60.8M
#ifndef OPENSSL_SYS_UEFI
332
60.8M
            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
42.1M
            case 'c':
373
42.1M
                if (!doapr_outch(&desc, va_arg(args, int)))
374
0
                    goto out;
375
42.1M
                break;
376
50.1M
            case 's':
377
50.1M
                strvalue = va_arg(args, char *);
378
50.1M
                if (max < 0)
379
50.0M
                    max = INT_MAX;
380
50.1M
                if (!fmtstr(&desc, strvalue, flags, min, max))
381
0
                    goto out;
382
50.1M
                break;
383
50.1M
            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
166M
            }
433
166M
            ch = *format++;
434
166M
            state = DP_S_DEFAULT;
435
166M
            flags = cflags = min = 0;
436
166M
            max = -1;
437
166M
            break;
438
89.9M
        case DP_S_DONE:
439
89.9M
            break;
440
0
        default:
441
0
            break;
442
1.35G
        }
443
1.35G
    }
444
89.9M
    ret = 1;
445
446
89.9M
out:
447
    /*
448
     * We have to truncate if there is no dynamic buffer and we have filled the
449
     * static buffer.
450
     */
451
89.9M
    if (buffer == NULL) {
452
23.2M
        *truncated = (desc.currlen > desc.maxlen - 1);
453
23.2M
        if (*truncated)
454
546
            desc.currlen = desc.maxlen - 1;
455
23.2M
    }
456
457
89.9M
    if (!doapr_outch(&desc, '\0'))
458
0
        ret = 0;
459
460
89.9M
    *retlen = desc.currlen - 1;
461
89.9M
    *sbuffer = desc.sbuffer;
462
89.9M
    *maxlen = desc.maxlen;
463
464
89.9M
    return ret;
465
89.9M
}
466
467
static int
468
fmtstr(struct pr_desc *desc, const char *value, int flags, int min, int max)
469
50.1M
{
470
50.1M
    int padlen = 0;
471
50.1M
    size_t strln;
472
50.1M
    int cnt = 0;
473
474
50.1M
    if (value == 0)
475
4.53k
        value = "<NULL>";
476
477
50.1M
    strln = OPENSSL_strnlen(value, max < 0 ? SIZE_MAX : (size_t)max);
478
479
50.1M
    if (min >= 0 && strln < INT_MAX) {
480
50.1M
        padlen = min - (int)strln;
481
50.1M
        if (padlen < 0)
482
38.4M
            padlen = 0;
483
50.1M
    }
484
50.1M
    if (max >= 0) {
485
        /*
486
         * Calculate the maximum output including padding.
487
         * Make sure max doesn't overflow into negativity
488
         */
489
50.1M
        if (max < INT_MAX - padlen)
490
25.8k
            max += padlen;
491
50.0M
        else
492
50.0M
            max = INT_MAX;
493
50.1M
    }
494
495
50.1M
    if (!(flags & DP_F_MINUS) && padlen > 0) {
496
        /* cap padlen to max so we can pass it as-is to eob_ok() */
497
6.14M
        if (max >= 0) {
498
6.14M
            if (padlen > max)
499
0
                padlen = max;
500
6.14M
            cnt = padlen;
501
6.14M
        }
502
49.6M
        while (padlen > 0 && eob_ok(desc, padlen)) {
503
43.5M
            if (!doapr_outch(desc, ' '))
504
0
                return 0;
505
43.5M
            --padlen;
506
43.5M
        }
507
6.14M
    }
508
50.1M
    if (max >= 0) {
509
        /* cap strln to (max - cnt) so we can pass it as-is to eob_ok() */
510
50.1M
        if (strln > INT_MAX || (int)strln > max - cnt)
511
0
            strln = max - cnt;
512
50.1M
        cnt += (int)strln;
513
50.1M
    }
514
168M
    while (strln > 0 && eob_ok(desc, strln)) {
515
118M
        if (!doapr_outch(desc, *value++))
516
0
            return 0;
517
118M
        --strln;
518
118M
    }
519
50.1M
    if ((flags & DP_F_MINUS) && padlen > 0) {
520
        /* cap padlen to (max - cnt) so we can pass it as-is to eob_ok() */
521
3.00M
        if (max >= 0) {
522
3.00M
            if (padlen > max - cnt)
523
0
                padlen = max - cnt;
524
3.00M
        }
525
35.9M
        while (padlen > 0 && eob_ok(desc, padlen)) {
526
32.9M
            if (!doapr_outch(desc, ' '))
527
0
                return 0;
528
32.9M
            --padlen;
529
32.9M
        }
530
3.00M
    }
531
50.1M
    return 1;
532
50.1M
}
533
534
static int
535
fmtint(struct pr_desc *desc,
536
    int64_t value, int base, int min, int max, int flags)
537
73.8M
{
538
73.8M
    static const char oct_prefix[] = "0";
539
540
73.8M
    int signvalue = 0;
541
73.8M
    const char *prefix = "";
542
73.8M
    uint64_t uvalue;
543
73.8M
    char convert[DECIMAL_SIZE(value) + 3];
544
73.8M
    int place = 0;
545
73.8M
    int spadlen = 0;
546
73.8M
    int zpadlen = 0;
547
73.8M
    int caps = 0;
548
549
73.8M
    if (max < 0) {
550
        /* A negative precision is taken as if the precision were omitted. */
551
73.8M
        max = 1;
552
73.8M
    } 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
73.8M
    uvalue = value;
560
73.8M
    if (!(flags & DP_F_UNSIGNED)) {
561
12.9M
        if (value < 0) {
562
11.8k
            signvalue = '-';
563
11.8k
            uvalue = 0 - (uint64_t)value;
564
12.9M
        } else if (flags & DP_F_PLUS)
565
227
            signvalue = '+';
566
12.9M
        else if (flags & DP_F_SPACE)
567
0
            signvalue = ' ';
568
12.9M
    }
569
73.8M
    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
73.8M
    if (flags & DP_F_UP)
578
23.5M
        caps = 1;
579
    /* When 0 is printed with an explicit precision 0, the output is empty. */
580
182M
    while (uvalue && (place < (int)sizeof(convert))) {
581
108M
        convert[place++] = (caps ? "0123456789ABCDEF" : "0123456789abcdef")
582
108M
            [uvalue % (unsigned)base];
583
108M
        uvalue = (uvalue / (unsigned)base);
584
108M
    }
585
73.8M
    if (place == sizeof(convert))
586
0
        place--;
587
73.8M
    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
73.8M
    zpadlen = max - place - (prefix == oct_prefix);
595
73.8M
    if (zpadlen < 0)
596
36.6M
        zpadlen = 0;
597
73.8M
    spadlen = min - OSSL_MAX(max, place + zpadlen + (signvalue ? 1 : 0) + (int)strlen(prefix));
598
73.8M
    if (spadlen < 0)
599
9.20M
        spadlen = 0;
600
73.8M
    if (flags & DP_F_MINUS) {
601
3.00M
        spadlen = -spadlen;
602
70.8M
    } else if (flags & DP_F_ZERO) {
603
56.6M
        zpadlen = zpadlen + spadlen;
604
56.6M
        spadlen = 0;
605
56.6M
    }
606
607
    /* spaces */
608
86.5M
    while (spadlen > 0 && eob_ok(desc, spadlen)) {
609
12.6M
        if (!doapr_outch(desc, ' '))
610
0
            return 0;
611
12.6M
        --spadlen;
612
12.6M
    }
613
614
    /* sign */
615
73.8M
    if (signvalue)
616
12.1k
        if (!doapr_outch(desc, signvalue))
617
0
            return 0;
618
619
    /* prefix */
620
73.8M
    while (*prefix) {
621
0
        if (!doapr_outch(desc, *prefix))
622
0
            return 0;
623
0
        prefix++;
624
0
    }
625
626
    /* zeros */
627
73.8M
    if (zpadlen > 0) {
628
73.3M
        while (zpadlen > 0 && eob_ok(desc, zpadlen)) {
629
44.2M
            if (!doapr_outch(desc, '0'))
630
0
                return 0;
631
44.2M
            --zpadlen;
632
44.2M
        }
633
29.0M
    }
634
    /* digits */
635
182M
    while (place > 0) {
636
108M
        if (!doapr_outch(desc, convert[--place]))
637
0
            return 0;
638
108M
    }
639
640
    /* left justified spaces */
641
73.8M
    if (spadlen < 0) {
642
2.87M
        spadlen = -spadlen;
643
644
5.74M
        while (spadlen > 0 && eob_ok(desc, spadlen)) {
645
2.87M
            if (!doapr_outch(desc, ' '))
646
0
                return 0;
647
2.87M
            --spadlen;
648
2.87M
        }
649
2.87M
    }
650
73.8M
    return 1;
651
73.8M
}
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.83k
#define BUFFER_INC 1024
960
961
static int
962
doapr_outch(struct pr_desc *desc, int c)
963
632M
{
964
    /* If we haven't at least one buffer, someone has done a big booboo */
965
632M
    if (!ossl_assert(desc->sbuffer != NULL || desc->buffer != NULL))
966
0
        return 0;
967
968
    /* |currlen| must always be <= |*maxlen| */
969
632M
    if (!ossl_assert(desc->currlen <= desc->maxlen))
970
0
        return 0;
971
972
632M
    if (desc->buffer != NULL && desc->currlen == desc->maxlen) {
973
1.91k
        if (desc->maxlen > INT_MAX - BUFFER_INC)
974
0
            return 0;
975
976
1.91k
        desc->maxlen += BUFFER_INC;
977
1.91k
        if (*(desc->buffer) == NULL) {
978
45
            if ((*(desc->buffer) = OPENSSL_malloc(desc->maxlen)) == NULL)
979
0
                return 0;
980
45
            if (desc->currlen > 0) {
981
45
                if (!ossl_assert(desc->sbuffer != NULL))
982
0
                    return 0;
983
45
                memcpy(*(desc->buffer), desc->sbuffer, desc->currlen);
984
45
            }
985
45
            desc->sbuffer = NULL;
986
1.87k
        } else {
987
1.87k
            char *tmpbuf;
988
989
1.87k
            tmpbuf = OPENSSL_realloc(*(desc->buffer), desc->maxlen);
990
1.87k
            if (tmpbuf == NULL)
991
0
                return 0;
992
1.87k
            *(desc->buffer) = tmpbuf;
993
1.87k
        }
994
1.91k
    }
995
996
632M
    if (desc->currlen < desc->maxlen) {
997
632M
        if (desc->sbuffer)
998
630M
            (desc->sbuffer)[(desc->currlen)++] = (char)c;
999
1.92M
        else
1000
1.92M
            (*(desc->buffer))[(desc->currlen)++] = (char)c;
1001
632M
    }
1002
1003
632M
    if (desc->pos < LLONG_MAX)
1004
632M
        desc->pos++;
1005
1006
632M
    return 1;
1007
632M
}
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
255M
{
1023
    /*
1024
     * desc->buffer is auto-sizeable, so we are never supposed to reach the end
1025
     * of it.
1026
     */
1027
255M
    if (desc->buffer != NULL)
1028
171M
        return 1;
1029
1030
83.9M
    if (desc->currlen >= desc->maxlen) {
1031
686
        if (left > 0) {
1032
686
            if (desc->pos < LLONG_MAX - left) {
1033
686
                desc->pos += left;
1034
686
            } else {
1035
0
                desc->pos = LLONG_MAX;
1036
0
            }
1037
686
        }
1038
1039
686
        return 0;
1040
686
    }
1041
1042
83.9M
    return 1;
1043
83.9M
}
1044
1045
/***************************************************************************/
1046
1047
int BIO_printf(BIO *bio, const char *format, ...)
1048
370M
{
1049
370M
    va_list args;
1050
370M
    int ret;
1051
1052
370M
    va_start(args, format);
1053
1054
370M
    ret = BIO_vprintf(bio, format, args);
1055
1056
370M
    va_end(args);
1057
370M
    return ret;
1058
370M
}
1059
1060
int BIO_vprintf(BIO *bio, const char *format, va_list args)
1061
302M
{
1062
302M
    int ret;
1063
302M
    size_t retlen;
1064
302M
    char hugebuf[1024 * 2]; /* Was previously 10k, which is unreasonable
1065
                             * in small-stack environments, like threads
1066
                             * or DOS programs. */
1067
302M
    char *hugebufp = hugebuf;
1068
302M
    size_t hugebufsize = sizeof(hugebuf);
1069
302M
    char *dynbuf = NULL;
1070
302M
    int ignored;
1071
1072
302M
    dynbuf = NULL;
1073
302M
    if (!_dopr(&hugebufp, &dynbuf, &hugebufsize, &retlen, &ignored, format,
1074
302M
            args)) {
1075
0
        OPENSSL_free(dynbuf);
1076
0
        return -1;
1077
0
    }
1078
302M
    if (dynbuf) {
1079
692
        ret = BIO_write(bio, dynbuf, (int)retlen);
1080
692
        OPENSSL_free(dynbuf);
1081
302M
    } else {
1082
302M
        ret = BIO_write(bio, hugebuf, (int)retlen);
1083
302M
    }
1084
302M
    return ret;
1085
302M
}
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
120M
{
1095
120M
    va_list args;
1096
120M
    int ret;
1097
1098
120M
    va_start(args, format);
1099
1100
120M
    ret = BIO_vsnprintf(buf, n, format, args);
1101
1102
120M
    va_end(args);
1103
120M
    return ret;
1104
120M
}
1105
1106
int BIO_vsnprintf(char *buf, size_t n, const char *format, va_list args)
1107
123M
{
1108
123M
    size_t retlen;
1109
123M
    int truncated;
1110
1111
123M
    if (!_dopr(&buf, NULL, &n, &retlen, &truncated, format, args))
1112
0
        return -1;
1113
1114
123M
    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
9.61k
        return -1;
1122
123M
    return (retlen <= INT_MAX) ? (int)retlen : -1;
1123
123M
}