Coverage Report

Created: 2025-07-11 06:57

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