in src/azure_base64.c [236:364]
static STRING_HANDLE Base64_Encode_Internal(const unsigned char* source, size_t size)
{
STRING_HANDLE result;
size_t neededSize = 0;
bool isBufferOverflow = false;
char* encoded;
size_t currentPosition = 0;
neededSize = safe_add_size_t(neededSize, (size == 0) ? (0) : safe_multiply_size_t(safe_add_size_t(((safe_subtract_size_t(size, 1)) / 3), 1), 4));
neededSize = safe_add_size_t(neededSize, 1); /*+1 because \0 at the end of the string*/
if (neededSize == 0 || neededSize == SIZE_MAX)
{
result = NULL;
LogError("Azure_Base64_Encode:: Invalid size parameter, neededSize:%zu.", neededSize);
}
/*Codes_SRS_BASE64_06_006: [If when allocating memory to produce the encoding a failure occurs then Azure_Base64_Encode shall return NULL.]*/
else if ((encoded = (char*)malloc(neededSize)) == NULL)
{
result = NULL;
LogError("Azure_Base64_Encode:: Allocation failed.");
}
else
{
/*b0 b1(+1) b2(+2)
7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0
|----c1---| |----c2---| |----c3---| |----c4---|
*/
size_t destinationPosition = 0;
while (size - currentPosition >= 3)
{
char c1 = base64char(source[currentPosition] >> 2);
char c2 = base64char(
((source[currentPosition] & 3) << 4) |
(source[currentPosition + 1] >> 4)
);
char c3 = base64char(
((source[currentPosition + 1] & 0x0F) << 2) |
((source[currentPosition + 2] >> 6) & 3)
);
char c4 = base64char(
source[currentPosition + 2] & 0x3F
);
currentPosition += 3;
if ((destinationPosition + 4) > neededSize)
{
LogError("Azure_Base64_Encode:: Invalid buffer size.");
isBufferOverflow = true;
break;
}
encoded[destinationPosition++] = c1;
encoded[destinationPosition++] = c2;
encoded[destinationPosition++] = c3;
encoded[destinationPosition++] = c4;
}
if (!isBufferOverflow && size - currentPosition == 2)
{
if ((destinationPosition + 4) > neededSize)
{
LogError("Azure_Base64_Encode:: Invalid buffer size.");
isBufferOverflow = true;
}
else
{
char c1 = base64char(source[currentPosition] >> 2);
char c2 = base64char(
((source[currentPosition] & 0x03) << 4) |
(source[currentPosition + 1] >> 4)
);
char c3 = base64b16(source[currentPosition + 1] & 0x0F);
encoded[destinationPosition++] = c1;
encoded[destinationPosition++] = c2;
encoded[destinationPosition++] = c3;
encoded[destinationPosition++] = '=';
}
}
else if (!isBufferOverflow && size - currentPosition == 1)
{
if ((destinationPosition + 4) > neededSize)
{
LogError("Azure_Base64_Encode:: Invalid buffer size.");
isBufferOverflow = true;
}
else
{
char c1 = base64char(source[currentPosition] >> 2);
char c2 = base64b8(source[currentPosition] & 0x03);
encoded[destinationPosition++] = c1;
encoded[destinationPosition++] = c2;
encoded[destinationPosition++] = '=';
encoded[destinationPosition++] = '=';
}
}
/*null terminating the string*/
if (!isBufferOverflow)
{
if ((destinationPosition + 1) > neededSize)
{
LogError("Azure_Base64_Encode:: Invalid buffer size.");
isBufferOverflow = true;
}
else
{
encoded[destinationPosition] = '\0';
}
}
if (isBufferOverflow)
{
free(encoded);
result = NULL;
}
else
{
/*Codes_SRS_BASE64_06_007: [Otherwise Azure_Base64_Encode shall return a pointer to STRING, that string contains the base 64 encoding of input.]*/
result = STRING_new_with_memory(encoded);
if (result == NULL)
{
free(encoded);
LogError("Azure_Base64_Encode:: Allocation failed for return value.");
}
}
}
return result;
}