Hello all,
I discovered a buffer overflow bug in the base64_encode() function,
located at line 1905 in file src\utils.c. Note that this bug is in the
latest version of the program (version 1.10.2) The bug appears to be that
the function is assuming that the input data is a size that is an even
multiple of 3 bytes. No doubt this is due to the fact that the base 64
algorithm is converting data to base 64 three bytes at a time. The
problem here is that if the block of data is not an even multiple of 3
bytes, then the last group of bytes will be either 1 or 2 bytes long.
This means that the only the last 1 or 2 bytes should be used in the base
64 algorithm. The remaining of the 3 bytes that is not used should be 0.
This function incorrectly indexes all 3 bytes. This has the effect of
reading 1 or 2 bytes past the end of the input buffer. Hence, causing a
potential buffer overflow. To see a trivial test of this bug, pass in the
string "a" as the data to be encoded in base 64. You will see that it
properly applies the "a" byte to the algorithm, but it then goes on and
applies the two bytes following "a" in memory to the algorithm. Granted,
later in the function it then properly overwrites the incorrect bytes in
the encode data with '=' signs to pad it out properly, but the fact
remains that it should not be reading past the end of the buffer here.
I have attached a source file containing a fixed version the function that
does not have the buffer overflow problem.
int
base64_encode (const char *str, int length, char *b64store)
{
// Conversion table.
static char tbl[64] = {
'A','B','C','D','E','F','G','H',
'I','J','K','L','M','N','O','P',
'Q','R','S','T','U','V','W','X',
'Y','Z','a','b','c','d','e','f',
'g','h','i','j','k','l','m','n',
'o','p','q','r','s','t','u','v',
'w','x','y','z','0','1','2','3',
'4','5','6','7','8','9','+','/'
};
size_t i;
const unsigned char *s = str;
unsigned char val[3];
char *p = b64store;
// Transform the 3x8 bits to 4x6 bits, as required by base64.
for (i = 0; i < length; i += 3)
{
val[0] = s[0];
val[1] = ( i+1 < length ) ? s[1] : 0;
val[2] = ( i+2 < length ) ? s[2] : 0;
*p++ = tbl[ val[0] >> 2];
*p++ = tbl[(( val[0] & 3) << 4) + (val[1] >> 4)];
*p++ = tbl[(( val[1] & 0xf) << 2) + ( val[2] >> 6)];
*p++ = tbl[ val[2] & 0x3f];
s += 3;
}
// Pad the result if necessary...
if (i == length + 1)
*(p - 1) = '=';
else if (i == length + 2)
*(p - 1) = *(p - 2) = '=';
// ...and zero-terminate it.
*p = '\0';
return p - b64store;
}