util/base64: Extend b64 decode to calculate exact len

When attempting to decode a base64 string, while there is a way to
calculate the maximum possible decode length, there isn't a way to
calculate the exact decode length without duplicating some base64
specific logic located in spdk_base64_decode. With this change, the
spdk_base64_decode function can now optionally calculate the exact
decode length without actually performing the decode by passing NULL
in as the dst argument.

Change-Id: Ice83db979f86a6fe9f39d236d3083102ca37ec68
Signed-off-by: Mike Carlin <mikefcarlin@protonmail.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/479479
Tested-by: SPDK CI Jenkins <sys_sgci@intel.com>
Community-CI: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: Shuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-by: Xiaodong Liu <xiaodong.liu@intel.com>
Reviewed-by: Tomasz Zawadzki <tomasz.zawadzki@intel.com>
This commit is contained in:
Mike Carlin 2020-01-06 15:23:33 -08:00 committed by Tomasz Zawadzki
parent 1c06235ab3
commit 06fc4cadbe
3 changed files with 90 additions and 10 deletions

View File

@ -64,7 +64,11 @@ static inline size_t spdk_base64_get_encoded_strlen(size_t raw_len)
/**
* Calculate length of raw buffer based on strlen of encoded Base64.
*
* \param encoded_strlen Length of enocded Base64 string, excluding terminating null byte ('\0').
* This length will be the max possible decoded len. The exact decoded length could be
* shorter depending on if there was padding in the Base64 string.
*
* \param encoded_strlen Length of encoded Base64 string, excluding terminating null
* byte ('\0').
* \return Length of raw buffer.
*/
static inline size_t spdk_base64_get_decoded_len(size_t encoded_strlen)
@ -106,13 +110,14 @@ int spdk_base64_urlsafe_encode(char *dst, const void *src, size_t src_len);
*
* \param dst Buffer address of decoded raw data. Its length should be enough
* to contain decoded raw data, so it needs to be at least as long as
* spdk_base64_get_decoded_len(encoded_strlen).
* spdk_base64_get_decoded_len(encoded_strlen). If NULL, only dst_len will be populated
* indicating the exact decoded length.
* \param dst_len Output parameter for the length of actual decoded raw data.
* If NULL, the actual decoded length won't be returned.
* \param src Data buffer for base64 string to be decoded.
*
* \return 0 on success.
* \return -EINVAL if dst or src is NULL, or content of src is illegal.
* \return -EINVAL if src is NULL, or content of src is illegal.
*/
int spdk_base64_decode(void *dst, size_t *dst_len, const char *src);
@ -121,13 +126,14 @@ int spdk_base64_decode(void *dst, size_t *dst_len, const char *src);
*
* \param dst Buffer address of decoded raw data. Its length should be enough
* to contain decoded raw data, so it needs to be at least as long as
* spdk_base64_get_decoded_len(encoded_strlen).
* spdk_base64_get_decoded_len(encoded_strlen). If NULL, only dst_len will be populated
* indicating the exact decoded length.
* \param dst_len Output parameter for the length of actual decoded raw data.
* If NULL, the actual decoded length won't be returned.
* \param src Data buffer for base64 string to be decoded.
*
* \return 0 on success.
* \return -EINVAL if dst or src is NULL, or content of src is illegal.
* \return -EINVAL if src is NULL, or content of src is illegal.
*/
int spdk_base64_urlsafe_decode(void *dst, size_t *dst_len, const char *src);

View File

