Coverage Report

Created: 2025-07-11 06:40

/src/httpd/srclib/apr/encoding/apr_base64.c
Line
Count
Source (jump to first uncovered line)
1
/* Licensed to the Apache Software Foundation (ASF) under one or more
2
 * contributor license agreements.  See the NOTICE file distributed with
3
 * this work for additional information regarding copyright ownership.
4
 * The ASF licenses this file to You under the Apache License, Version 2.0
5
 * (the "License"); you may not use this file except in compliance with
6
 * the License.  You may obtain a copy of the License at
7
 *
8
 *     http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16
17
/* base64 encoder/decoder. Originally part of main/util.c
18
 * but moved here so that support/ab and apr_sha1.c could
19
 * use it. This meant removing the apr_palloc()s and adding
20
 * ugly 'len' functions, which is quite a nasty cost.
21
 */
22
23
#include "apr_base64.h"
24
#if APR_CHARSET_EBCDIC
25
#include "apr_xlate.h"
26
#endif                /* APR_CHARSET_EBCDIC */
27
28
/* APR__ASSERT() to always abort() on failure (no output when NDEBUG) */
29
#ifndef NDEBUG
30
#include <assert.h>
31
5.06k
#define APR__ASSERT(cond) assert(cond)
32
#else
33
#include "apr.h"
34
#if APR_HAVE_STDLIB_H
35
#include <stdlib.h>
36
#endif
37
#define APR__ASSERT(cond) do { \
38
    if (!(cond)) { \
39
        abort(); \
40
    } \
41
} while (0)
42
#endif
43
44
/* Above APR_BASE64_ENCODE_MAX length the encoding can't fit in an int >= 0 */
45
#define APR_BASE64_ENCODE_MAX 1610612733
46
47
/* Above APR_BASE64_DECODE_MAX length the decoding can't fit in an int >= 0 */
48
#define APR_BASE64_DECODE_MAX 2863311524u
49
50
/* aaaack but it's fast and const should make it shared text page. */
51
static const unsigned char pr2six[256] =
52
{
53
#if !APR_CHARSET_EBCDIC
54
    /* ASCII table */
55
    64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
56
    64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
57
    64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64, 64, 64, 63,
58
    52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 64, 64, 64,
59
    64,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,
60
    15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64, 64,
61
    64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
62
    41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 64, 64, 64, 64, 64,
63
    64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
64
    64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
65
    64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
66
    64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
67
    64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
68
    64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
69
    64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
70
    64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64
71
#else /*APR_CHARSET_EBCDIC*/
72
    /* EBCDIC table */
73
    64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
74
    64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
75
    64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
76
    64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
77
    64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 62, 64,
78
    64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
79
    64, 63, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
80
    64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
81
    64, 26, 27, 28, 29, 30, 31, 32, 33, 34, 64, 64, 64, 64, 64, 64,
82
    64, 35, 36, 37, 38, 39, 40, 41, 42, 43, 64, 64, 64, 64, 64, 64,
83
    64, 64, 44, 45, 46, 47, 48, 49, 50, 51, 64, 64, 64, 64, 64, 64,
84
    64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64, 64,
85
    64,  0,  1,  2,  3,  4,  5,  6,  7,  8, 64, 64, 64, 64, 64, 64,
86
    64,  9, 10, 11, 12, 13, 14, 15, 16, 17, 64, 64, 64, 64, 64, 64,
87
    64, 64, 18, 19, 20, 21, 22, 23, 24, 25, 64, 64, 64, 64, 64, 64,
88
    52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 64, 64, 64, 64, 64, 64
89
#endif /*APR_CHARSET_EBCDIC*/
90
};
91
92
#if APR_CHARSET_EBCDIC
93
static apr_xlate_t *xlate_to_ebcdic;
94
static unsigned char os_toascii[256];
95
96
APR_DECLARE(apr_status_t) apr_base64init_ebcdic(apr_xlate_t *to_ascii,
97
                                             apr_xlate_t *to_ebcdic)
