Coverage Report

Created: 2026-04-09 06:50

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