MySQL 8.0.37
Source Code Documentation
base64.h
Go to the documentation of this file.
1/* Copyright (c) 2003, 2024, Oracle and/or its affiliates.
2
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License, version 2.0,
5 as published by the Free Software Foundation.
6
7 This program is designed to work with certain software (including
8 but not limited to OpenSSL) that is licensed under separate terms,
9 as designated in a particular file or component or in included license
10 documentation. The authors of MySQL hereby grant you an additional
11 permission to link the program and your derivative works with the
12 separately licensed software that they have either included with
13 the program or referenced in the documentation.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License, version 2.0, for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
23
24#ifndef __BASE64_H_INCLUDED__
25#define __BASE64_H_INCLUDED__
26
27/**
28 @file include/base64.h
29*/
30
31#include <stddef.h>
32
33#include <assert.h>
34#include <math.h>
35#include <stddef.h>
36#include <stdio.h>
37#include <stdlib.h>
38#include <string.h>
39#include <sys/types.h>
40
41#include "my_config.h"
42#include "my_inttypes.h"
43
44/* Allow multuple chunks 'AAA= AA== AA==', binlog uses this */
45#define MY_BASE64_DECODE_ALLOW_MULTIPLE_CHUNKS 1
46
47static char base64_table[] =
48 "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
49 "abcdefghijklmnopqrstuvwxyz"
50 "0123456789+/";
51
52/*
53 Base64 decoder stream
54*/
55typedef struct my_base64_decoder_t {
56 const char *src; /* Pointer to the current input position */
57 const char *end; /* Pointer to the end of input buffer */
58 uint c; /* Collect bits into this number */
59 int error; /* Error code */
60 uchar state; /* Character number in the current group of 4 */
61 uchar mark; /* Number of padding marks in the current group */
63
64/*
65 Helper table for decoder.
66 -2 means "space character"
67 -1 means "bad character"
68 Non-negative values mean valid base64 encoding character.
69*/
71 /*00*/ -1, -1, -1, -1, -1, -1, -1, -1,
72 -1, -2, -2, -2, -2, -2, -1, -1,
73 /*10*/ -1, -1, -1, -1, -1, -1, -1, -1,
74 -1, -1, -1, -1, -1, -1, -1, -1,
75 /*20*/ -2, -1, -1, -1, -1, -1, -1, -1,
76 -1, -1, -1, 62, -1, -1, -1, 63, /* !"#$%&'()*+,-./ */
77 /*30*/ 52, 53, 54, 55, 56, 57, 58, 59,
78 60, 61, -1, -1, -1, -1, -1, -1, /* 0123456789:;<=>? */
79 /*40*/ -1, 0, 1, 2, 3, 4, 5, 6,
80 7, 8, 9, 10, 11, 12, 13, 14, /* @ABCDEFGHIJKLMNO */
81 /*50*/ 15, 16, 17, 18, 19, 20, 21, 22,
82 23, 24, 25, -1, -1, -1, -1, -1, /* PQRSTUVWXYZ[\]^_ */
83 /*60*/ -1, 26, 27, 28, 29, 30, 31, 32,
84 33, 34, 35, 36, 37, 38, 39, 40, /* `abcdefghijklmno */
85 /*70*/ 41, 42, 43, 44, 45, 46, 47, 48,
86 49, 50, 51, -1, -1, -1, -1, -1, /* pqrstuvwxyz{|}~ */
87 /*80*/ -1, -1, -1, -1, -1, -1, -1, -1,
88 -1, -1, -1, -1, -1, -1, -1, -1,
89 /*90*/ -1, -1, -1, -1, -1, -1, -1, -1,
90 -1, -1, -1, -1, -1, -1, -1, -1,
91 /*A0*/ -2, -1, -1, -1, -1, -1, -1, -1,
92 -1, -1, -1, -1, -1, -1, -1, -1,
93 /*B0*/ -1, -1, -1, -1, -1, -1, -1, -1,
94 -1, -1, -1, -1, -1, -1, -1, -1,
95 /*C0*/ -1, -1, -1, -1, -1, -1, -1, -1,
96 -1, -1, -1, -1, -1, -1, -1, -1,
97 /*D0*/ -1, -1, -1, -1, -1, -1, -1, -1,
98 -1, -1, -1, -1, -1, -1, -1, -1,
99 /*E0*/ -1, -1, -1, -1, -1, -1, -1, -1,
100 -1, -1, -1, -1, -1, -1, -1, -1,
101 /*F0*/ -1, -1, -1, -1, -1, -1, -1, -1,
102 -1, -1, -1, -1, -1, -1, -1, -1};
103
104/**
105 * Skip leading spaces in a base64 encoded stream
106 * and stop on the first non-space character.
107 * decoder->src will point to the first non-space character,
108 * or to the end of the input string.
109 * In case when end-of-input met on unexpected position,
110 * decoder->error is also set to 1.
111 *
112 * @param decoder Pointer to MY_BASE64_DECODER
113 *
114 * @return
115 * false on success (there are some more non-space input characters)
116 * true on error (end-of-input found)
117 */
119 for (; decoder->src < decoder->end; decoder->src++) {
120 if (from_base64_table[(uchar)*decoder->src] != -2) return false;
121 }
122 if (decoder->state > 0)
123 decoder->error = 1; /* Unexpected end-of-input found */
124 return true;
125}
126
127/**
128 * Convert the next character in a base64 encoded stream
129 * to a number in the range [0..63]
130 * and mix it with the previously collected value in decoder->c.
131 *
132 * @param decoder base64 decoding stream
133 *
134 * @return
135 * false on success
136 * true on error (invalid base64 character found)
137 */
138static inline bool my_base64_add(MY_BASE64_DECODER *decoder) {
139 int res;
140 decoder->c <<= 6;
141 if ((res = from_base64_table[(uchar)*decoder->src++]) < 0)
142 return (decoder->error = true);
143 decoder->c += (uint)res;
144 return false;
145}
146
147/**
148 * Get the next character from a base64 encoded stream.
149 * Skip spaces, then scan the next base64 character or a pad character
150 * and collect bits into decoder->c.
151 *
152 * @param decoder Pointer to MY_BASE64_DECODER
153 * @return
154 * false on success (a valid base64 encoding character found)
155 * true on error (unexpected character or unexpected end-of-input found)
156 */
157static inline bool my_base64_decoder_getch(MY_BASE64_DECODER *decoder) {
158 if (my_base64_decoder_skip_spaces(decoder)) return true; /* End-of-input */
159
160 if (!my_base64_add(decoder)) /* Valid base64 character found */
161 {
162 if (decoder->mark) {
163 /* If we have scanned '=' already, then only '=' is valid */
164 assert(decoder->state == 3);
165 decoder->error = 1;
166 decoder->src--;
167 return true; /* expected '=', but encoding character found */
168 }
169 decoder->state++;
170 return false;
171 }
172
173 /* Process error */
174 switch (decoder->state) {
175 case 0:
176 case 1:
177 decoder->src--;
178 return true; /* base64 character expected */
179
180 case 2:
181 case 3:
182 if (decoder->src[-1] == '=') {
183 decoder->error = 0; /* Not an error - it's a pad character */
184 decoder->mark++;
185 } else {
186 decoder->src--;
187 return true; /* base64 character or '=' expected */
188 }
189 break;
190
191 default:
192 assert(0);
193 return true; /* Wrong state, should not happen */
194 }
195
196 decoder->state++;
197 return false;
198}
199
200/*
201 Calculate how much memory needed for dst of base64_encode()
202*/
203static inline uint64 base64_needed_encoded_length(uint64 length_of_data) {
204 uint64 nb_base64_chars;
205 if (length_of_data == 0) return 1;
206 nb_base64_chars = (length_of_data + 2) / 3 * 4;
207
208 return nb_base64_chars + /* base64 char incl padding */
209 (nb_base64_chars - 1) / 76 + /* newlines */
210 1; /* NUL termination of string */
211}
212
213/*
214 Maximum length base64_encode_needed_length() can accept with no overflow.
215*/
217#if (SIZEOF_VOIDP == 8)
218 /*
219 6827690988321067803 -> 9223372036854775805
220 6827690988321067804 -> -9223372036854775807
221 */
222 return 0x5EC0D4C77B03531BLL;
223#else
224 /*
225 1589695686 -> 2147483646
226 1589695687 -> -2147483645
227 */
228 return 0x5EC0D4C6;
229#endif
230}
231
232/*
233 Calculate how much memory needed for dst of base64_decode()
234*/
236 uint64 length_of_encoded_data) {
237 return static_cast<uint64>(
238 ceil(static_cast<double>(length_of_encoded_data * 3 / 4)));
239}
240
241/*
242 Maximum length base64_decode_needed_length() can accept with no overflow.
243*/
245#if (SIZEOF_VOIDP == 8)
246 return 0x2AAAAAAAAAAAAAAALL;
247#else
248 return 0x2AAAAAAA;
249#endif
250}
251
252/*
253 Encode data as a base64 string
254*/
255static inline int base64_encode(const void *src, size_t src_len, char *dst) {
256 const unsigned char *s = (const unsigned char *)src;
257 size_t i = 0;
258 size_t len = 0;
259
260 for (; i < src_len; len += 4) {
261 unsigned c;
262
263 if (len == 76) {
264 len = 0;
265 *dst++ = '\n';
266 }
267
268 c = s[i++];
269 c <<= 8;
270
271 if (i < src_len) c += s[i];
272 c <<= 8;
273 i++;
274
275 if (i < src_len) c += s[i];
276 i++;
277
278 *dst++ = base64_table[(c >> 18) & 0x3f];
279 *dst++ = base64_table[(c >> 12) & 0x3f];
280
281 if (i > (src_len + 1))
282 *dst++ = '=';
283 else
284 *dst++ = base64_table[(c >> 6) & 0x3f];
285
286 if (i > src_len)
287 *dst++ = '=';
288 else
289 *dst++ = base64_table[(c >> 0) & 0x3f];
290 }
291 *dst = '\0';
292
293 return 0;
294}
295
296/**
297 * Decode a base64 string
298 * The base64-encoded data in the range ['src','*end_ptr') will be
299 * decoded and stored starting at 'dst'. The decoding will stop
300 * after 'len' characters have been read from 'src', or when padding
301 * occurs in the base64-encoded data. In either case: if 'end_ptr' is
302 * non-null, '*end_ptr' will be set to point to the character after
303 * the last read character, even in the presence of error.
304 *
305 * Note: We require that 'dst' is pre-allocated to correct size.
306 *
307 * @param src_base Pointer to base64-encoded string
308 * @param len Length of string at 'src'
309 * @param dst Pointer to location where decoded data will be stored
310 * @param end_ptr Pointer to variable that will refer to the character
311 * after the end of the encoded data that were decoded.
312 * Can be NULL.
313 * @param flags flags e.g. allow multiple chunks
314 * @return Number of bytes written at 'dst', or -1 in case of failure
315 */
316static inline int64 base64_decode(const char *src_base, size_t len, void *dst,
317 const char **end_ptr, int flags) {
318 char *d = (char *)dst;
319 MY_BASE64_DECODER decoder;
320
321 decoder.src = src_base;
322 decoder.end = src_base + len;
323 decoder.error = 0;
324 decoder.mark = 0;
325
326 for (;;) {
327 decoder.c = 0;
328 decoder.state = 0;
329
330 if (my_base64_decoder_getch(&decoder) ||
331 my_base64_decoder_getch(&decoder) ||
333 break;
334
335 *d++ = (decoder.c >> 16) & 0xff;
336 *d++ = (decoder.c >> 8) & 0xff;
337 *d++ = (decoder.c >> 0) & 0xff;
338
339 if (decoder.mark) {
340 d -= decoder.mark;
342 decoder.mark = 0;
343 }
344 }
345
346 /* Return error if there are more non-space characters */
347 decoder.state = 0;
348 if (!my_base64_decoder_skip_spaces(&decoder)) decoder.error = 1;
349
350 if (end_ptr != nullptr) *end_ptr = decoder.src;
351
352 return decoder.error ? -1 : (int)(d - (char *)dst);
353}
354
355#endif /* !__BASE64_H_INCLUDED__ */
static int flags[50]
Definition: hp_test1.cc:40
static bool my_base64_decoder_getch(MY_BASE64_DECODER *decoder)
Get the next character from a base64 encoded stream.
Definition: base64.h:157
static uint64 base64_encode_max_arg_length()
Definition: base64.h:216
static bool my_base64_add(MY_BASE64_DECODER *decoder)
Convert the next character in a base64 encoded stream to a number in the range [0....
Definition: base64.h:138
static char base64_table[]
Definition: base64.h:47
static uint64 base64_needed_decoded_length(uint64 length_of_encoded_data)
Definition: base64.h:235
#define MY_BASE64_DECODE_ALLOW_MULTIPLE_CHUNKS
Definition: base64.h:45
struct my_base64_decoder_t MY_BASE64_DECODER
static int8 from_base64_table[]
Definition: base64.h:70
static uint64 base64_needed_encoded_length(uint64 length_of_data)
Definition: base64.h:203
static uint64 base64_decode_max_arg_length()
Definition: base64.h:244
static int64 base64_decode(const char *src_base, size_t len, void *dst, const char **end_ptr, int flags)
Decode a base64 string The base64-encoded data in the range ['src','*end_ptr') will be decoded and st...
Definition: base64.h:316
static bool my_base64_decoder_skip_spaces(MY_BASE64_DECODER *decoder)
Skip leading spaces in a base64 encoded stream and stop on the first non-space character.
Definition: base64.h:118
static int base64_encode(const void *src, size_t src_len, char *dst)
Definition: base64.h:255
if(!(yy_init))
Definition: lexyy.cc:1144
Some integer typedefs for easier portability.
unsigned char uchar
Definition: my_inttypes.h:52
int64_t int64
Definition: my_inttypes.h:68
int8_t int8
Definition: my_inttypes.h:62
uint64_t uint64
Definition: my_inttypes.h:69
Definition: base64.h:55
uchar mark
Definition: base64.h:61
int error
Definition: base64.h:59
uchar state
Definition: base64.h:60
const char * end
Definition: base64.h:57
uint c
Definition: base64.h:58
const char * src
Definition: base64.h:56
unsigned int uint
Definition: uca9-dump.cc:75