in src/azure_base32.c [172:281]
static BUFFER_HANDLE base32_decode_impl(const char* source)
{
BUFFER_HANDLE result;
size_t src_length = strlen(source);
if (src_length % BASE32_INPUT_SIZE != 0)
{
/* Codes_SRS_BASE32_07_021: [ If the source length is not evenly divisible by 8, base32_decode_impl shall return NULL. ] */
LogError("Failure invalid input length %lu", (unsigned long)src_length);
result = NULL;
}
else
{
size_t dest_size = 0;
unsigned char* temp_buffer;
unsigned char* dest_buff;
bool continue_processing = true;
unsigned char input[8];
const char* iterator = source;
/* Codes_SRS_BASE32_07_022: [ base32_decode_impl shall allocate a temp buffer to store the in process value. ] */
size_t allocation_len = base32_decoding_length(src_length);
if ((temp_buffer = (unsigned char*)malloc(allocation_len)) == NULL)
{
/* Codes_SRS_BASE32_07_023: [ If an error is encountered, base32_decode_impl shall return NULL. ] */
LogError("Failure allocating buffer");
result = NULL;
}
else
{
dest_buff = temp_buffer;
while (*iterator != '\0')
{
size_t index = 0;
/* Codes_SRS_BASE32_07_024: [ base32_decode_impl shall loop through and collect 8 characters from the source variable. ] */
for (index = 0; index < BASE32_INPUT_SIZE; index++)
{
input[index] = *iterator;
iterator++;
if (input[index] >= ASCII_VALUE_MAX)
{
LogError("Failure source encoding");
continue_processing = false;
break;
}
input[index] = convert_value_to_base32_char(input[index]);
}
if (!continue_processing)
{
result = NULL;
break;
}
else if ((dest_size + TARGET_BLOCK_SIZE) > allocation_len)
{
LogError("Failure target length exceeded");
result = NULL;
continue_processing = false;
break;
}
else
{
// Codes_SRS_BASE32_07_025: [ base32_decode_impl shall group 5 bytes at a time into the temp buffer. ]
*dest_buff++ = ((input[0] & 0x1f) << 3) | ((input[1] & 0x1c) >> 2);
*dest_buff++ = ((input[1] & 0x03) << 6) | ((input[2] & 0x1f) << 1) | ((input[3] & 0x10) >> 4);
*dest_buff++ = ((input[3] & 0x0f) << 4) | ((input[4] & 0x1e) >> 1);
*dest_buff++ = ((input[4] & 0x01) << 7) | ((input[5] & 0x1f) << 2) | ((input[6] & 0x18) >> 3);
*dest_buff++ = ((input[6] & 0x07) << 5) | (input[7] & 0x1f);
dest_size += TARGET_BLOCK_SIZE;
// If there is padding remove it
// Because we are packing 5 bytes into an 8 byte variable we need to check every other
// variable for padding
if (input[7] == BASE32_EQUAL_SIGN)
{
--dest_size;
if (input[5] == BASE32_EQUAL_SIGN)
{
--dest_size;
if (input[4] == BASE32_EQUAL_SIGN)
{
--dest_size;
if (input[2] == BASE32_EQUAL_SIGN)
{
--dest_size;
}
}
}
}
}
}
if (!continue_processing)
{
result = NULL;
}
else
{
/* Codes_SRS_BASE32_07_026: [ Once base32_decode_impl is complete it shall create a BUFFER with the temp buffer. ] */
result = BUFFER_create(temp_buffer, dest_size);
if (result == NULL)
{
LogError("Failure: BUFFER_create failed to create decoded buffer");
}
}
free(temp_buffer);
}
}
return result;
}