Coverage Report

Created: 2025-01-28 07:34

/src/fluent-bit/src/flb_base64.c
Line
Count
Source (jump to first uncovered line)
1
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2
3
/*  Fluent Bit
4
 *  ==========
5
 *  Copyright (C) 2019-2021 The Fluent Bit Authors
6
 *
7
 *  Licensed under the Apache License, Version 2.0 (the "License");
8
 *  you may not use this file except in compliance with the License.
9
 *  You may obtain a copy of the License at
10
 *
11
 *      http://www.apache.org/licenses/LICENSE-2.0
12
 *
13
 *  Unless required by applicable law or agreed to in writing, software
14
 *  distributed under the License is distributed on an "AS IS" BASIS,
15
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
 *  See the License for the specific language governing permissions and
17
 *  limitations under the License.
18
 */
19
20
/* This code is based on base64.c from the mbedtls-2.25.0 Library distribution,
21
 * as originally written by Paul Bakker, et al., and forked by the Fluent Bit
22
 * project to provide performant base64 encoding and decoding routines.
23
 * The 2.25.0 implementation is included rather than 2.26.0+ implementation due
24
 * to performance degradation introduced in 2.26.0.
25
 *
26
 * Method and variable names are changed by the Fluent Bit authors to maintain
27
 * consistency with the Fluent Bit project.
28
 * The self test section of the code was removed by the Fluent Bit authors.
29
 * Other minor changes are made by the Fluent Bit authors.
30
 *
31
 * The original source file base64.c is copyright and licensed as follows;
32
 *
33
 *  RFC 1521 base64 encoding/decoding
34
 *
35
 *  Copyright The Mbed TLS Contributors
36
 *  SPDX-License-Identifier: Apache-2.0
37
 *
38
 *  Licensed under the Apache License, Version 2.0 (the "License"); you may
39
 *  not use this file except in compliance with the License.
40
 *  You may obtain a copy of the License at
41
 *
42
 *  http://www.apache.org/licenses/LICENSE-2.0
43
 *
44
 *  Unless required by applicable law or agreed to in writing, software
45
 *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
46
 *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
47
 *  See the License for the specific language governing permissions and
48
 *  limitations under the License.
49
 */
50
51
#include <fluent-bit/flb_base64.h>
52
53
#include <stdint.h>
54
55
static const unsigned char base64_enc_map[64] =
56
{
57
    'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',
58
    'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',
59
    'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
60
    'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n',
61
    'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
62
    'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7',
63
    '8', '9', '+', '/'
64
};
65
66
static const unsigned char base64_dec_map[128] =
67
{
68
    127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
69
    127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
70
    127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
71
    127, 127, 127, 127, 127, 127, 127, 127, 127, 127,
72
    127, 127, 127,  62, 127, 127, 127,  63,  52,  53,
73
     54,  55,  56,  57,  58,  59,  60,  61, 127, 127,
74
    127,  64, 127, 127, 127,   0,   1,   2,   3,   4,
75
      5,   6,   7,   8,   9,  10,  11,  12,  13,  14,
76
     15,  16,  17,  18,  19,  20,  21,  22,  23,  24,
77
     25, 127, 127, 127, 127, 127, 127,  26,  27,  28,
78
     29,  30,  31,  32,  33,  34,  35,  36,  37,  38,
79
     39,  40,  41,  42,  43,  44,  45,  46,  47,  48,
80
     49,  50,  51, 127, 127, 127, 127, 127
81
};
82
83
692
#define BASE64_SIZE_T_MAX   ( (size_t) -1 ) /* SIZE_T_MAX is not standard */
84
85
/*
86
 * Encode a buffer into base64 format
87
 */
88
int flb_base64_encode( unsigned char *dst, size_t dlen, size_t *olen,
89
                   const unsigned char *src, size_t slen )
