From 9aa8090d069eb0b36769f33544faf0e7e429e844 Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Fri, 24 Apr 2015 14:34:32 +0100 Subject: [base16] Add buffer size parameter to base16_encode() and base16_decode() The current API for Base16 (and Base64) encoding requires the caller to always provide sufficient buffer space. This prevents the use of the generic encoding/decoding functionality in some situations, such as in formatting the hex setting types. Implement a generic hex_encode() (based on the existing format_hex_setting()), implement base16_encode() and base16_decode() in terms of the more generic hex_encode() and hex_decode(), and update all callers to provide the additional buffer length parameter. Signed-off-by: Michael Brown --- src/core/base16.c | 81 ++++++++++++++++------------------------------------- src/core/settings.c | 38 ++++--------------------- 2 files changed, 30 insertions(+), 89 deletions(-) (limited to 'src/core') diff --git a/src/core/base16.c b/src/core/base16.c index f5177c07c..f9e0f3364 100644 --- a/src/core/base16.c +++ b/src/core/base16.c @@ -28,6 +28,7 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); #include #include #include +#include #include /** @file @@ -37,48 +38,42 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL ); */ /** - * Base16-encode data + * Encode hexadecimal string (with optional byte separator character) * + * @v separator Byte separator character, or 0 for no separator * @v raw Raw data - * @v len Length of raw data - * @v encoded Buffer for encoded string - * - * The buffer must be the correct length for the encoded string. Use - * something like - * - * char buf[ base16_encoded_len ( len ) + 1 ]; - * - * (the +1 is for the terminating NUL) to provide a buffer of the - * correct size. + * @v raw_len Length of raw data + * @v data Buffer + * @v len Length of buffer + * @ret len Encoded length */ -void base16_encode ( const uint8_t *raw, size_t len, char *encoded ) { - const uint8_t *raw_bytes = raw; - char *encoded_bytes = encoded; - size_t remaining = len; - - /* Encode each byte */ - for ( ; remaining-- ; encoded_bytes += 2 ) { - sprintf ( encoded_bytes, "%02x", *(raw_bytes++) ); +size_t hex_encode ( char separator, const void *raw, size_t raw_len, + char *data, size_t len ) { + const uint8_t *bytes = raw; + const char delimiter[2] = { separator, '\0' }; + size_t used = 0; + unsigned int i; + + if ( len ) + data[0] = 0; /* Ensure that a terminating NUL exists */ + for ( i = 0 ; i < raw_len ; i++ ) { + used += ssnprintf ( ( data + used ), ( len - used ), + "%s%02x", ( used ? delimiter : "" ), + bytes[i] ); } - - /* Ensure terminating NUL exists even if length was zero */ - *encoded_bytes = '\0'; - - DBG ( "Base16-encoded to \"%s\":\n", encoded ); - DBG_HDA ( 0, raw, len ); - assert ( strlen ( encoded ) == base16_encoded_len ( len ) ); + return used; } /** - * Decode hexadecimal string + * Decode hexadecimal string (with optional byte separator character) * - * @v encoded Encoded string * @v separator Byte separator character, or 0 for no separator + * @v encoded Encoded string * @v data Buffer * @v len Length of buffer * @ret len Length of data, or negative error */ -int hex_decode ( const char *encoded, char separator, void *data, size_t len ) { +int hex_decode ( char separator, const char *encoded, void *data, size_t len ) { uint8_t *out = data; unsigned int count = 0; unsigned int sixteens; @@ -110,31 +105,3 @@ int hex_decode ( const char *encoded, char separator, void *data, size_t len ) { } return count; } - -/** - * Base16-decode data - * - * @v encoded Encoded string - * @v raw Raw data - * @ret len Length of raw data, or negative error - * - * The buffer must be large enough to contain the decoded data. Use - * something like - * - * char buf[ base16_decoded_max_len ( encoded ) ]; - * - * to provide a buffer of the correct size. - */ -int base16_decode ( const char *encoded, uint8_t *raw ) { - int len; - - len = hex_decode ( encoded, 0, raw, -1UL ); - if ( len < 0 ) - return len; - - DBG ( "Base16-decoded \"%s\" to:\n", encoded ); - DBG_HDA ( 0, raw, len ); - assert ( len <= ( int ) base16_decoded_max_len ( encoded ) ); - - return len; -} diff --git a/src/core/settings.c b/src/core/settings.c index bd242f6b6..be48ea7a7 100644 --- a/src/core/settings.c +++ b/src/core/settings.c @@ -2005,32 +2005,6 @@ const struct setting_type setting_type_uint16 __setting_type = const struct setting_type setting_type_uint32 __setting_type = SETTING_TYPE_UINT ( SETTING_TYPE_INT32 ); -/** - * Format hex string setting value - * - * @v delimiter Byte delimiter - * @v raw Raw setting value - * @v raw_len Length of raw setting value - * @v buf Buffer to contain formatted value - * @v len Length of buffer - * @ret len Length of formatted value, or negative error - */ -static int format_hex_setting ( const char *delimiter, const void *raw, - size_t raw_len, char *buf, size_t len ) { - const uint8_t *bytes = raw; - int used = 0; - unsigned int i; - - if ( len ) - buf[0] = 0; /* Ensure that a terminating NUL exists */ - for ( i = 0 ; i < raw_len ; i++ ) { - used += ssnprintf ( ( buf + used ), ( len - used ), - "%s%02x", ( used ? delimiter : "" ), - bytes[i] ); - } - return used; -} - /** * Parse hex string setting value (using colon delimiter) * @@ -2043,7 +2017,7 @@ static int format_hex_setting ( const char *delimiter, const void *raw, */ static int parse_hex_setting ( const struct setting_type *type __unused, const char *value, void *buf, size_t len ) { - return hex_decode ( value, ':', buf, len ); + return hex_decode ( ':', value, buf, len ); } /** @@ -2059,7 +2033,7 @@ static int parse_hex_setting ( const struct setting_type *type __unused, static int format_hex_colon_setting ( const struct setting_type *type __unused, const void *raw, size_t raw_len, char *buf, size_t len ) { - return format_hex_setting ( ":", raw, raw_len, buf, len ); + return hex_encode ( ':', raw, raw_len, buf, len ); } /** @@ -2075,7 +2049,7 @@ static int format_hex_colon_setting ( const struct setting_type *type __unused, static int parse_hex_hyphen_setting ( const struct setting_type *type __unused, const char *value, void *buf, size_t len ) { - return hex_decode ( value, '-', buf, len ); + return hex_decode ( '-', value, buf, len ); } /** @@ -2091,7 +2065,7 @@ static int parse_hex_hyphen_setting ( const struct setting_type *type __unused, static int format_hex_hyphen_setting ( const struct setting_type *type __unused, const void *raw, size_t raw_len, char *buf, size_t len ) { - return format_hex_setting ( "-", raw, raw_len, buf, len ); + return hex_encode ( '-', raw, raw_len, buf, len ); } /** @@ -2106,7 +2080,7 @@ static int format_hex_hyphen_setting ( const struct setting_type *type __unused, */ static int parse_hex_raw_setting ( const struct setting_type *type __unused, const char *value, void *buf, size_t len ) { - return hex_decode ( value, 0, buf, len ); + return hex_decode ( 0, value, buf, len ); } /** @@ -2122,7 +2096,7 @@ static int parse_hex_raw_setting ( const struct setting_type *type __unused, static int format_hex_raw_setting ( const struct setting_type *type __unused, const void *raw, size_t raw_len, char *buf, size_t len ) { - return format_hex_setting ( "", raw, raw_len, buf, len ); + return hex_encode ( 0, raw, raw_len, buf, len ); } /** A hex-string setting (colon-delimited) */ -- cgit v1.2.3-55-g7522