1
0
mirror of https://github.com/pgbackrest/pgbackrest.git synced 2025-01-18 04:58:51 +02:00

Use switch rather than if-else for encoding types.

This is more efficient and the error case can be an assert rather than a runtime error.

For extra safety initialize destinationSize to SIZE_MAX to increase the chances of an error if the switch fails.
This commit is contained in:
David Steele 2021-02-19 17:57:13 -05:00
parent abcbe0f9c1
commit edab2a0b89
3 changed files with 66 additions and 54 deletions

View File

@ -11,10 +11,10 @@ Binary to String Encode/Decode
#include "common/error.h"
/***********************************************************************************************************************************
Macro to handle invalid encode type errors
Assert that encoding type is valid. This needs to be kept up to date with the last item in the enum.
***********************************************************************************************************************************/
#define ENCODE_TYPE_INVALID_ERROR(encodeType) \
THROW_FMT(AssertError, "invalid encode type %u", encodeType);
#define ASSERT_ENCODE_TYPE_VALID(type) \
ASSERT(type <= encodeBase64);
/***********************************************************************************************************************************
Base64 encoding/decoding
@ -228,85 +228,101 @@ decodeToBinSizeBase64(const char *source)
Generic encoding/decoding
***********************************************************************************************************************************/
void
encodeToStr(EncodeType encodeType, const unsigned char *source, size_t sourceSize, char *destination)
encodeToStr(EncodeType type, const unsigned char *source, size_t sourceSize, char *destination)
{
FUNCTION_TEST_BEGIN();
FUNCTION_TEST_PARAM(ENUM, encodeType);
FUNCTION_TEST_PARAM(ENUM, type);
FUNCTION_TEST_PARAM_P(UCHARDATA, source);
FUNCTION_TEST_PARAM(SIZE, sourceSize);
FUNCTION_TEST_PARAM_P(CHARDATA, destination);
FUNCTION_TEST_END();
if (encodeType == encodeBase64)
encodeToStrBase64(source, sourceSize, destination);
else
ENCODE_TYPE_INVALID_ERROR(encodeType);
ASSERT_ENCODE_TYPE_VALID(type);
switch (type)
{
case encodeBase64:
encodeToStrBase64(source, sourceSize, destination);
break;
}
FUNCTION_TEST_RETURN_VOID();
}
/**********************************************************************************************************************************/
size_t
encodeToStrSize(EncodeType encodeType, size_t sourceSize)
encodeToStrSize(EncodeType type, size_t sourceSize)
{
FUNCTION_TEST_BEGIN();
FUNCTION_TEST_PARAM(ENUM, encodeType);
FUNCTION_TEST_PARAM(ENUM, type);
FUNCTION_TEST_PARAM(SIZE, sourceSize);
FUNCTION_TEST_END();
size_t destinationSize = 0;
ASSERT_ENCODE_TYPE_VALID(type);
if (encodeType == encodeBase64)
destinationSize = encodeToStrSizeBase64(sourceSize);
else
ENCODE_TYPE_INVALID_ERROR(encodeType);
size_t destinationSize = SIZE_MAX;
switch (type)
{
case encodeBase64:
destinationSize = encodeToStrSizeBase64(sourceSize);
break;
}
FUNCTION_TEST_RETURN(destinationSize);
}
/**********************************************************************************************************************************/
void
decodeToBin(EncodeType encodeType, const char *source, unsigned char *destination)
decodeToBin(EncodeType type, const char *source, unsigned char *destination)
{
FUNCTION_TEST_BEGIN();
FUNCTION_TEST_PARAM(ENUM, encodeType);
FUNCTION_TEST_PARAM(ENUM, type);
FUNCTION_TEST_PARAM(STRINGZ, source);
FUNCTION_TEST_PARAM_P(UCHARDATA, destination);
FUNCTION_TEST_END();
if (encodeType == encodeBase64)
decodeToBinBase64(source, destination);
else
ENCODE_TYPE_INVALID_ERROR(encodeType);
ASSERT_ENCODE_TYPE_VALID(type);
switch (type)
{
case encodeBase64:
decodeToBinBase64(source, destination);
break;
}
FUNCTION_TEST_RETURN_VOID();
}
/**********************************************************************************************************************************/
size_t
decodeToBinSize(EncodeType encodeType, const char *source)
decodeToBinSize(EncodeType type, const char *source)
{
FUNCTION_TEST_BEGIN();
FUNCTION_TEST_PARAM(ENUM, encodeType);
FUNCTION_TEST_PARAM(ENUM, type);
FUNCTION_TEST_PARAM(STRINGZ, source);
FUNCTION_TEST_END();
size_t destinationSize = 0;
ASSERT_ENCODE_TYPE_VALID(type);
if (encodeType == encodeBase64)
destinationSize = decodeToBinSizeBase64(source);
else
ENCODE_TYPE_INVALID_ERROR(encodeType);
size_t destinationSize = SIZE_MAX;
switch (type)
{
case encodeBase64:
destinationSize = decodeToBinSizeBase64(source);
break;
}
FUNCTION_TEST_RETURN(destinationSize);
}
/**********************************************************************************************************************************/
bool
decodeToBinValid(EncodeType encodeType, const char *source)
decodeToBinValid(EncodeType type, const char *source)
{
FUNCTION_TEST_BEGIN();
FUNCTION_TEST_PARAM(ENUM, encodeType);
FUNCTION_TEST_PARAM(ENUM, type);
FUNCTION_TEST_PARAM(STRINGZ, source);
FUNCTION_TEST_END();
@ -314,7 +330,7 @@ decodeToBinValid(EncodeType encodeType, const char *source)
TRY_BEGIN()
{
decodeToBinValidate(encodeType, source);
decodeToBinValidate(type, source);
}
CATCH(FormatError)
{
@ -327,17 +343,21 @@ decodeToBinValid(EncodeType encodeType, const char *source)
/**********************************************************************************************************************************/
void
decodeToBinValidate(EncodeType encodeType, const char *source)
decodeToBinValidate(EncodeType type, const char *source)
{
FUNCTION_TEST_BEGIN();
FUNCTION_TEST_PARAM(ENUM, encodeType);
FUNCTION_TEST_PARAM(ENUM, type);
FUNCTION_TEST_PARAM(STRINGZ, source);
FUNCTION_TEST_END();
if (encodeType == encodeBase64)
decodeToBinValidateBase64(source);
else
ENCODE_TYPE_INVALID_ERROR(encodeType);
ASSERT_ENCODE_TYPE_VALID(type);
switch (type)
{
case encodeBase64:
decodeToBinValidateBase64(source);
break;
}
FUNCTION_TEST_RETURN_VOID();
}

View File

@ -20,21 +20,21 @@ typedef enum
Functions
***********************************************************************************************************************************/
// Encode binary data to a printable string
void encodeToStr(EncodeType encodeType, const unsigned char *source, size_t sourceSize, char *destination);
void encodeToStr(EncodeType type, const unsigned char *source, size_t sourceSize, char *destination);
// Size of the string returned by encodeToStr()
size_t encodeToStrSize(EncodeType encodeType, size_t sourceSize);
size_t encodeToStrSize(EncodeType type, size_t sourceSize);
// Decode a string to binary data
void decodeToBin(EncodeType encodeType, const char *source, unsigned char *destination);
void decodeToBin(EncodeType type, const char *source, unsigned char *destination);
// Size of the binary data returned by decodeToBin()
size_t decodeToBinSize(EncodeType encodeType, const char *source);
size_t decodeToBinSize(EncodeType type, const char *source);
// Check that the encoded string is valid
bool decodeToBinValid(EncodeType encodeType, const char *source);
bool decodeToBinValid(EncodeType type, const char *source);
// Validate the encoded string
void decodeToBinValidate(EncodeType encodeType, const char *source);
void decodeToBinValidate(EncodeType type, const char *source);
#endif

View File

@ -40,9 +40,6 @@ testRun(void)
TEST_RESULT_Z(destinationEncode, "c3RyaW5nX3RvX2VuY29kZQ0KAA==", "encode full string with \\r\\n and null");
TEST_RESULT_UINT(encodeToStrSize(encodeBase64, strlen((char *)encode) + 1), strlen(destinationEncode), "check size");
TEST_ERROR(encodeToStr(999, encode, strlen((char *)encode), destinationEncode), AssertError, "invalid encode type 999");
TEST_ERROR(encodeToStrSize(999, strlen((char *)encode)), AssertError, "invalid encode type 999");
// -------------------------------------------------------------------------------------------------------------------------
unsigned char destinationDecode[256];
@ -88,9 +85,8 @@ testRun(void)
TEST_RESULT_INT(destinationDecode[1], 0xFF, "check for overrun");
TEST_RESULT_UINT(decodeToBinSize(encodeBase64, decode), 1, "check size");
TEST_ERROR(decodeToBin(9999, decode, destinationDecode), AssertError, "invalid encode type 9999");
TEST_ERROR(decodeToBinSize(9999, decode), AssertError, "invalid encode type 9999");
TEST_ERROR(decodeToBin(encodeBase64, "cc$=", destinationDecode), FormatError, "base64 invalid character found at position 2");
TEST_ERROR(
decodeToBin(encodeBase64, "cc$=", destinationDecode), FormatError, "base64 invalid character found at position 2");
// -------------------------------------------------------------------------------------------------------------------------
TEST_ERROR(decodeToBinValidate(encodeBase64, "c3"), FormatError, "base64 size 2 is not evenly divisible by 4");
@ -99,13 +95,9 @@ testRun(void)
TEST_ERROR(
decodeToBinValidate(encodeBase64, "cc=c"), FormatError, "base64 last character must be '=' if second to last is");
TEST_ERROR(decodeToBinValidate(9999, "cc=c"), AssertError, "invalid encode type 9999");
// -------------------------------------------------------------------------------------------------------------------------
TEST_RESULT_BOOL(decodeToBinValid(encodeBase64, "CCCCCCCCCCC"), false, "base64 string not valid");
TEST_RESULT_BOOL(decodeToBinValid(encodeBase64, "CCCCCCCCCCCC"), true, "base64 string valid");
TEST_ERROR(decodeToBinValid(9999, "CCCCCCCCCCCC"), AssertError, "invalid encode type 9999");
}
FUNCTION_HARNESS_RESULT_VOID();