Coverage Report

Created: 2025-12-04 06:33

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