diff options
Diffstat (limited to 'gl/base64.c')
| -rw-r--r-- | gl/base64.c | 56 |
1 files changed, 20 insertions, 36 deletions
diff --git a/gl/base64.c b/gl/base64.c index 95b669aa..8a0edd4a 100644 --- a/gl/base64.c +++ b/gl/base64.c | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | /* base64.c -- Encode binary data using printable characters. | 1 | /* base64.c -- Encode binary data using printable characters. |
| 2 | Copyright (C) 1999-2001, 2004-2006, 2009-2023 Free Software Foundation, Inc. | 2 | Copyright (C) 1999-2001, 2004-2006, 2009-2025 Free Software Foundation, Inc. |
| 3 | 3 | ||
| 4 | This file is free software: you can redistribute it and/or modify | 4 | This file is free software: you can redistribute it and/or modify |
| 5 | it under the terms of the GNU Lesser General Public License as | 5 | it under the terms of the GNU Lesser General Public License as |
| @@ -42,15 +42,13 @@ | |||
| 42 | #include <config.h> | 42 | #include <config.h> |
| 43 | 43 | ||
| 44 | /* Get prototype. */ | 44 | /* Get prototype. */ |
| 45 | #define BASE64_INLINE _GL_EXTERN_INLINE | ||
| 45 | #include "base64.h" | 46 | #include "base64.h" |
| 46 | 47 | ||
| 47 | /* Get imalloc. */ | 48 | /* Get imalloc. */ |
| 48 | #include <ialloc.h> | 49 | #include <ialloc.h> |
| 49 | 50 | ||
| 50 | #include <intprops.h> | 51 | #include <stdckdint.h> |
| 51 | |||
| 52 | /* Get UCHAR_MAX. */ | ||
| 53 | #include <limits.h> | ||
| 54 | 52 | ||
| 55 | #include <string.h> | 53 | #include <string.h> |
| 56 | 54 | ||
| @@ -61,7 +59,7 @@ to_uchar (char ch) | |||
| 61 | return ch; | 59 | return ch; |
| 62 | } | 60 | } |
| 63 | 61 | ||
| 64 | static const char b64c[64] = | 62 | static const char b64c[64] _GL_ATTRIBUTE_NONSTRING = |
| 65 | "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; | 63 | "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; |
| 66 | 64 | ||
| 67 | /* Base64 encode IN array of size INLEN into OUT array. OUT needs | 65 | /* Base64 encode IN array of size INLEN into OUT array. OUT needs |
| @@ -150,7 +148,7 @@ base64_encode_alloc (const char *in, idx_t inlen, char **out) | |||
| 150 | Treat negative INLEN as overflow, for better compatibility with | 148 | Treat negative INLEN as overflow, for better compatibility with |
| 151 | pre-2021-08-27 API, which used size_t. */ | 149 | pre-2021-08-27 API, which used size_t. */ |
| 152 | idx_t in_over_3 = inlen / 3 + (inlen % 3 != 0), outlen; | 150 | idx_t in_over_3 = inlen / 3 + (inlen % 3 != 0), outlen; |
| 153 | if (! INT_MULTIPLY_OK (in_over_3, 4, &outlen) || inlen < 0) | 151 | if (ckd_mul (&outlen, in_over_3, 4) || inlen < 0) |
| 154 | { | 152 | { |
| 155 | *out = NULL; | 153 | *out = NULL; |
| 156 | return 0; | 154 | return 0; |
| @@ -242,7 +240,7 @@ base64_encode_alloc (const char *in, idx_t inlen, char **out) | |||
| 242 | : (_) == '/' ? 63 \ | 240 | : (_) == '/' ? 63 \ |
| 243 | : -1) | 241 | : -1) |
| 244 | 242 | ||
| 245 | static const signed char b64[0x100] = { | 243 | signed char const base64_to_int[256] = { |
| 246 | B64 (0), B64 (1), B64 (2), B64 (3), | 244 | B64 (0), B64 (1), B64 (2), B64 (3), |
| 247 | B64 (4), B64 (5), B64 (6), B64 (7), | 245 | B64 (4), B64 (5), B64 (6), B64 (7), |
| 248 | B64 (8), B64 (9), B64 (10), B64 (11), | 246 | B64 (8), B64 (9), B64 (10), B64 (11), |
| @@ -309,28 +307,6 @@ static const signed char b64[0x100] = { | |||
| 309 | B64 (252), B64 (253), B64 (254), B64 (255) | 307 | B64 (252), B64 (253), B64 (254), B64 (255) |
| 310 | }; | 308 | }; |
| 311 | 309 | ||
| 312 | #if UCHAR_MAX == 255 | ||
| 313 | # define uchar_in_range(c) true | ||
| 314 | #else | ||
| 315 | # define uchar_in_range(c) ((c) <= 255) | ||
| 316 | #endif | ||
| 317 | |||
| 318 | /* Return true if CH is a character from the Base64 alphabet, and | ||
| 319 | false otherwise. Note that '=' is padding and not considered to be | ||
| 320 | part of the alphabet. */ | ||
| 321 | bool | ||
| 322 | isbase64 (char ch) | ||
| 323 | { | ||
| 324 | return uchar_in_range (to_uchar (ch)) && 0 <= b64[to_uchar (ch)]; | ||
| 325 | } | ||
| 326 | |||
| 327 | /* Initialize decode-context buffer, CTX. */ | ||
| 328 | void | ||
| 329 | base64_decode_ctx_init (struct base64_decode_context *ctx) | ||
| 330 | { | ||
| 331 | ctx->i = 0; | ||
| 332 | } | ||
| 333 | |||
| 334 | /* If CTX->i is 0 or 4, there are four or more bytes in [*IN..IN_END), and | 310 | /* If CTX->i is 0 or 4, there are four or more bytes in [*IN..IN_END), and |
| 335 | none of those four is a newline, then return *IN. Otherwise, copy up to | 311 | none of those four is a newline, then return *IN. Otherwise, copy up to |
| 336 | 4 - CTX->i non-newline bytes from that range into CTX->buf, starting at | 312 | 4 - CTX->i non-newline bytes from that range into CTX->buf, starting at |
| @@ -405,8 +381,8 @@ decode_4 (char const *restrict in, idx_t inlen, | |||
| 405 | 381 | ||
| 406 | if (*outleft) | 382 | if (*outleft) |
| 407 | { | 383 | { |
| 408 | *out++ = ((b64[to_uchar (in[0])] << 2) | 384 | *out++ = ((base64_to_int[to_uchar (in[0])] << 2) |
| 409 | | (b64[to_uchar (in[1])] >> 4)); | 385 | | (base64_to_int[to_uchar (in[1])] >> 4)); |
| 410 | --*outleft; | 386 | --*outleft; |
| 411 | } | 387 | } |
| 412 | 388 | ||
| @@ -420,6 +396,10 @@ decode_4 (char const *restrict in, idx_t inlen, | |||
| 420 | 396 | ||
| 421 | if (in[3] != '=') | 397 | if (in[3] != '=') |
| 422 | return_false; | 398 | return_false; |
| 399 | |||
| 400 | /* Reject non-canonical encodings. */ | ||
| 401 | if (base64_to_int[to_uchar (in[1])] & 0x0f) | ||
| 402 | return_false; | ||
| 423 | } | 403 | } |
| 424 | else | 404 | else |
| 425 | { | 405 | { |
| @@ -428,8 +408,8 @@ decode_4 (char const *restrict in, idx_t inlen, | |||
| 428 | 408 | ||
| 429 | if (*outleft) | 409 | if (*outleft) |
| 430 | { | 410 | { |
| 431 | *out++ = (((b64[to_uchar (in[1])] << 4) & 0xf0) | 411 | *out++ = (((base64_to_int[to_uchar (in[1])] << 4) & 0xf0) |
| 432 | | (b64[to_uchar (in[2])] >> 2)); | 412 | | (base64_to_int[to_uchar (in[2])] >> 2)); |
| 433 | --*outleft; | 413 | --*outleft; |
| 434 | } | 414 | } |
| 435 | 415 | ||
| @@ -440,6 +420,10 @@ decode_4 (char const *restrict in, idx_t inlen, | |||
| 440 | { | 420 | { |
| 441 | if (inlen != 4) | 421 | if (inlen != 4) |
| 442 | return_false; | 422 | return_false; |
| 423 | |||
| 424 | /* Reject non-canonical encodings. */ | ||
| 425 | if (base64_to_int[to_uchar (in[2])] & 0x03) | ||
| 426 | return_false; | ||
| 443 | } | 427 | } |
| 444 | else | 428 | else |
| 445 | { | 429 | { |
| @@ -448,8 +432,8 @@ decode_4 (char const *restrict in, idx_t inlen, | |||
| 448 | 432 | ||
| 449 | if (*outleft) | 433 | if (*outleft) |
| 450 | { | 434 | { |
| 451 | *out++ = (((b64[to_uchar (in[2])] << 6) & 0xc0) | 435 | *out++ = (((base64_to_int[to_uchar (in[2])] << 6) & 0xc0) |
| 452 | | b64[to_uchar (in[3])]); | 436 | | base64_to_int[to_uchar (in[3])]); |
| 453 | --*outleft; | 437 | --*outleft; |
| 454 | } | 438 | } |
| 455 | } | 439 | } |
