in sdk/src/azure/core/az_base64.c [202:311]
static az_result _az_base64_decode(
az_span destination_bytes,
az_span source_base64_url_text,
int32_t* out_written,
_az_base64_mode mode)
{
int32_t source_length = az_span_size(source_base64_url_text);
uint8_t* source_ptr = az_span_ptr(source_base64_url_text);
int32_t destination_length = az_span_size(destination_bytes);
uint8_t* destination_ptr = az_span_ptr(destination_bytes);
if (destination_length < az_base64_get_max_decoded_size(source_length) - 2)
{
return AZ_ERROR_NOT_ENOUGH_SPACE;
}
int32_t source_index = 0;
int32_t destination_index = 0;
while (source_index < source_length - 4)
{
int32_t result = _az_base64_decode_four_bytes(source_ptr + source_index, mode);
if (result < 0)
{
return AZ_ERROR_UNEXPECTED_CHAR;
}
_az_base64_write_three_low_order_bytes(destination_ptr, result);
destination_ptr += 3;
destination_index += 3;
source_index += 4;
}
// If using standard base64 decoding, there is a precondition guaranteeing size is divisible by 4.
// Otherwise with url encoding, we can assume padding characters.
// If length is divisible by four, do nothing. Else, we assume up to two padding characters.
int32_t source_length_mod_four = source_length % 4;
int32_t i0 = *(source_ptr + source_index);
int32_t i1 = *(source_ptr + source_index + 1);
int32_t i2 = source_length_mod_four == 2 ? _az_ENCODING_PAD : *(source_ptr + source_index + 2);
int32_t i3 = source_length_mod_four == 2 || source_length_mod_four == 3
? _az_ENCODING_PAD
: *(source_ptr + source_index + 3);
i0 = _get_base64_decoded_char(i0, mode);
i1 = _get_base64_decoded_char(i1, mode);
i0 <<= 18;
i1 <<= 12;
i0 |= i1;
if (i3 != _az_ENCODING_PAD)
{
i2 = _get_base64_decoded_char(i2, mode);
i3 = _get_base64_decoded_char(i3, mode);
i2 <<= 6;
i0 |= i3;
i0 |= i2;
if (i0 < 0)
{
return AZ_ERROR_UNEXPECTED_CHAR;
}
if (destination_index > destination_length - 3)
{
return AZ_ERROR_NOT_ENOUGH_SPACE;
}
_az_base64_write_three_low_order_bytes(destination_ptr, i0);
destination_ptr += 3;
}
else if (i2 != _az_ENCODING_PAD)
{
i2 = _get_base64_decoded_char(i2, mode);
i2 <<= 6;
i0 |= i2;
if (i0 < 0)
{
return AZ_ERROR_UNEXPECTED_CHAR;
}
if (destination_index > destination_length - 2)
{
return AZ_ERROR_NOT_ENOUGH_SPACE;
}
*(destination_ptr + 1) = (uint8_t)(i0 >> 8);
*destination_ptr = (uint8_t)(i0 >> 16);
destination_ptr += 2;
}
else
{
if (i0 < 0)
{
return AZ_ERROR_UNEXPECTED_CHAR;
}
if (destination_index > destination_length - 1)
{
return AZ_ERROR_NOT_ENOUGH_SPACE;
}
*destination_ptr = (uint8_t)(i0 >> 16);
destination_ptr += 1;
}
*out_written = (int32_t)(destination_ptr - az_span_ptr(destination_bytes));
return AZ_OK;
}