90
692
{
91
692
    size_t i, n;
92
692
    int C1, C2, C3;
93
692
    unsigned char *p;
94
95
692
    if( slen == 0 )
96
0
    {
97
0
        *olen = 0;
98
0
        return( 0 );
99
0
    }
100
101
692
    n = slen / 3 + ( slen % 3 != 0 );
102
103
692
    if( n > ( BASE64_SIZE_T_MAX - 1 ) / 4 )
104
0
    {
105
0
        *olen = BASE64_SIZE_T_MAX;
106
0
        return( FLB_BASE64_ERR_BUFFER_TOO_SMALL );
107
0
    }
108
109
692
    n *= 4;
110
111
692
    if( ( dlen < n + 1 ) || ( NULL == dst ) )
112
155
    {
113
155
        *olen = n + 1;
114
155
        return( FLB_BASE64_ERR_BUFFER_TOO_SMALL );
115
155
    }
116
117
537
    n = ( slen / 3 ) * 3;
118
119
4.42k
    for( i = 0, p = dst; i < n; i += 3 )
120
3.88k
    {
121
3.88k
        C1 = *src++;
122
3.88k
        C2 = *src++;
123
3.88k
        C3 = *src++;
124
125
3.88k
        *p++ = base64_enc_map[(C1 >> 2) & 0x3F];
126
3.88k
        *p++ = base64_enc_map[(((C1 &  3) << 4) + (C2 >> 4)) & 0x3F];
127
3.88k
        *p++ = base64_enc_map[(((C2 & 15) << 2) + (C3 >> 6)) & 0x3F];
128
3.88k
        *p++ = base64_enc_map[C3 & 0x3F];
129
3.88k
    }
130
131
537
    if( i < slen )
132
433
    {
133
433
        C1 = *src++;
134
433
        C2 = ( ( i + 1 ) < slen ) ? *src++ : 0;
135
136
433
        *p++ = base64_enc_map[(C1 >> 2) & 0x3F];
137
433
        *p++ = base64_enc_map[(((C1 & 3) << 4) + (C2 >> 4)) & 0x3F];
138
139
433
        if( ( i + 1 ) < slen )
140
113
             *p++ = base64_enc_map[((C2 & 15) << 2) & 0x3F];
141
320
        else *p++ = '=';
142
143
433
        *p++ = '=';
144
433
    }
145
146
537
    *olen = p - dst;
147
537
    *p = 0;
148
149
537
    return( 0 );
150
692
}
151
152
/*
153
 * Decode a base64-formatted buffer
154
 */
155
int flb_base64_decode( unsigned char *dst, size_t dlen, size_t *olen,
156
                   const unsigned char *src, size_t slen )
157
293
{
158
293
    size_t i, n;
159
293
    uint32_t j, x;
160
293
    unsigned char *p;
161
162
    /* First pass: check for validity and get output length */
163
7.18M
    for( i = n = j = 0; i < slen; i++ )
164
7.18M
    {
165
        /* Skip spaces before checking for EOL */
166
7.18M
        x = 0;
167
11.5M
        while( i < slen && src[i] == ' ' )
168
4.39M
        {
169
4.39M
            ++i;
170
4.39M
            ++x;
171
4.39M
        }
172
173
        /* Spaces at end of buffer are OK */
174
7.18M
        if( i == slen )
175
31
            break;
176
177
7.18M
        if( ( slen - i ) >= 2 &&
178
7.18M
            src[i] == '\r' && src[i + 1] == '\n' )
179
5.10k
            continue;
180
181
7.18M
        if( src[i] == '\n' )
182
14.9k
            continue;
183
184
        /* Space inside a line is an error */
185
7.16M
        if( x != 0 )
186
33
            return( FLB_BASE64_ERR_INVALID_CHARACTER );
187
188
7.16M
        if( src[i] == '=' && ++j > 2 )
189
1
            return( FLB_BASE64_ERR_INVALID_CHARACTER );
190
191
7.16M
        if( src[i] > 127 || base64_dec_map[src[i]] == 127 )
192
85
            return( FLB_BASE64_ERR_INVALID_CHARACTER );
193
194
7.16M
        if( base64_dec_map[src[i]] < 64 && j != 0 )
195
1
            return( FLB_BASE64_ERR_INVALID_CHARACTER );
196
197
7.16M
        n++;
198
7.16M
    }
199
200
173
    if( n == 0 )
201
25
    {
202
25
        *olen = 0;
203
25
        return( 0 );
204
25
    }
205
206
    /* The following expression is to calculate the following formula without
207
     * risk of integer overflow in n:
208
     *     n = ( ( n * 6 ) + 7 ) >> 3;
209
     */
210
148
    n = ( 6 * ( n >> 3 ) ) + ( ( 6 * ( n & 0x7 ) + 7 ) >> 3 );
211
148
    n -= j;
212
213
148
    if( dst == NULL || dlen < n )
214
56
    {
215
56
        *olen = n;
216
56
        return( FLB_BASE64_ERR_BUFFER_TOO_SMALL );
217
56
    }
218
219
2.11M
   for( j = 3, n = x = 0, p = dst; i > 0; i--, src++ )
220
2.11M
   {
221
2.11M
        if( *src == '\r' || *src == '\n' || *src == ' ' )
222
2.11M
            continue;
223
224
1.52k
        j -= ( base64_dec_map[*src] == 64 );
225
1.52k
        x  = ( x << 6 ) | ( base64_dec_map[*src] & 0x3F );
226
227
1.52k
        if( ++n == 4 )
228
350
        {
229
350
            n = 0;
230
350
            if( j > 0 ) *p++ = (unsigned char)( x >> 16 );
231
350
            if( j > 1 ) *p++ = (unsigned char)( x >>  8 );
232
350
            if( j > 2 ) *p++ = (unsigned char)( x       );
233
350
        }
234
1.52k
    }
235
236
92
    *olen = p - dst;
237
238
92
    return( 0 );
239
148
}