98
{
99
    int i;
100
    apr_size_t inbytes_left, outbytes_left;
101
    apr_status_t rv;
102
    int onoff;
103
104
    /* Only single-byte conversion is supported.
105
     */
106
    rv = apr_xlate_sb_get(to_ascii, &onoff);
107
    if (rv) {
108
        return rv;
109
    }
110
    if (!onoff) { /* If conversion is not single-byte-only */
111
        return APR_EINVAL;
112
    }
113
    rv = apr_xlate_sb_get(to_ebcdic, &onoff);
114
    if (rv) {
115
        return rv;
116
    }
117
    if (!onoff) { /* If conversion is not single-byte-only */
118
        return APR_EINVAL;
119
    }
120
    xlate_to_ebcdic = to_ebcdic;
121
    for (i = 0; i < sizeof(os_toascii); i++) {
122
        os_toascii[i] = i;
123
    }
124
    inbytes_left = outbytes_left = sizeof(os_toascii);
125
    apr_xlate_conv_buffer(to_ascii, os_toascii, &inbytes_left,
126
                          os_toascii, &outbytes_left);
127
128
    return APR_SUCCESS;
129
}
130
#endif /*APR_CHARSET_EBCDIC*/
131
132
APR_DECLARE(int) apr_base64_decode_len(const char *bufcoded)
133
1.28k
{
134
1.28k
    register const unsigned char *bufin;
135
1.28k
    register apr_size_t nprbytes;
136
137
1.28k
    bufin = (const unsigned char *) bufcoded;
138
8.08k
    while (pr2six[*(bufin++)] <= 63);
139
1.28k
    nprbytes = (bufin - (const unsigned char *) bufcoded) - 1;
140
1.28k
    APR__ASSERT(nprbytes <= APR_BASE64_DECODE_MAX);
141
142
1.28k
    return (int)(((nprbytes + 3u) / 4u) * 3u + 1u);
143
1.28k
}
144
145
APR_DECLARE(int) apr_base64_decode(char *bufplain, const char *bufcoded)
146
1.28k
{
147
#if APR_CHARSET_EBCDIC
148
    apr_size_t inbytes_left, outbytes_left;
149
#endif /* APR_CHARSET_EBCDIC */
150
1.28k
    int len;
151
152
1.28k
    len = apr_base64_decode_binary((unsigned char *) bufplain, bufcoded);
153
#if APR_CHARSET_EBCDIC
154
    inbytes_left = outbytes_left = len;
155
    apr_xlate_conv_buffer(xlate_to_ebcdic, bufplain, &inbytes_left,
156
                          bufplain, &outbytes_left);
157
#endif                /* APR_CHARSET_EBCDIC */
158
1.28k
    bufplain[len] = '\0';
159
1.28k
    return len;
160
1.28k
}
161
162
/* This is the same as apr_base64_decode() except:
163
 * - no \0 is appended
164
 * - on EBCDIC machines, the conversion of the output to ebcdic is left out
165
 */
166
APR_DECLARE(int) apr_base64_decode_binary(unsigned char *bufplain,
167
                                          const char *bufcoded)
168
1.28k
{
169
1.28k
    int nbytesdecoded;
170
1.28k
    register const unsigned char *bufin;
171
1.28k
    register unsigned char *bufout;
172
1.28k
    register apr_size_t nprbytes;
173
174
1.28k
    bufin = (const unsigned char *) bufcoded;
175
8.08k
    while (pr2six[*(bufin++)] <= 63);
176
1.28k
    nprbytes = (bufin - (const unsigned char *) bufcoded) - 1;
177
1.28k
    APR__ASSERT(nprbytes <= APR_BASE64_DECODE_MAX);
178
1.28k
    nbytesdecoded = (int)(((nprbytes + 3u) / 4u) * 3u);
179
180
1.28k
    bufout = (unsigned char *) bufplain;
181
1.28k
    bufin = (const unsigned char *) bufcoded;
182
183
2.81k
    while (nprbytes >= 4) {
184
1.53k
        *(bufout++) =
185
1.53k
            (unsigned char) (pr2six[*bufin] << 2 | pr2six[bufin[1]] >> 4);
186
1.53k
        *(bufout++) =
187
1.53k
            (unsigned char) (pr2six[bufin[1]] << 4 | pr2six[bufin[2]] >> 2);
188
1.53k
        *(bufout++) =
189
1.53k
            (unsigned char) (pr2six[bufin[2]] << 6 | pr2six[bufin[3]]);
190
1.53k
        bufin += 4;
191
1.53k
        nprbytes -= 4;
192
1.53k
    }
193
194
    /* Note: (nprbytes == 1) would be an error, so just ignore that case */
195
1.28k
    if (nprbytes > 1) {
196
204
        *(bufout++) =
197
204
            (unsigned char) (pr2six[*bufin] << 2 | pr2six[bufin[1]] >> 4);
198
204
    }
199
1.28k
    if (nprbytes > 2) {
200
103
        *(bufout++) =
201
103
            (unsigned char) (pr2six[bufin[1]] << 4 | pr2six[bufin[2]] >> 2);
202
103
    }
203
204
1.28k
    return nbytesdecoded - (int)((4u - nprbytes) & 3u);
205
1.28k
}
206
207
APR_DECLARE(char *) apr_pbase64_decode(apr_pool_t *p, const char *bufcoded)
208
0
{
209
0
    char *decoded;
210
211
0
    decoded = (char *) apr_palloc(p, apr_base64_decode_len(bufcoded));
212
0
    apr_base64_decode(decoded, bufcoded);
213
214
0
    return decoded;
215
0
}
216
217
static const char basis_64[] =
218
    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
