base64: faster base64 decoding
- by using a lookup table instead of strchr() - by doing full quantums first, then padding Closes #10032
This commit is contained in:
parent
8fe33a9661
commit
c6f602c93f
118
lib/base64.c
118
lib/base64.c
@ -51,39 +51,12 @@ static const char base64[]=
|
|||||||
static const char base64url[]=
|
static const char base64url[]=
|
||||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
|
||||||
|
|
||||||
static size_t decodeQuantum(unsigned char *dest, const char *src)
|
static const unsigned char decodetable[] =
|
||||||
{
|
{ 62, 255, 255, 255, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255, 255,
|
||||||
size_t padding = 0;
|
255, 255, 255, 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16,
|
||||||
const char *s;
|
17, 18, 19, 20, 21, 22, 23, 24, 25, 255, 255, 255, 255, 255, 255, 26, 27, 28,
|
||||||
unsigned long i, x = 0;
|
29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
|
||||||
|
48, 49, 50, 51 };
|
||||||
for(i = 0, s = src; i < 4; i++, s++) {
|
|
||||||
if(*s == '=') {
|
|
||||||
x <<= 6;
|
|
||||||
padding++;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
const char *p = strchr(base64, *s);
|
|
||||||
if(p)
|
|
||||||
x = (x << 6) + curlx_uztoul(p - base64);
|
|
||||||
else
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(padding < 1)
|
|
||||||
dest[2] = curlx_ultouc(x & 0xFFUL);
|
|
||||||
|
|
||||||
x >>= 8;
|
|
||||||
if(padding < 2)
|
|
||||||
dest[1] = curlx_ultouc(x & 0xFFUL);
|
|
||||||
|
|
||||||
x >>= 8;
|
|
||||||
dest[0] = curlx_ultouc(x & 0xFFUL);
|
|
||||||
|
|
||||||
return 3 - padding;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Curl_base64_decode()
|
* Curl_base64_decode()
|
||||||
*
|
*
|
||||||
@ -105,10 +78,11 @@ CURLcode Curl_base64_decode(const char *src,
|
|||||||
size_t padding = 0;
|
size_t padding = 0;
|
||||||
size_t i;
|
size_t i;
|
||||||
size_t numQuantums;
|
size_t numQuantums;
|
||||||
|
size_t fullQuantums;
|
||||||
size_t rawlen = 0;
|
size_t rawlen = 0;
|
||||||
const char *padptr;
|
|
||||||
unsigned char *pos;
|
unsigned char *pos;
|
||||||
unsigned char *newstr;
|
unsigned char *newstr;
|
||||||
|
unsigned char lookup[256];
|
||||||
|
|
||||||
*outptr = NULL;
|
*outptr = NULL;
|
||||||
*outlen = 0;
|
*outlen = 0;
|
||||||
@ -118,21 +92,18 @@ CURLcode Curl_base64_decode(const char *src,
|
|||||||
if(!srclen || srclen % 4)
|
if(!srclen || srclen % 4)
|
||||||
return CURLE_BAD_CONTENT_ENCODING;
|
return CURLE_BAD_CONTENT_ENCODING;
|
||||||
|
|
||||||
/* Find the position of any = padding characters */
|
/* srclen is at least 4 here */
|
||||||
padptr = strchr(src, '=');
|
while(src[srclen - 1 - padding] == '=') {
|
||||||
if(padptr) {
|
/* count padding characters */
|
||||||
padding++;
|
padding++;
|
||||||
/* A maximum of two = padding characters is allowed */
|
/* A maximum of two = padding characters is allowed */
|
||||||
if(padptr[1] == '=')
|
if(padding > 2)
|
||||||
padding++;
|
|
||||||
|
|
||||||
/* Check the = padding characters weren't part way through the input */
|
|
||||||
if(padptr + padding != src + srclen)
|
|
||||||
return CURLE_BAD_CONTENT_ENCODING;
|
return CURLE_BAD_CONTENT_ENCODING;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Calculate the number of quantums */
|
/* Calculate the number of quantums */
|
||||||
numQuantums = srclen / 4;
|
numQuantums = srclen / 4;
|
||||||
|
fullQuantums = numQuantums - (padding ? 1 : 0);
|
||||||
|
|
||||||
/* Calculate the size of the decoded string */
|
/* Calculate the size of the decoded string */
|
||||||
rawlen = (numQuantums * 3) - padding;
|
rawlen = (numQuantums * 3) - padding;
|
||||||
@ -144,17 +115,59 @@ CURLcode Curl_base64_decode(const char *src,
|
|||||||
|
|
||||||
pos = newstr;
|
pos = newstr;
|
||||||
|
|
||||||
/* Decode the quantums */
|
memset(lookup, 0xff, sizeof(lookup));
|
||||||
for(i = 0; i < numQuantums; i++) {
|
memcpy(&lookup['+'], decodetable, sizeof(decodetable));
|
||||||
size_t result = decodeQuantum(pos, src);
|
/* replaces
|
||||||
if(!result) {
|
{
|
||||||
free(newstr);
|
unsigned char c;
|
||||||
|
const unsigned char *p = (const unsigned char *)base64;
|
||||||
return CURLE_BAD_CONTENT_ENCODING;
|
for(c = 0; *p; c++, p++)
|
||||||
|
lookup[*p] = c;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
pos += result;
|
/* Decode the complete quantums first */
|
||||||
src += 4;
|
for(i = 0; i < fullQuantums; i++) {
|
||||||
|
unsigned char val;
|
||||||
|
unsigned int x = 0;
|
||||||
|
int j;
|
||||||
|
|
||||||
|
for(j = 0; j < 4; j++) {
|
||||||
|
val = lookup[(unsigned char)*src++];
|
||||||
|
if(val == 0xff) /* bad symbol */
|
||||||
|
goto bad;
|
||||||
|
x = (x << 6) | val;
|
||||||
|
}
|
||||||
|
pos[2] = x & 0xff;
|
||||||
|
pos[1] = (x >> 8) & 0xff;
|
||||||
|
pos[0] = (x >> 16) & 0xff;
|
||||||
|
pos += 3;
|
||||||
|
}
|
||||||
|
if(padding) {
|
||||||
|
/* this means either 8 or 16 bits output */
|
||||||
|
unsigned char val;
|
||||||
|
unsigned int x = 0;
|
||||||
|
int j;
|
||||||
|
size_t padc = 0;
|
||||||
|
for(j = 0; j < 4; j++) {
|
||||||
|
if(*src == '=') {
|
||||||
|
x <<= 6;
|
||||||
|
src++;
|
||||||
|
if(++padc > padding)
|
||||||
|
/* this is a badly placed '=' symbol! */
|
||||||
|
goto bad;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
val = lookup[(unsigned char)*src++];
|
||||||
|
if(val == 0xff) /* bad symbol */
|
||||||
|
goto bad;
|
||||||
|
x = (x << 6) | val;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(padding == 1)
|
||||||
|
pos[1] = (x >> 8) & 0xff;
|
||||||
|
pos[0] = (x >> 16) & 0xff;
|
||||||
|
pos += 3 - padding;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Zero terminate */
|
/* Zero terminate */
|
||||||
@ -165,6 +178,9 @@ CURLcode Curl_base64_decode(const char *src,
|
|||||||
*outlen = rawlen;
|
*outlen = rawlen;
|
||||||
|
|
||||||
return CURLE_OK;
|
return CURLE_OK;
|
||||||
|
bad:
|
||||||
|
free(newstr);
|
||||||
|
return CURLE_BAD_CONTENT_ENCODING;
|
||||||
}
|
}
|
||||||
|
|
||||||
static CURLcode base64_encode(const char *table64,
|
static CURLcode base64_encode(const char *table64,
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user