1
0
mirror of https://github.com/pgbackrest/pgbackrest.git synced 2025-11-06 08:49:29 +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" #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) \ #define ASSERT_ENCODE_TYPE_VALID(type) \
THROW_FMT(AssertError, "invalid encode type %u", encodeType); ASSERT(type <= encodeBase64);
/*********************************************************************************************************************************** /***********************************************************************************************************************************
Base64 encoding/decoding Base64 encoding/decoding
@@ -228,85 +228,101 @@ decodeToBinSizeBase64(const char *source)
Generic encoding/decoding Generic encoding/decoding
***********************************************************************************************************************************/ ***********************************************************************************************************************************/
void 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_BEGIN();
FUNCTION_TEST_PARAM(ENUM, encodeType); FUNCTION_TEST_PARAM(ENUM, type);
FUNCTION_TEST_PARAM_P(UCHARDATA, source); FUNCTION_TEST_PARAM_P(UCHARDATA, source);
FUNCTION_TEST_PARAM(SIZE, sourceSize); FUNCTION_TEST_PARAM(SIZE, sourceSize);
FUNCTION_TEST_PARAM_P(CHARDATA, destination); FUNCTION_TEST_PARAM_P(CHARDATA, destination);
FUNCTION_TEST_END(); FUNCTION_TEST_END();
if (encodeType == encodeBase64) ASSERT_ENCODE_TYPE_VALID(type);
encodeToStrBase64(source, sourceSize, destination);
else switch (type)
ENCODE_TYPE_INVALID_ERROR(encodeType); {
case encodeBase64:
encodeToStrBase64(source, sourceSize, destination);
break;
}
FUNCTION_TEST_RETURN_VOID(); FUNCTION_TEST_RETURN_VOID();
} }
/**********************************************************************************************************************************/ /**********************************************************************************************************************************/
size_t size_t
encodeToStrSize(EncodeType encodeType, size_t sourceSize) encodeToStrSize(EncodeType type, size_t sourceSize)
{ {
FUNCTION_TEST_BEGIN(); FUNCTION_TEST_BEGIN();
FUNCTION_TEST_PARAM(ENUM, encodeType); FUNCTION_TEST_PARAM(ENUM, type);
FUNCTION_TEST_PARAM(SIZE, sourceSize); FUNCTION_TEST_PARAM(SIZE, sourceSize);
FUNCTION_TEST_END(); FUNCTION_TEST_END();
size_t destinationSize = 0; ASSERT_ENCODE_TYPE_VALID(type);
if (encodeType == encodeBase64) size_t destinationSize = SIZE_MAX;
destinationSize = encodeToStrSizeBase64(sourceSize);
else switch (type)
ENCODE_TYPE_INVALID_ERROR(encodeType); {
case encodeBase64:
destinationSize = encodeToStrSizeBase64(sourceSize);
break;
}
FUNCTION_TEST_RETURN(destinationSize); FUNCTION_TEST_RETURN(destinationSize);
} }
/**********************************************************************************************************************************/ /**********************************************************************************************************************************/
void void
decodeToBin(EncodeType encodeType, const char *source, unsigned char *destination) decodeToBin(EncodeType type, const char *source, unsigned char *destination)
{ {
FUNCTION_TEST_BEGIN(); FUNCTION_TEST_BEGIN();
FUNCTION_TEST_PARAM(ENUM, encodeType); FUNCTION_TEST_PARAM(ENUM, type);
FUNCTION_TEST_PARAM(STRINGZ, source); FUNCTION_TEST_PARAM(STRINGZ, source);
FUNCTION_TEST_PARAM_P(UCHARDATA, destination); FUNCTION_TEST_PARAM_P(UCHARDATA, destination);
FUNCTION_TEST_END(); FUNCTION_TEST_END();
if (encodeType == encodeBase64) ASSERT_ENCODE_TYPE_VALID(type);
decodeToBinBase64(source, destination);
else switch (type)
ENCODE_TYPE_INVALID_ERROR(encodeType); {
case encodeBase64:
decodeToBinBase64(source, destination);
break;
}
FUNCTION_TEST_RETURN_VOID(); FUNCTION_TEST_RETURN_VOID();
} }
/**********************************************************************************************************************************/ /**********************************************************************************************************************************/
size_t size_t
decodeToBinSize(EncodeType encodeType, const char *source) decodeToBinSize(EncodeType type, const char *source)
{ {
FUNCTION_TEST_BEGIN(); FUNCTION_TEST_BEGIN();
FUNCTION_TEST_PARAM(ENUM, encodeType); FUNCTION_TEST_PARAM(ENUM, type);
FUNCTION_TEST_PARAM(STRINGZ, source); FUNCTION_TEST_PARAM(STRINGZ, source);
FUNCTION_TEST_END(); FUNCTION_TEST_END();
size_t destinationSize = 0; ASSERT_ENCODE_TYPE_VALID(type);
if (encodeType == encodeBase64) size_t destinationSize = SIZE_MAX;
destinationSize = decodeToBinSizeBase64(source);
else switch (type)
ENCODE_TYPE_INVALID_ERROR(encodeType); {
case encodeBase64:
destinationSize = decodeToBinSizeBase64(source);
break;
}
FUNCTION_TEST_RETURN(destinationSize); FUNCTION_TEST_RETURN(destinationSize);
} }
/**********************************************************************************************************************************/ /**********************************************************************************************************************************/
bool bool
decodeToBinValid(EncodeType encodeType, const char *source) decodeToBinValid(EncodeType type, const char *source)
{ {
FUNCTION_TEST_BEGIN(); FUNCTION_TEST_BEGIN();
FUNCTION_TEST_PARAM(ENUM, encodeType); FUNCTION_TEST_PARAM(ENUM, type);
FUNCTION_TEST_PARAM(STRINGZ, source); FUNCTION_TEST_PARAM(STRINGZ, source);
FUNCTION_TEST_END(); FUNCTION_TEST_END();
@@ -314,7 +330,7 @@ decodeToBinValid(EncodeType encodeType, const char *source)
TRY_BEGIN() TRY_BEGIN()
{ {
decodeToBinValidate(encodeType, source); decodeToBinValidate(type, source);
} }
CATCH(FormatError) CATCH(FormatError)
{ {
@@ -327,17 +343,21 @@ decodeToBinValid(EncodeType encodeType, const char *source)
/**********************************************************************************************************************************/ /**********************************************************************************************************************************/
void void
decodeToBinValidate(EncodeType encodeType, const char *source) decodeToBinValidate(EncodeType type, const char *source)
{ {
FUNCTION_TEST_BEGIN(); FUNCTION_TEST_BEGIN();
FUNCTION_TEST_PARAM(ENUM, encodeType); FUNCTION_TEST_PARAM(ENUM, type);
FUNCTION_TEST_PARAM(STRINGZ, source); FUNCTION_TEST_PARAM(STRINGZ, source);
FUNCTION_TEST_END(); FUNCTION_TEST_END();
if (encodeType == encodeBase64) ASSERT_ENCODE_TYPE_VALID(type);
decodeToBinValidateBase64(source);
else switch (type)
ENCODE_TYPE_INVALID_ERROR(encodeType); {
case encodeBase64:
decodeToBinValidateBase64(source);
break;
}
FUNCTION_TEST_RETURN_VOID(); FUNCTION_TEST_RETURN_VOID();
} }

View File

@@ -20,21 +20,21 @@ typedef enum
Functions Functions
***********************************************************************************************************************************/ ***********************************************************************************************************************************/
// Encode binary data to a printable string // 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 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 // 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 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 // 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 // Validate the encoded string
void decodeToBinValidate(EncodeType encodeType, const char *source); void decodeToBinValidate(EncodeType type, const char *source);
#endif #endif

View File

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