219
220
APR_DECLARE(int) apr_base64_encode_len(int len)
221
1.25k
{
222
1.25k
    APR__ASSERT(len >= 0 && len <= APR_BASE64_ENCODE_MAX);
223
224
1.25k
    return ((len + 2) / 3 * 4) + 1;
225
1.25k
}
226
227
APR_DECLARE(int) apr_base64_encode(char *encoded, const char *string, int len)
228
1.25k
{
229
1.25k
#if !APR_CHARSET_EBCDIC
230
1.25k
    return apr_base64_encode_binary(encoded, (const unsigned char *) string, len);
231
#else /* APR_CHARSET_EBCDIC */
232
    int i;
233
    char *p;
234
235
    APR__ASSERT(len >= 0 && len <= APR_BASE64_ENCODE_MAX);
236
237
    p = encoded;
238
    for (i = 0; i < len - 2; i += 3) {
239
        *p++ = basis_64[(os_toascii[string[i]] >> 2) & 0x3F];
240
        *p++ = basis_64[((os_toascii[string[i]] & 0x3) << 4) |
241
            ((int) (os_toascii[string[i + 1]] & 0xF0) >> 4)];
242
        *p++ = basis_64[((os_toascii[string[i + 1]] & 0xF) << 2) |
243
            ((int) (os_toascii[string[i + 2]] & 0xC0) >> 6)];
244
        *p++ = basis_64[os_toascii[string[i + 2]] & 0x3F];
245
    }
246
    if (i < len) {
247
        *p++ = basis_64[(os_toascii[string[i]] >> 2) & 0x3F];
248
        if (i == (len - 1)) {
249
            *p++ = basis_64[((os_toascii[string[i]] & 0x3) << 4)];
250
            *p++ = '=';
251
        }
252
        else {
253
            *p++ = basis_64[((os_toascii[string[i]] & 0x3) << 4) |
254
                ((int) (os_toascii[string[i + 1]] & 0xF0) >> 4)];
255
            *p++ = basis_64[((os_toascii[string[i + 1]] & 0xF) << 2)];
256
        }
257
        *p++ = '=';
258
    }
259
260
    *p++ = '\0';
261
    return (unsigned int)(p - encoded);
262
#endif                /* APR_CHARSET_EBCDIC */
263
1.25k
}
264
265
/* This is the same as apr_base64_encode() except on EBCDIC machines, where
266
 * the conversion of the input to ascii is left out.
267
 */
268
APR_DECLARE(int) apr_base64_encode_binary(char *encoded,
269
                                      const unsigned char *string, int len)
270
1.25k
{
271
1.25k
    int i;
272
1.25k
    char *p;
273
274
1.25k
    APR__ASSERT(len >= 0 && len <= APR_BASE64_ENCODE_MAX);
275
276
1.25k
    p = encoded;
277
19.3k
    for (i = 0; i < len - 2; i += 3) {
278
18.0k
        *p++ = basis_64[(string[i] >> 2) & 0x3F];
279
18.0k
        *p++ = basis_64[((string[i] & 0x3) << 4) |
280
18.0k
            ((int) (string[i + 1] & 0xF0) >> 4)];
281
18.0k
        *p++ = basis_64[((string[i + 1] & 0xF) << 2) |
282
18.0k
            ((int) (string[i + 2] & 0xC0) >> 6)];
283
18.0k
        *p++ = basis_64[string[i + 2] & 0x3F];
284
18.0k
    }
285
1.25k
    if (i < len) {
286
600
        *p++ = basis_64[(string[i] >> 2) & 0x3F];
287
600
        if (i == (len - 1)) {
288
338
            *p++ = basis_64[((string[i] & 0x3) << 4)];
289
338
            *p++ = '=';
290
338
        }
291
262
        else {
292
262
            *p++ = basis_64[((string[i] & 0x3) << 4) |
293
262
                ((int) (string[i + 1] & 0xF0) >> 4)];
294
262
            *p++ = basis_64[((string[i + 1] & 0xF) << 2)];
295
262
        }
296
600
        *p++ = '=';
297
600
    }
298
299
1.25k
    *p++ = '\0';
300
1.25k
    return (unsigned int)(p - encoded);
301
1.25k
}
302
303
APR_DECLARE(char *) apr_pbase64_encode(apr_pool_t *p, const char *string)
304
0
{
305
0
    char *encoded;
306
0
    apr_size_t len = strlen(string);
307
308
0
    APR__ASSERT(len <= (apr_size_t)APR_BASE64_ENCODE_MAX);
309
0
    encoded = (char *) apr_palloc(p, apr_base64_encode_len((int)len));
310
0
    apr_base64_encode(encoded, string, (int)len);
311
312
0
    return encoded;
313
0
}