Commit 06fc4cad authored by Mike Carlin's avatar Mike Carlin Committed by Tomasz Zawadzki
Browse files

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: default avatarMike Carlin <mikefcarlin@protonmail.com>
Reviewed-on: https://review.gerrithub.io/c/spdk/spdk/+/479479


Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
Community-CI: SPDK CI Jenkins <sys_sgci@intel.com>
Reviewed-by: default avatarShuhei Matsumoto <shuhei.matsumoto.xt@hitachi.com>
Reviewed-by: default avatarXiaodong Liu <xiaodong.liu@intel.com>
Reviewed-by: default avatarTomasz Zawadzki <tomasz.zawadzki@intel.com>
parent 1c06235a
Loading
Loading
Loading
Loading
+11 −5
Original line number Diff line number Diff line
@@ -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);

+7 −1
Original line number Diff line number Diff line
@@ -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__
+72 −4
Original line number Diff line number Diff line
@@ -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);
}