Coverage Report

Created: 2026-04-09 06:50

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