aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/fns.c221
1 files changed, 124 insertions, 97 deletions
diff --git a/src/fns.c b/src/fns.c
index 3dad8f5f5fb..7d5443150d4 100644
--- a/src/fns.c
+++ b/src/fns.c
@@ -3186,33 +3186,11 @@ The data read from the system are decoded using `locale-coding-system'. */)
3186 3186
3187#define MIME_LINE_LENGTH 76 3187#define MIME_LINE_LENGTH 76
3188 3188
3189#define IS_ASCII(Character) \ 3189/* Tables of characters coding the 64 values. */
3190 ((Character) < 128) 3190static char const base64_value_to_char[2][64] =
3191#define IS_BASE64(Character) \
3192 (IS_ASCII (Character) && b64_char_to_value[Character] >= 0)
3193#define IS_BASE64_IGNORABLE(Character) \
3194 ((Character) == ' ' || (Character) == '\t' || (Character) == '\n' \
3195 || (Character) == '\f' || (Character) == '\r')
3196
3197/* Used by base64_decode_1 to retrieve a non-base64-ignorable
3198 character or return retval if there are no characters left to
3199 process. */
3200#define READ_QUADRUPLET_BYTE(retval) \
3201 do \
3202 { \
3203 if (i == length) \
3204 { \
3205 if (nchars_return) \
3206 *nchars_return = nchars; \
3207 return (retval); \
3208 } \
3209 c = from[i++]; \
3210 } \
3211 while (IS_BASE64_IGNORABLE (c))
3212
3213/* Table of characters coding the 64 values. */
3214static const char base64_value_to_char[64] =
3215{ 3191{
3192 /* base64 */
3193 {
3216 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', /* 0- 9 */ 3194 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', /* 0- 9 */
3217 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', /* 10-19 */ 3195 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', /* 10-19 */
3218 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', /* 20-29 */ 3196 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', /* 20-29 */
@@ -3220,10 +3198,9 @@ static const char base64_value_to_char[64] =
3220 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', /* 40-49 */ 3198 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', /* 40-49 */
3221 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', /* 50-59 */ 3199 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', /* 50-59 */
3222 '8', '9', '+', '/' /* 60-63 */ 3200 '8', '9', '+', '/' /* 60-63 */
3223}; 3201 },
3224 3202 /* base64url */
3225static const char base64url_value_to_char[64] = 3203 {
3226{
3227 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', /* 0- 9 */ 3204 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', /* 0- 9 */
3228 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', /* 10-19 */ 3205 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', /* 10-19 */
3229 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', /* 20-29 */ 3206 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd', /* 20-29 */
@@ -3231,41 +3208,47 @@ static const char base64url_value_to_char[64] =
3231 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', /* 40-49 */ 3208 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', /* 40-49 */
3232 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', /* 50-59 */ 3209 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', /* 50-59 */
3233 '8', '9', '-', '_' /* 60-63 */ 3210 '8', '9', '-', '_' /* 60-63 */
3211 }
3234}; 3212};
3235 3213
3236/* Table of base64 values for first 128 characters. */ 3214/* Tables of base64 values for bytes. -1 means ignorable, 0 invalid,
3237static const short base64_char_to_value[128] = 3215 positive means 1 + the represented value. */
3238{ 3216static signed char const base64_char_to_value[2][UCHAR_MAX] =
3239 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0- 9 */ 3217{
3240 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 10- 19 */ 3218 /* base64 */
3241 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 20- 29 */ 3219 {
3242 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 30- 39 */ 3220 ['\t']= -1, ['\n']= -1, ['\f']= -1, ['\r']= -1, [' '] = -1,
3243 -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, /* 40- 49 */ 3221 ['A'] = 1, ['B'] = 2, ['C'] = 3, ['D'] = 4, ['E'] = 5,
3244 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, /* 50- 59 */ 3222 ['F'] = 6, ['G'] = 7, ['H'] = 8, ['I'] = 9, ['J'] = 10,
3245 -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, /* 60- 69 */ 3223 ['K'] = 11, ['L'] = 12, ['M'] = 13, ['N'] = 14, ['O'] = 15,
3246 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, /* 70- 79 */ 3224 ['P'] = 16, ['Q'] = 17, ['R'] = 18, ['S'] = 19, ['T'] = 20,
3247 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, /* 80- 89 */ 3225 ['U'] = 21, ['V'] = 22, ['W'] = 23, ['X'] = 24, ['Y'] = 25, ['Z'] = 26,
3248 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, /* 90- 99 */ 3226 ['a'] = 27, ['b'] = 28, ['c'] = 29, ['d'] = 30, ['e'] = 31,
3249 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, /* 100-109 */ 3227 ['f'] = 32, ['g'] = 33, ['h'] = 34, ['i'] = 35, ['j'] = 36,
3250 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, /* 110-119 */ 3228 ['k'] = 37, ['l'] = 38, ['m'] = 39, ['n'] = 40, ['o'] = 41,
3251 49, 50, 51, -1, -1, -1, -1, -1 /* 120-127 */ 3229 ['p'] = 42, ['q'] = 43, ['r'] = 44, ['s'] = 45, ['t'] = 46,
3252}; 3230 ['u'] = 47, ['v'] = 48, ['w'] = 49, ['x'] = 50, ['y'] = 51, ['z'] = 52,
3253 3231 ['0'] = 53, ['1'] = 54, ['2'] = 55, ['3'] = 56, ['4'] = 57,
3254static const short base64url_char_to_value[128] = 3232 ['5'] = 58, ['6'] = 59, ['7'] = 60, ['8'] = 61, ['9'] = 62,
3255{ 3233 ['+'] = 63, ['/'] = 64
3256 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0- 9 */ 3234 },
3257 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 10- 19 */ 3235 /* base64url */
3258 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 20- 29 */ 3236 {
3259 -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 30- 39 */ 3237 ['\t']= -1, ['\n']= -1, ['\f']= -1, ['\r']= -1, [' '] = -1,
3260 -1, -1, -1, -1, -1, 62, -1, -1, 52, 53, /* 40- 49 */ 3238 ['A'] = 1, ['B'] = 2, ['C'] = 3, ['D'] = 4, ['E'] = 5,
3261 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, /* 50- 59 */ 3239 ['F'] = 6, ['G'] = 7, ['H'] = 8, ['I'] = 9, ['J'] = 10,
3262 -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, /* 60- 69 */ 3240 ['K'] = 11, ['L'] = 12, ['M'] = 13, ['N'] = 14, ['O'] = 15,
3263 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, /* 70- 79 */ 3241 ['P'] = 16, ['Q'] = 17, ['R'] = 18, ['S'] = 19, ['T'] = 20,
3264 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, /* 80- 89 */ 3242 ['U'] = 21, ['V'] = 22, ['W'] = 23, ['X'] = 24, ['Y'] = 25, ['Z'] = 26,
3265 25, -1, -1, -1, -1, 63, -1, 26, 27, 28, /* 90- 99 */ 3243 ['a'] = 27, ['b'] = 28, ['c'] = 29, ['d'] = 30, ['e'] = 31,
3266 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, /* 100-109 */ 3244 ['f'] = 32, ['g'] = 33, ['h'] = 34, ['i'] = 35, ['j'] = 36,
3267 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, /* 110-119 */ 3245 ['k'] = 37, ['l'] = 38, ['m'] = 39, ['n'] = 40, ['o'] = 41,
3268 49, 50, 51, -1, -1, -1, -1, -1 /* 120-127 */ 3246 ['p'] = 42, ['q'] = 43, ['r'] = 44, ['s'] = 45, ['t'] = 46,
3247 ['u'] = 47, ['v'] = 48, ['w'] = 49, ['x'] = 50, ['y'] = 51, ['z'] = 52,
3248 ['0'] = 53, ['1'] = 54, ['2'] = 55, ['3'] = 56, ['4'] = 57,
3249 ['5'] = 58, ['6'] = 59, ['7'] = 60, ['8'] = 61, ['9'] = 62,
3250 ['-'] = 63, ['_'] = 64
3251 }
3269}; 3252};
3270 3253
3271/* The following diagram shows the logical steps by which three octets 3254/* The following diagram shows the logical steps by which three octets
@@ -3454,7 +3437,7 @@ base64_encode_1 (const char *from, char *to, ptrdiff_t length,
3454 int c; 3437 int c;
3455 unsigned int value; 3438 unsigned int value;
3456 int bytes; 3439 int bytes;
3457 char const *b64_value_to_char = (base64url) ? base64url_value_to_char : base64_value_to_char; 3440 char const *b64_value_to_char = base64_value_to_char[base64url];
3458 3441
3459 while (i < length) 3442 while (i < length)
3460 { 3443 {
@@ -3632,8 +3615,9 @@ the base 64 encoding, as defined in RFC 4648. */)
3632 decoded = SAFE_ALLOCA (length); 3615 decoded = SAFE_ALLOCA (length);
3633 3616
3634 /* The decoded result should be unibyte. */ 3617 /* The decoded result should be unibyte. */
3618 ptrdiff_t decoded_chars;
3635 decoded_length = base64_decode_1 (SSDATA (string), decoded, length, 3619 decoded_length = base64_decode_1 (SSDATA (string), decoded, length,
3636 !NILP (base64url), 0, NULL); 3620 !NILP (base64url), 0, &decoded_chars);
3637 if (decoded_length > length) 3621 if (decoded_length > length)
3638 emacs_abort (); 3622 emacs_abort ();
3639 else if (decoded_length >= 0) 3623 else if (decoded_length >= 0)
@@ -3650,41 +3634,60 @@ the base 64 encoding, as defined in RFC 4648. */)
3650 3634
3651/* Base64-decode the data at FROM of LENGTH bytes into TO. If 3635/* Base64-decode the data at FROM of LENGTH bytes into TO. If
3652 MULTIBYTE, the decoded result should be in multibyte 3636 MULTIBYTE, the decoded result should be in multibyte
3653 form. If NCHARS_RETURN is not NULL, store the number of produced 3637 form. Store the number of produced characters in *NCHARS_RETURN. */
3654 characters in *NCHARS_RETURN. */
3655 3638
3656static ptrdiff_t 3639static ptrdiff_t
3657base64_decode_1 (const char *from, char *to, ptrdiff_t length, 3640base64_decode_1 (const char *from, char *to, ptrdiff_t length,
3658 bool base64url, 3641 bool base64url,
3659 bool multibyte, ptrdiff_t *nchars_return) 3642 bool multibyte, ptrdiff_t *nchars_return)
3660{ 3643{
3661 ptrdiff_t i = 0; /* Used inside READ_QUADRUPLET_BYTE */ 3644 char const *f = from;
3645 char const *flim = from + length;
3662 char *e = to; 3646 char *e = to;
3663 unsigned char c;
3664 unsigned long value;
3665 ptrdiff_t nchars = 0; 3647 ptrdiff_t nchars = 0;
3666 short const *b64_char_to_value = (base64url) ? base64url_char_to_value : base64_char_to_value; 3648 signed char const *b64_char_to_value = base64_char_to_value[base64url];
3649 unsigned char multibyte_bit = multibyte << 7;
3667 3650
3668 while (1) 3651 while (true)
3669 { 3652 {
3653 unsigned char c;
3654 int v1;
3655
3670 /* Process first byte of a quadruplet. */ 3656 /* Process first byte of a quadruplet. */
3671 3657
3672 READ_QUADRUPLET_BYTE (e-to); 3658 do
3659 {
3660 if (f == flim)
3661 {
3662 *nchars_return = nchars;
3663 return e - to;
3664 }
3665 c = *f++;
3666 v1 = b64_char_to_value[c];
3667 }
3668 while (v1 < 0);
3673 3669
3674 if (!IS_BASE64 (c)) 3670 if (v1 == 0)
3675 return -1; 3671 return -1;
3676 value = b64_char_to_value[c] << 18; 3672 unsigned int value = (v1 - 1) << 18;
3677 3673
3678 /* Process second byte of a quadruplet. */ 3674 /* Process second byte of a quadruplet. */
3679 3675
3680 READ_QUADRUPLET_BYTE (-1); 3676 do
3677 {
3678 if (f == flim)
3679 return -1;
3680 c = *f++;
3681 v1 = b64_char_to_value[c];
3682 }
3683 while (v1 < 0);
3681 3684
3682 if (!IS_BASE64 (c)) 3685 if (v1 == 0)
3683 return -1; 3686 return -1;
3684 value |= b64_char_to_value[c] << 12; 3687 value += (v1 - 1) << 12;
3685 3688
3686 c = (unsigned char) (value >> 16); 3689 c = value >> 16 & 0xff;
3687 if (multibyte && c >= 128) 3690 if (c & multibyte_bit)
3688 e += BYTE8_STRING (c, e); 3691 e += BYTE8_STRING (c, e);
3689 else 3692 else
3690 *e++ = c; 3693 *e++ = c;
@@ -3692,26 +3695,41 @@ base64_decode_1 (const char *from, char *to, ptrdiff_t length,
3692 3695
3693 /* Process third byte of a quadruplet. */ 3696 /* Process third byte of a quadruplet. */
3694 3697
3695 if (!base64url) 3698 do
3696 READ_QUADRUPLET_BYTE (-1); 3699 {
3697 else 3700 if (f == flim)
3698 READ_QUADRUPLET_BYTE (e-to); 3701 {
3702 if (!base64url)
3703 return -1;
3704 *nchars_return = nchars;
3705 return e - to;
3706 }
3707 c = *f++;
3708 v1 = b64_char_to_value[c];
3709 }
3710 while (v1 < 0);
3699 3711
3700 if (c == '=') 3712 if (c == '=')
3701 { 3713 {
3702 READ_QUADRUPLET_BYTE (-1); 3714 do
3715 {
3716 if (f == flim)
3717 return -1;
3718 c = *f++;
3719 }
3720 while (b64_char_to_value[c] < 0);
3703 3721
3704 if (c != '=') 3722 if (c != '=')
3705 return -1; 3723 return -1;
3706 continue; 3724 continue;
3707 } 3725 }
3708 3726
3709 if (!IS_BASE64 (c)) 3727 if (v1 == 0)
3710 return -1; 3728 return -1;
3711 value |= b64_char_to_value[c] << 6; 3729 value += (v1 - 1) << 6;
3712 3730
3713 c = (unsigned char) (0xff & value >> 8); 3731 c = value >> 8 & 0xff;
3714 if (multibyte && c >= 128) 3732 if (c & multibyte_bit)
3715 e += BYTE8_STRING (c, e); 3733 e += BYTE8_STRING (c, e);
3716 else 3734 else
3717 *e++ = c; 3735 *e++ = c;
@@ -3719,20 +3737,29 @@ base64_decode_1 (const char *from, char *to, ptrdiff_t length,
3719 3737
3720 /* Process fourth byte of a quadruplet. */ 3738 /* Process fourth byte of a quadruplet. */
3721 3739
3722 if (!base64url) 3740 do
3723 READ_QUADRUPLET_BYTE (-1); 3741 {
3724 else 3742 if (f == flim)
3725 READ_QUADRUPLET_BYTE (e-to); 3743 {
3744 if (!base64url)
3745 return -1;
3746 *nchars_return = nchars;
3747 return e - to;
3748 }
3749 c = *f++;
3750 v1 = b64_char_to_value[c];
3751 }
3752 while (v1 < 0);
3726 3753
3727 if (c == '=') 3754 if (c == '=')
3728 continue; 3755 continue;
3729 3756
3730 if (!IS_BASE64 (c)) 3757 if (v1 < 0)
3731 return -1; 3758 return -1;
3732 value |= b64_char_to_value[c]; 3759 value += v1 - 1;
3733 3760
3734 c = (unsigned char) (0xff & value); 3761 c = value & 0xff;
3735 if (multibyte && c >= 128) 3762 if (c & multibyte_bit)
3736 e += BYTE8_STRING (c, e); 3763 e += BYTE8_STRING (c, e);
3737 else 3764 else
3738 *e++ = c; 3765 *e++ = c;