Coverage Report

Created: 2023-06-08 06:40

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