Coverage Report

Created: 2025-06-13 06:58

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