diff options
Diffstat (limited to 'gl/base64.c')
| -rw-r--r-- | gl/base64.c | 66 |
1 files changed, 34 insertions, 32 deletions
diff --git a/gl/base64.c b/gl/base64.c index c8b3b76b..77ee371b 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-2024 Free Software Foundation, Inc. | 2 | Copyright (C) 1999-2001, 2004-2006, 2009-2026 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 |
| @@ -39,16 +39,16 @@ | |||
| 39 | * | 39 | * |
| 40 | */ | 40 | */ |
| 41 | 41 | ||
| 42 | #define BASE64_INLINE _GL_EXTERN_INLINE | ||
| 42 | #include <config.h> | 43 | #include <config.h> |
| 43 | 44 | ||
| 44 | /* Get prototype. */ | 45 | /* Get prototype. */ |
| 45 | #define BASE64_INLINE _GL_EXTERN_INLINE | ||
| 46 | #include "base64.h" | 46 | #include "base64.h" |
| 47 | 47 | ||
| 48 | /* Get imalloc. */ | 48 | /* Get imalloc. */ |
| 49 | #include <ialloc.h> | 49 | #include <ialloc.h> |
| 50 | 50 | ||
| 51 | #include <intprops.h> | 51 | #include <stdckdint.h> |
| 52 | 52 | ||
| 53 | #include <string.h> | 53 | #include <string.h> |
| 54 | 54 | ||
| @@ -59,7 +59,7 @@ to_uchar (char ch) | |||
| 59 | return ch; | 59 | return ch; |
| 60 | } | 60 | } |
| 61 | 61 | ||
| 62 | static const char b64c[64] = | 62 | static const char b64c[64] _GL_ATTRIBUTE_NONSTRING = |
| 63 | "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; | 63 | "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; |
| 64 | 64 | ||
| 65 | /* 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 |
| @@ -148,7 +148,7 @@ base64_encode_alloc (const char *in, idx_t inlen, char **out) | |||
| 148 | Treat negative INLEN as overflow, for better compatibility with | 148 | Treat negative INLEN as overflow, for better compatibility with |
| 149 | pre-2021-08-27 API, which used size_t. */ | 149 | pre-2021-08-27 API, which used size_t. */ |
| 150 | idx_t in_over_3 = inlen / 3 + (inlen % 3 != 0), outlen; | 150 | idx_t in_over_3 = inlen / 3 + (inlen % 3 != 0), outlen; |
| 151 | if (! INT_MULTIPLY_OK (in_over_3, 4, &outlen) || inlen < 0) | 151 | if (ckd_mul (&outlen, in_over_3, 4) || inlen < 0) |
| 152 | { | 152 | { |
| 153 | *out = NULL; | 153 | *out = NULL; |
| 154 | return 0; | 154 | return 0; |
| @@ -372,13 +372,14 @@ static bool | |||
| 372 | decode_4 (char const *restrict in, idx_t inlen, | 372 | decode_4 (char const *restrict in, idx_t inlen, |
| 373 | char *restrict *outp, idx_t *outleft) | 373 | char *restrict *outp, idx_t *outleft) |
| 374 | { | 374 | { |
| 375 | char *out = *outp; | ||
| 376 | if (inlen < 2) | 375 | if (inlen < 2) |
| 377 | return false; | 376 | return false; |
| 378 | 377 | ||
| 379 | if (!isbase64 (in[0]) || !isbase64 (in[1])) | 378 | if (!isbase64 (in[0]) || !isbase64 (in[1])) |
| 380 | return false; | 379 | return false; |
| 381 | 380 | ||
| 381 | char *out = *outp; | ||
| 382 | |||
| 382 | if (*outleft) | 383 | if (*outleft) |
| 383 | { | 384 | { |
| 384 | *out++ = ((base64_to_int[to_uchar (in[0])] << 2) | 385 | *out++ = ((base64_to_int[to_uchar (in[0])] << 2) |
| @@ -466,7 +467,6 @@ base64_decode_ctx (struct base64_decode_context *ctx, | |||
| 466 | const char *restrict in, idx_t inlen, | 467 | const char *restrict in, idx_t inlen, |
| 467 | char *restrict out, idx_t *outlen) | 468 | char *restrict out, idx_t *outlen) |
| 468 | { | 469 | { |
| 469 | idx_t outleft = *outlen; | ||
| 470 | bool ignore_newlines = ctx != NULL; | 470 | bool ignore_newlines = ctx != NULL; |
| 471 | bool flush_ctx = false; | 471 | bool flush_ctx = false; |
| 472 | unsigned int ctx_i = 0; | 472 | unsigned int ctx_i = 0; |
| @@ -477,6 +477,7 @@ base64_decode_ctx (struct base64_decode_context *ctx, | |||
| 477 | flush_ctx = inlen == 0; | 477 | flush_ctx = inlen == 0; |
| 478 | } | 478 | } |
| 479 | 479 | ||
| 480 | idx_t outleft = *outlen; | ||
| 480 | 481 | ||
| 481 | while (true) | 482 | while (true) |
| 482 | { | 483 | { |
| @@ -505,35 +506,36 @@ base64_decode_ctx (struct base64_decode_context *ctx, | |||
| 505 | { | 506 | { |
| 506 | ++in; | 507 | ++in; |
| 507 | --inlen; | 508 | --inlen; |
| 508 | continue; | ||
| 509 | } | 509 | } |
| 510 | else | ||
| 511 | { | ||
| 512 | /* Restore OUT and OUTLEFT. */ | ||
| 513 | out -= outleft_save - outleft; | ||
| 514 | outleft = outleft_save; | ||
| 510 | 515 | ||
| 511 | /* Restore OUT and OUTLEFT. */ | ||
| 512 | out -= outleft_save - outleft; | ||
| 513 | outleft = outleft_save; | ||
| 514 | |||
| 515 | { | ||
| 516 | char const *in_end = in + inlen; | ||
| 517 | char const *non_nl; | ||
| 518 | |||
| 519 | if (ignore_newlines) | ||
| 520 | non_nl = get_4 (ctx, &in, in_end, &inlen); | ||
| 521 | else | ||
| 522 | non_nl = in; /* Might have nl in this case. */ | ||
| 523 | |||
| 524 | /* If the input is empty or consists solely of newlines (0 non-newlines), | ||
| 525 | then we're done. Likewise if there are fewer than 4 bytes when not | ||
| 526 | flushing context and not treating newlines as garbage. */ | ||
| 527 | if (inlen == 0 || (inlen < 4 && !flush_ctx && ignore_newlines)) | ||
| 528 | { | 516 | { |
| 529 | inlen = 0; | 517 | char const *in_end = in + inlen; |
| 530 | break; | 518 | |
| 531 | } | 519 | char const *non_nl; |
| 532 | if (!decode_4 (non_nl, inlen, &out, &outleft)) | 520 | if (ignore_newlines) |
| 533 | break; | 521 | non_nl = get_4 (ctx, &in, in_end, &inlen); |
| 522 | else | ||
| 523 | non_nl = in; /* Might have nl in this case. */ | ||
| 524 | |||
| 525 | /* If the input is empty or consists solely of newlines (0 non-newlines), | ||
| 526 | then we're done. Likewise if there are fewer than 4 bytes when not | ||
| 527 | flushing context and not treating newlines as garbage. */ | ||
| 528 | if (inlen == 0 || (inlen < 4 && !flush_ctx && ignore_newlines)) | ||
| 529 | { | ||
| 530 | inlen = 0; | ||
| 531 | break; | ||
| 532 | } | ||
| 533 | if (!decode_4 (non_nl, inlen, &out, &outleft)) | ||
| 534 | break; | ||
| 534 | 535 | ||
| 535 | inlen = in_end - in; | 536 | inlen = in_end - in; |
| 536 | } | 537 | } |
| 538 | } | ||
| 537 | } | 539 | } |
| 538 | 540 | ||
| 539 | *outlen -= outleft; | 541 | *outlen -= outleft; |
