base64: only allow padding bytes at the end of a string when decoding

This commit is contained in:
Craig Barnes 2020-11-30 06:06:28 +00:00
parent 0beed9fcf6
commit c66ad27cc8

View file

@ -12,8 +12,8 @@
#include "log.h" #include "log.h"
enum { enum {
P = 0, // Padding byte (=) P = 1 << 6, // Padding byte (=)
I = 128, // Invalid byte ([^A-Za-z0-9+/=]) I = 1 << 7, // Invalid byte ([^A-Za-z0-9+/=])
}; };
static const uint8_t reverse_lookup[256] = { static const uint8_t reverse_lookup[256] = {
@ -63,10 +63,16 @@ base64_decode(const char *s)
unsigned c = reverse_lookup[(unsigned char)s[i + 2]]; unsigned c = reverse_lookup[(unsigned char)s[i + 2]];
unsigned d = reverse_lookup[(unsigned char)s[i + 3]]; unsigned d = reverse_lookup[(unsigned char)s[i + 3]];
if (unlikely((a | b | c | d) & I)) { unsigned u = a | b | c | d;
free(ret); if (unlikely(u & I))
errno = EINVAL; goto invalid;
return NULL;
if (unlikely(u & P)) {
if (unlikely(i + 4 != len || (a | b) & P || (c & P && !(d & P))))
goto invalid;
c &= 63;
d &= 63;
} }
uint32_t v = a << 18 | b << 12 | c << 6 | d << 0; uint32_t v = a << 18 | b << 12 | c << 6 | d << 0;
@ -82,6 +88,11 @@ base64_decode(const char *s)
ret[len / 4 * 3] = '\0'; ret[len / 4 * 3] = '\0';
return ret; return ret;
invalid:
free(ret);
errno = EINVAL;
return NULL;
} }
char * char *