Branch data Line data Source code
1 : : /* base64.c -- Encode binary data using printable characters.
2 : : Copyright (C) 1999-2001, 2004-2006, 2009-2012 Free Software Foundation, Inc.
3 : :
4 : : This program is free software; you can redistribute it and/or modify
5 : : it under the terms of the GNU Lesser General Public License as published by
6 : : the Free Software Foundation; either version 2.1, or (at your option)
7 : : any later version.
8 : :
9 : : This program is distributed in the hope that it will be useful,
10 : : but WITHOUT ANY WARRANTY; without even the implied warranty of
11 : : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 : : GNU Lesser General Public License for more details.
13 : :
14 : : You should have received a copy of the GNU Lesser General Public License
15 : : along with this program; if not, see <http://www.gnu.org/licenses/>. */
16 : :
17 : : /* Written by Simon Josefsson. Partially adapted from GNU MailUtils
18 : : * (mailbox/filter_trans.c, as of 2004-11-28). Improved by review
19 : : * from Paul Eggert, Bruno Haible, and Stepan Kasal.
20 : : *
21 : : * See also RFC 4648 <http://www.ietf.org/rfc/rfc4648.txt>.
22 : : *
23 : : * Be careful with error checking. Here is how you would typically
24 : : * use these functions:
25 : : *
26 : : * bool ok = base64_decode_alloc (in, inlen, &out, &outlen);
27 : : * if (!ok)
28 : : * FAIL: input was not valid base64
29 : : * if (out == NULL)
30 : : * FAIL: memory allocation error
31 : : * OK: data in OUT/OUTLEN
32 : : *
33 : : * size_t outlen = base64_encode_alloc (in, inlen, &out);
34 : : * if (out == NULL && outlen == 0 && inlen != 0)
35 : : * FAIL: input too long
36 : : * if (out == NULL)
37 : : * FAIL: memory allocation error
38 : : * OK: data in OUT/OUTLEN.
39 : : *
40 : : */
41 : :
42 : : #include <config.h>
43 : :
44 : : /* Get prototype. */
45 : : #include "base64.h"
46 : :
47 : : /* Get malloc. */
48 : : #include <stdlib.h>
49 : :
50 : : /* Get UCHAR_MAX. */
51 : : #include <limits.h>
52 : :
53 : : #include <string.h>
54 : :
55 : : /* C89 compliant way to cast 'char' to 'unsigned char'. */
56 : : static inline unsigned char
57 : 35389 : to_uchar (char ch)
58 : : {
59 : 35389 : return ch;
60 : : }
61 : :
62 : : /* Base64 encode IN array of size INLEN into OUT array of size OUTLEN.
63 : : If OUTLEN is less than BASE64_LENGTH(INLEN), write as many bytes as
64 : : possible. If OUTLEN is larger than BASE64_LENGTH(INLEN), also zero
65 : : terminate the output buffer. */
66 : : void
67 : 500 : base64_encode (const char *restrict in, size_t inlen,
68 : : char *restrict out, size_t outlen)
69 : : {
70 : : static const char b64str[64] =
71 : : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
72 : :
73 [ + + ][ + - ]: 3685 : while (inlen && outlen)
74 : : {
75 : 3192 : *out++ = b64str[(to_uchar (in[0]) >> 2) & 0x3f];
76 [ + + ]: 3192 : if (!--outlen)
77 : 2 : break;
78 : 3190 : *out++ = b64str[((to_uchar (in[0]) << 4)
79 [ + + ]: 3190 : + (--inlen ? to_uchar (in[1]) >> 4 : 0))
80 : 3190 : & 0x3f];
81 [ + + ]: 3190 : if (!--outlen)
82 : 1 : break;
83 [ + + ]: 6300 : *out++ =
84 : : (inlen
85 : 3111 : ? b64str[((to_uchar (in[1]) << 2)
86 [ + + ]: 3111 : + (--inlen ? to_uchar (in[2]) >> 6 : 0))
87 : 3111 : & 0x3f]
88 : : : '=');
89 [ + + ]: 3189 : if (!--outlen)
90 : 1 : break;
91 [ + + ]: 3188 : *out++ = inlen ? b64str[to_uchar (in[2]) & 0x3f] : '=';
92 [ + + ]: 3188 : if (!--outlen)
93 : 3 : break;
94 [ + + ]: 3185 : if (inlen)
95 : 2934 : inlen--;
96 [ + + ]: 3185 : if (inlen)
97 : 2727 : in += 3;
98 : : }
99 : :
100 [ + + ]: 500 : if (outlen)
101 : 492 : *out = '\0';
102 : 500 : }
103 : :
104 : : /* Allocate a buffer and store zero terminated base64 encoded data
105 : : from array IN of size INLEN, returning BASE64_LENGTH(INLEN), i.e.,
106 : : the length of the encoded data, excluding the terminating zero. On
107 : : return, the OUT variable will hold a pointer to newly allocated
108 : : memory that must be deallocated by the caller. If output string
109 : : length would overflow, 0 is returned and OUT is set to NULL. If
110 : : memory allocation failed, OUT is set to NULL, and the return value
111 : : indicates length of the requested memory block, i.e.,
112 : : BASE64_LENGTH(inlen) + 1. */
113 : : size_t
114 : 491 : base64_encode_alloc (const char *in, size_t inlen, char **out)
115 : : {
116 : 491 : size_t outlen = 1 + BASE64_LENGTH (inlen);
117 : :
118 : : /* Check for overflow in outlen computation.
119 : : *
120 : : * If there is no overflow, outlen >= inlen.
121 : : *
122 : : * If the operation (inlen + 2) overflows then it yields at most +1, so
123 : : * outlen is 0.
124 : : *
125 : : * If the multiplication overflows, we lose at least half of the
126 : : * correct value, so the result is < ((inlen + 2) / 3) * 2, which is
127 : : * less than (inlen + 2) * 0.66667, which is less than inlen as soon as
128 : : * (inlen > 4).
129 : : */
130 [ + + ]: 491 : if (inlen > outlen)
131 : : {
132 : 1 : *out = NULL;
133 : 1 : return 0;
134 : : }
135 : :
136 : 490 : *out = malloc (outlen);
137 [ - + ]: 490 : if (!*out)
138 : 0 : return outlen;
139 : :
140 : 490 : base64_encode (in, inlen, *out, outlen);
141 : :
142 : 491 : return outlen - 1;
143 : : }
144 : :
145 : : /* With this approach this file works independent of the charset used
146 : : (think EBCDIC). However, it does assume that the characters in the
147 : : Base64 alphabet (A-Za-z0-9+/) are encoded in 0..255. POSIX
148 : : 1003.1-2001 require that char and unsigned char are 8-bit
149 : : quantities, though, taking care of that problem. But this may be a
150 : : potential problem on non-POSIX C99 platforms.
151 : :
152 : : IBM C V6 for AIX mishandles "#define B64(x) ...'x'...", so use "_"
153 : : as the formal parameter rather than "x". */
154 : : #define B64(_) \
155 : : ((_) == 'A' ? 0 \
156 : : : (_) == 'B' ? 1 \
157 : : : (_) == 'C' ? 2 \
158 : : : (_) == 'D' ? 3 \
159 : : : (_) == 'E' ? 4 \
160 : : : (_) == 'F' ? 5 \
161 : : : (_) == 'G' ? 6 \
162 : : : (_) == 'H' ? 7 \
163 : : : (_) == 'I' ? 8 \
164 : : : (_) == 'J' ? 9 \
165 : : : (_) == 'K' ? 10 \
166 : : : (_) == 'L' ? 11 \
167 : : : (_) == 'M' ? 12 \
168 : : : (_) == 'N' ? 13 \
169 : : : (_) == 'O' ? 14 \
170 : : : (_) == 'P' ? 15 \
171 : : : (_) == 'Q' ? 16 \
172 : : : (_) == 'R' ? 17 \
173 : : : (_) == 'S' ? 18 \
174 : : : (_) == 'T' ? 19 \
175 : : : (_) == 'U' ? 20 \
176 : : : (_) == 'V' ? 21 \
177 : : : (_) == 'W' ? 22 \
178 : : : (_) == 'X' ? 23 \
179 : : : (_) == 'Y' ? 24 \
180 : : : (_) == 'Z' ? 25 \
181 : : : (_) == 'a' ? 26 \
182 : : : (_) == 'b' ? 27 \
183 : : : (_) == 'c' ? 28 \
184 : : : (_) == 'd' ? 29 \
185 : : : (_) == 'e' ? 30 \
186 : : : (_) == 'f' ? 31 \
187 : : : (_) == 'g' ? 32 \
188 : : : (_) == 'h' ? 33 \
189 : : : (_) == 'i' ? 34 \
190 : : : (_) == 'j' ? 35 \
191 : : : (_) == 'k' ? 36 \
192 : : : (_) == 'l' ? 37 \
193 : : : (_) == 'm' ? 38 \
194 : : : (_) == 'n' ? 39 \
195 : : : (_) == 'o' ? 40 \
196 : : : (_) == 'p' ? 41 \
197 : : : (_) == 'q' ? 42 \
198 : : : (_) == 'r' ? 43 \
199 : : : (_) == 's' ? 44 \
200 : : : (_) == 't' ? 45 \
201 : : : (_) == 'u' ? 46 \
202 : : : (_) == 'v' ? 47 \
203 : : : (_) == 'w' ? 48 \
204 : : : (_) == 'x' ? 49 \
205 : : : (_) == 'y' ? 50 \
206 : : : (_) == 'z' ? 51 \
207 : : : (_) == '0' ? 52 \
208 : : : (_) == '1' ? 53 \
209 : : : (_) == '2' ? 54 \
210 : : : (_) == '3' ? 55 \
211 : : : (_) == '4' ? 56 \
212 : : : (_) == '5' ? 57 \
213 : : : (_) == '6' ? 58 \
214 : : : (_) == '7' ? 59 \
215 : : : (_) == '8' ? 60 \
216 : : : (_) == '9' ? 61 \
217 : : : (_) == '+' ? 62 \
218 : : : (_) == '/' ? 63 \
219 : : : -1)
220 : :
221 : : static const signed char b64[0x100] = {
222 : : B64 (0), B64 (1), B64 (2), B64 (3),
223 : : B64 (4), B64 (5), B64 (6), B64 (7),
224 : : B64 (8), B64 (9), B64 (10), B64 (11),
225 : : B64 (12), B64 (13), B64 (14), B64 (15),
226 : : B64 (16), B64 (17), B64 (18), B64 (19),
227 : : B64 (20), B64 (21), B64 (22), B64 (23),
228 : : B64 (24), B64 (25), B64 (26), B64 (27),
229 : : B64 (28), B64 (29), B64 (30), B64 (31),
230 : : B64 (32), B64 (33), B64 (34), B64 (35),
231 : : B64 (36), B64 (37), B64 (38), B64 (39),
232 : : B64 (40), B64 (41), B64 (42), B64 (43),
233 : : B64 (44), B64 (45), B64 (46), B64 (47),
234 : : B64 (48), B64 (49), B64 (50), B64 (51),
235 : : B64 (52), B64 (53), B64 (54), B64 (55),
236 : : B64 (56), B64 (57), B64 (58), B64 (59),
237 : : B64 (60), B64 (61), B64 (62), B64 (63),
238 : : B64 (64), B64 (65), B64 (66), B64 (67),
239 : : B64 (68), B64 (69), B64 (70), B64 (71),
240 : : B64 (72), B64 (73), B64 (74), B64 (75),
241 : : B64 (76), B64 (77), B64 (78), B64 (79),
242 : : B64 (80), B64 (81), B64 (82), B64 (83),
243 : : B64 (84), B64 (85), B64 (86), B64 (87),
244 : : B64 (88), B64 (89), B64 (90), B64 (91),
245 : : B64 (92), B64 (93), B64 (94), B64 (95),
246 : : B64 (96), B64 (97), B64 (98), B64 (99),
247 : : B64 (100), B64 (101), B64 (102), B64 (103),
248 : : B64 (104), B64 (105), B64 (106), B64 (107),
249 : : B64 (108), B64 (109), B64 (110), B64 (111),
250 : : B64 (112), B64 (113), B64 (114), B64 (115),
251 : : B64 (116), B64 (117), B64 (118), B64 (119),
252 : : B64 (120), B64 (121), B64 (122), B64 (123),
253 : : B64 (124), B64 (125), B64 (126), B64 (127),
254 : : B64 (128), B64 (129), B64 (130), B64 (131),
255 : : B64 (132), B64 (133), B64 (134), B64 (135),
256 : : B64 (136), B64 (137), B64 (138), B64 (139),
257 : : B64 (140), B64 (141), B64 (142), B64 (143),
258 : : B64 (144), B64 (145), B64 (146), B64 (147),
259 : : B64 (148), B64 (149), B64 (150), B64 (151),
260 : : B64 (152), B64 (153), B64 (154), B64 (155),
261 : : B64 (156), B64 (157), B64 (158), B64 (159),
262 : : B64 (160), B64 (161), B64 (162), B64 (163),
263 : : B64 (164), B64 (165), B64 (166), B64 (167),
264 : : B64 (168), B64 (169), B64 (170), B64 (171),
265 : : B64 (172), B64 (173), B64 (174), B64 (175),
266 : : B64 (176), B64 (177), B64 (178), B64 (179),
267 : : B64 (180), B64 (181), B64 (182), B64 (183),
268 : : B64 (184), B64 (185), B64 (186), B64 (187),
269 : : B64 (188), B64 (189), B64 (190), B64 (191),
270 : : B64 (192), B64 (193), B64 (194), B64 (195),
271 : : B64 (196), B64 (197), B64 (198), B64 (199),
272 : : B64 (200), B64 (201), B64 (202), B64 (203),
273 : : B64 (204), B64 (205), B64 (206), B64 (207),
274 : : B64 (208), B64 (209), B64 (210), B64 (211),
275 : : B64 (212), B64 (213), B64 (214), B64 (215),
276 : : B64 (216), B64 (217), B64 (218), B64 (219),
277 : : B64 (220), B64 (221), B64 (222), B64 (223),
278 : : B64 (224), B64 (225), B64 (226), B64 (227),
279 : : B64 (228), B64 (229), B64 (230), B64 (231),
280 : : B64 (232), B64 (233), B64 (234), B64 (235),
281 : : B64 (236), B64 (237), B64 (238), B64 (239),
282 : : B64 (240), B64 (241), B64 (242), B64 (243),
283 : : B64 (244), B64 (245), B64 (246), B64 (247),
284 : : B64 (248), B64 (249), B64 (250), B64 (251),
285 : : B64 (252), B64 (253), B64 (254), B64 (255)
286 : : };
287 : :
288 : : #if UCHAR_MAX == 255
289 : : # define uchar_in_range(c) true
290 : : #else
291 : : # define uchar_in_range(c) ((c) <= 255)
292 : : #endif
293 : :
294 : : /* Return true if CH is a character from the Base64 alphabet, and
295 : : false otherwise. Note that '=' is padding and not considered to be
296 : : part of the alphabet. */
297 : : bool
298 : 6835 : isbase64 (char ch)
299 : : {
300 : 6835 : return uchar_in_range (to_uchar (ch)) && 0 <= b64[to_uchar (ch)];
301 : : }
302 : :
303 : : /* Initialize decode-context buffer, CTX. */
304 : : void
305 : 5 : base64_decode_ctx_init (struct base64_decode_context *ctx)
306 : : {
307 : 5 : ctx->i = 0;
308 : 5 : }
309 : :
310 : : /* If CTX->i is 0 or 4, there are four or more bytes in [*IN..IN_END), and
311 : : none of those four is a newline, then return *IN. Otherwise, copy up to
312 : : 4 - CTX->i non-newline bytes from that range into CTX->buf, starting at
313 : : index CTX->i and setting CTX->i to reflect the number of bytes copied,
314 : : and return CTX->buf. In either case, advance *IN to point to the byte
315 : : after the last one processed, and set *N_NON_NEWLINE to the number of
316 : : verified non-newline bytes accessible through the returned pointer. */
317 : : static inline char *
318 : 8 : get_4 (struct base64_decode_context *ctx,
319 : : char const *restrict *in, char const *restrict in_end,
320 : : size_t *n_non_newline)
321 : : {
322 [ + + ]: 8 : if (ctx->i == 4)
323 : 2 : ctx->i = 0;
324 : :
325 [ + + ]: 8 : if (ctx->i == 0)
326 : : {
327 : 6 : char const *t = *in;
328 [ + + ][ + + ]: 6 : if (4 <= in_end - *in && memchr (t, '\n', 4) == NULL)
329 : : {
330 : : /* This is the common case: no newline. */
331 : 1 : *in += 4;
332 : 1 : *n_non_newline = 4;
333 : 1 : return (char *) t;
334 : : }
335 : : }
336 : :
337 : : {
338 : : /* Copy non-newline bytes into BUF. */
339 : 7 : char const *p = *in;
340 [ + + ]: 22 : while (p < in_end)
341 : : {
342 : 19 : char c = *p++;
343 [ + + ]: 19 : if (c != '\n')
344 : : {
345 : 16 : ctx->buf[ctx->i++] = c;
346 [ + + ]: 16 : if (ctx->i == 4)
347 : 4 : break;
348 : : }
349 : : }
350 : :
351 : 7 : *in = p;
352 : 7 : *n_non_newline = ctx->i;
353 : 8 : return ctx->buf;
354 : : }
355 : : }
356 : :
357 : : #define return_false \
358 : : do \
359 : : { \
360 : : *outp = out; \
361 : : return false; \
362 : : } \
363 : : while (false)
364 : :
365 : : /* Decode up to four bytes of base64-encoded data, IN, of length INLEN
366 : : into the output buffer, *OUT, of size *OUTLEN bytes. Return true if
367 : : decoding is successful, false otherwise. If *OUTLEN is too small,
368 : : as many bytes as possible are written to *OUT. On return, advance
369 : : *OUT to point to the byte after the last one written, and decrement
370 : : *OUTLEN to reflect the number of bytes remaining in *OUT. */
371 : : static inline bool
372 : 2108 : decode_4 (char const *restrict in, size_t inlen,
373 : : char *restrict *outp, size_t *outleft)
374 : : {
375 : 2108 : char *out = *outp;
376 [ + + ]: 2108 : if (inlen < 2)
377 : 324 : return false;
378 : :
379 [ + + ][ - + ]: 1784 : if (!isbase64 (in[0]) || !isbase64 (in[1]))
380 : 7 : return false;
381 : :
382 [ + + ]: 1777 : if (*outleft)
383 : : {
384 : 1776 : *out++ = ((b64[to_uchar (in[0])] << 2)
385 : 1776 : | (b64[to_uchar (in[1])] >> 4));
386 : 1776 : --*outleft;
387 : : }
388 : :
389 [ + + ]: 1777 : if (inlen == 2)
390 : 2 : return_false;
391 : :
392 [ + + ]: 1775 : if (in[2] == '=')
393 : : {
394 [ + + ]: 68 : if (inlen != 4)
395 : 2 : return_false;
396 : :
397 [ + + ]: 66 : if (in[3] != '=')
398 : 4 : return_false;
399 : : }
400 : : else
401 : : {
402 [ + + ]: 1707 : if (!isbase64 (in[2]))
403 : 3 : return_false;
404 : :
405 [ + + ]: 1704 : if (*outleft)
406 : : {
407 : 1702 : *out++ = (((b64[to_uchar (in[1])] << 4) & 0xf0)
408 : 1702 : | (b64[to_uchar (in[2])] >> 2));
409 : 1702 : --*outleft;
410 : : }
411 : :
412 [ + + ]: 1704 : if (inlen == 3)
413 : 2 : return_false;
414 : :
415 [ + + ]: 1702 : if (in[3] == '=')
416 : : {
417 [ + + ]: 135 : if (inlen != 4)
418 : 2 : return_false;
419 : : }
420 : : else
421 : : {
422 [ + + ]: 1567 : if (!isbase64 (in[3]))
423 : 2 : return_false;
424 : :
425 [ + + ]: 1565 : if (*outleft)
426 : : {
427 : 1562 : *out++ = (((b64[to_uchar (in[2])] << 6) & 0xc0)
428 : 1562 : | b64[to_uchar (in[3])]);
429 : 1562 : --*outleft;
430 : : }
431 : : }
432 : : }
433 : :
434 : 1760 : *outp = out;
435 : 2108 : return true;
436 : : }
437 : :
438 : : /* Decode base64-encoded input array IN of length INLEN to output array
439 : : OUT that can hold *OUTLEN bytes. The input data may be interspersed
440 : : with newlines. Return true if decoding was successful, i.e. if the
441 : : input was valid base64 data, false otherwise. If *OUTLEN is too
442 : : small, as many bytes as possible will be written to OUT. On return,
443 : : *OUTLEN holds the length of decoded bytes in OUT. Note that as soon
444 : : as any non-alphabet, non-newline character is encountered, decoding
445 : : is stopped and false is returned. If INLEN is zero, then process
446 : : only whatever data is stored in CTX.
447 : :
448 : : Initially, CTX must have been initialized via base64_decode_ctx_init.
449 : : Subsequent calls to this function must reuse whatever state is recorded
450 : : in that buffer. It is necessary for when a quadruple of base64 input
451 : : bytes spans two input buffers.
452 : :
453 : : If CTX is NULL then newlines are treated as garbage and the input
454 : : buffer is processed as a unit. */
455 : :
456 : : bool
457 : 335 : base64_decode_ctx (struct base64_decode_context *ctx,
458 : : const char *restrict in, size_t inlen,
459 : : char *restrict out, size_t *outlen)
460 : : {
461 : 335 : size_t outleft = *outlen;
462 : 335 : bool ignore_newlines = ctx != NULL;
463 : 335 : bool flush_ctx = false;
464 : 335 : unsigned int ctx_i = 0;
465 : :
466 [ + + ]: 335 : if (ignore_newlines)
467 : : {
468 : 8 : ctx_i = ctx->i;
469 : 8 : flush_ctx = inlen == 0;
470 : : }
471 : :
472 : :
473 : : while (true)
474 : : {
475 : 346 : size_t outleft_save = outleft;
476 [ + + ][ + - ]: 346 : if (ctx_i == 0 && !flush_ctx)
477 : : {
478 : : while (true)
479 : : {
480 : : /* Save a copy of outleft, in case we need to re-parse this
481 : : block of four bytes. */
482 : 2095 : outleft_save = outleft;
483 [ + + ]: 2095 : if (!decode_4 (in, inlen, &out, &outleft))
484 : 340 : break;
485 : :
486 : 1755 : in += 4;
487 : 1755 : inlen -= 4;
488 : 1755 : }
489 : : }
490 : :
491 [ + + ][ + + ]: 346 : if (inlen == 0 && !flush_ctx)
492 : 324 : break;
493 : :
494 : : /* Handle the common case of 72-byte wrapped lines.
495 : : This also handles any other multiple-of-4-byte wrapping. */
496 [ + + ][ + + ]: 22 : if (inlen && *in == '\n' && ignore_newlines)
[ + - ]
497 : : {
498 : 6 : ++in;
499 : 6 : --inlen;
500 : 6 : continue;
501 : : }
502 : :
503 : : /* Restore OUT and OUTLEFT. */
504 : 16 : out -= outleft_save - outleft;
505 : 16 : outleft = outleft_save;
506 : :
507 : : {
508 : 16 : char const *in_end = in + inlen;
509 : : char const *non_nl;
510 : :
511 [ + + ]: 16 : if (ignore_newlines)
512 : 8 : non_nl = get_4 (ctx, &in, in_end, &inlen);
513 : : else
514 : 8 : non_nl = in; /* Might have nl in this case. */
515 : :
516 : : /* If the input is empty or consists solely of newlines (0 non-newlines),
517 : : then we're done. Likewise if there are fewer than 4 bytes when not
518 : : flushing context and not treating newlines as garbage. */
519 [ + + ][ + + ]: 16 : if (inlen == 0 || (inlen < 4 && !flush_ctx && ignore_newlines))
[ + - ][ + + ]
520 : : {
521 : 3 : inlen = 0;
522 : 3 : break;
523 : : }
524 [ + + ]: 13 : if (!decode_4 (non_nl, inlen, &out, &outleft))
525 : 8 : break;
526 : :
527 : 5 : inlen = in_end - in;
528 : : }
529 : 11 : }
530 : :
531 : 335 : *outlen -= outleft;
532 : :
533 : 335 : return inlen == 0;
534 : : }
535 : :
536 : : /* Allocate an output buffer in *OUT, and decode the base64 encoded
537 : : data stored in IN of size INLEN to the *OUT buffer. On return, the
538 : : size of the decoded data is stored in *OUTLEN. OUTLEN may be NULL,
539 : : if the caller is not interested in the decoded length. *OUT may be
540 : : NULL to indicate an out of memory error, in which case *OUTLEN
541 : : contains the size of the memory block needed. The function returns
542 : : true on successful decoding and memory allocation errors. (Use the
543 : : *OUT and *OUTLEN parameters to differentiate between successful
544 : : decoding and memory error.) The function returns false if the
545 : : input was invalid, in which case *OUT is NULL and *OUTLEN is
546 : : undefined. */
547 : : bool
548 : 328 : base64_decode_alloc_ctx (struct base64_decode_context *ctx,
549 : : const char *in, size_t inlen, char **out,
550 : : size_t *outlen)
551 : : {
552 : : /* This may allocate a few bytes too many, depending on input,
553 : : but it's not worth the extra CPU time to compute the exact size.
554 : : The exact size is 3 * (inlen + (ctx ? ctx->i : 0)) / 4, minus 1 if the
555 : : input ends with "=" and minus another 1 if the input ends with "==".
556 : : Dividing before multiplying avoids the possibility of overflow. */
557 : 328 : size_t needlen = 3 * (inlen / 4) + 3;
558 : :
559 : 328 : *out = malloc (needlen);
560 [ - + ]: 328 : if (!*out)
561 : 0 : return true;
562 : :
563 [ + + ]: 328 : if (!base64_decode_ctx (ctx, in, inlen, *out, &needlen))
564 : : {
565 : 8 : free (*out);
566 : 8 : *out = NULL;
567 : 8 : return false;
568 : : }
569 : :
570 [ + - ]: 320 : if (outlen)
571 : 320 : *outlen = needlen;
572 : :
573 : 328 : return true;
574 : : }
|