@ -163,7 +163,7 @@ _spdk_base64_decode(void *dst, size_t *_dst_len, const uint8_t *dec_table, const
uint32_t tmp[4];
int i;
if (!dst || !src) {
if (!src) {
return -EINVAL;
}
@ -190,6 +190,12 @@ _spdk_base64_decode(void *dst, size_t *_dst_len, const uint8_t *dec_table, const
if (_dst_len) {
*_dst_len = spdk_base64_get_decoded_len(src_strlen);
}
/* If dst is NULL, the client is only concerned w/ _dst_len, return */
if (!dst) {
return 0;
}
src_in = (const uint8_t *) src;
#ifdef __aarch64__

View File

@ -148,31 +148,67 @@ test_base64_decode(void)
size_t raw_len;
int ret;
/* len */
ret = spdk_base64_decode(NULL, &raw_len, text_A);
CU_ASSERT_EQUAL(ret, 0);
CU_ASSERT_EQUAL(raw_len, sizeof(raw_A));
/* decode */
ret = spdk_base64_decode(raw, &raw_len, text_A);
CU_ASSERT_EQUAL(ret, 0);
CU_ASSERT_EQUAL(raw_len, sizeof(raw_A));
CU_ASSERT(memcmp(raw, raw_A, sizeof(raw_A)) == 0);
/* len */
ret = spdk_base64_decode(NULL, &raw_len, text_B);
CU_ASSERT_EQUAL(ret, 0);
CU_ASSERT_EQUAL(raw_len, sizeof(raw_B));
/* decode */
ret = spdk_base64_decode(raw, &raw_len, text_B);
CU_ASSERT_EQUAL(ret, 0);
CU_ASSERT_EQUAL(raw_len, sizeof(raw_B));
CU_ASSERT(memcmp(raw, raw_B, sizeof(raw_B)) == 0);
/* len */
ret = spdk_base64_decode(NULL, &raw_len, text_C);
CU_ASSERT_EQUAL(ret, 0);
CU_ASSERT_EQUAL(raw_len, sizeof(raw_C));
/* decode */
ret = spdk_base64_decode(raw, &raw_len, text_C);
CU_ASSERT_EQUAL(ret, 0);
CU_ASSERT_EQUAL(raw_len, sizeof(raw_C));
CU_ASSERT(memcmp(raw, raw_C, sizeof(raw_C)) == 0);
/* len */
ret = spdk_base64_decode(NULL, &raw_len, text_D);
CU_ASSERT_EQUAL(ret, 0);
CU_ASSERT_EQUAL(raw_len, sizeof(raw_D));
/* decode */
ret = spdk_base64_decode(raw, &raw_len, text_D);
CU_ASSERT_EQUAL(ret, 0);
CU_ASSERT_EQUAL(raw_len, sizeof(raw_D));
CU_ASSERT(memcmp(raw, raw_D, sizeof(raw_D)) == 0);
/* len */
ret = spdk_base64_decode(NULL, &raw_len, text_I);
CU_ASSERT_EQUAL(ret, 0);
CU_ASSERT_EQUAL(raw_len, sizeof(raw_I));
/* decode */
ret = spdk_base64_decode(raw, &raw_len, text_I);
CU_ASSERT_EQUAL(ret, 0);
CU_ASSERT_EQUAL(raw_len, sizeof(raw_I));
CU_ASSERT(memcmp(raw, raw_I, sizeof(raw_I)) == 0);
/* len */
ret = spdk_base64_decode(NULL, &raw_len, text_J);
CU_ASSERT_EQUAL(ret, 0);
CU_ASSERT_EQUAL(raw_len, sizeof(raw_J));
/* decode */
ret = spdk_base64_decode(raw, &raw_len, text_J);
CU_ASSERT_EQUAL(ret, 0);
CU_ASSERT_EQUAL(raw_len, sizeof(raw_J));
@ -186,8 +222,6 @@ test_base64_decode(void)
CU_ASSERT_EQUAL(ret, -EINVAL);
ret = spdk_base64_decode(raw, &raw_len, text_H);
CU_ASSERT_EQUAL(ret, -EINVAL);
ret = spdk_base64_decode(NULL, &raw_len, text_H);
CU_ASSERT_EQUAL(ret, -EINVAL);
ret = spdk_base64_decode(raw, &raw_len, NULL);
CU_ASSERT_EQUAL(ret, -EINVAL);
}
@ -240,31 +274,67 @@ test_base64_urlsafe_decode(void)
size_t raw_len = 0;
int ret;
/* len */
ret = spdk_base64_urlsafe_decode(NULL, &raw_len, text_A);
CU_ASSERT_EQUAL(ret, 0);
CU_ASSERT_EQUAL(raw_len, sizeof(raw_A));
/* decode */
ret = spdk_base64_urlsafe_decode(raw, &raw_len, text_A);
CU_ASSERT_EQUAL(ret, 0);
CU_ASSERT_EQUAL(raw_len, sizeof(raw_A));
CU_ASSERT(memcmp(raw, raw_A, sizeof(raw_A)) == 0);
/* len */
ret = spdk_base64_urlsafe_decode(NULL, &raw_len, text_urlsafe_B);
CU_ASSERT_EQUAL(ret, 0);
CU_ASSERT_EQUAL(raw_len, sizeof(raw_B));
/* decode */
ret = spdk_base64_urlsafe_decode(raw, &raw_len, text_urlsafe_B);
CU_ASSERT_EQUAL(ret, 0);
CU_ASSERT_EQUAL(raw_len, sizeof(raw_B));
CU_ASSERT(memcmp(raw, raw_B, sizeof(raw_B)) == 0);
/* len */
ret = spdk_base64_urlsafe_decode(NULL, &raw_len, text_urlsafe_C);
CU_ASSERT_EQUAL(ret, 0);
CU_ASSERT_EQUAL(raw_len, sizeof(raw_C));
/* decode */
ret = spdk_base64_urlsafe_decode(raw, &raw_len, text_urlsafe_C);
CU_ASSERT_EQUAL(ret, 0);
CU_ASSERT_EQUAL(raw_len, sizeof(raw_C));
CU_ASSERT(memcmp(raw, raw_C, sizeof(raw_C)) == 0);
/* len */
ret = spdk_base64_urlsafe_decode(NULL, &raw_len, text_urlsafe_D);
CU_ASSERT_EQUAL(ret, 0);
CU_ASSERT_EQUAL(raw_len, sizeof(raw_D));
/* decode */
ret = spdk_base64_urlsafe_decode(raw, &raw_len, text_urlsafe_D);
CU_ASSERT_EQUAL(ret, 0);
CU_ASSERT_EQUAL(raw_len, sizeof(raw_D));
CU_ASSERT(memcmp(raw, raw_D, sizeof(raw_D)) == 0);
/* len */
ret = spdk_base64_urlsafe_decode(NULL, &raw_len, text_urlsafe_I);
CU_ASSERT_EQUAL(ret, 0);
CU_ASSERT_EQUAL(raw_len, sizeof(raw_I));
/* decode */
ret = spdk_base64_urlsafe_decode(raw, &raw_len, text_urlsafe_I);
CU_ASSERT_EQUAL(ret, 0);
CU_ASSERT_EQUAL(raw_len, sizeof(raw_I));
CU_ASSERT(memcmp(raw, raw_I, sizeof(raw_I)) == 0);
/* len */
ret = spdk_base64_urlsafe_decode(NULL, &raw_len, text_urlsafe_J);
CU_ASSERT_EQUAL(ret, 0);
CU_ASSERT_EQUAL(raw_len, sizeof(raw_J));
/* decode */
ret = spdk_base64_urlsafe_decode(raw, &raw_len, text_urlsafe_J);
CU_ASSERT_EQUAL(ret, 0);
CU_ASSERT_EQUAL(raw_len, sizeof(raw_J));
@ -278,8 +348,6 @@ test_base64_urlsafe_decode(void)
CU_ASSERT_EQUAL(ret, -EINVAL);
ret = spdk_base64_urlsafe_decode(raw, &raw_len, text_H);
CU_ASSERT_EQUAL(ret, -EINVAL);
ret = spdk_base64_urlsafe_decode(NULL, &raw_len, text_H);
CU_ASSERT_EQUAL(ret, -EINVAL);
ret = spdk_base64_urlsafe_decode(raw, &raw_len, NULL);
CU_ASSERT_EQUAL(ret, -EINVAL);
}