diff --git a/common/convert.c b/common/convert.c index 40fb4eecf..54182e15b 100644 --- a/common/convert.c +++ b/common/convert.c @@ -191,7 +191,7 @@ bin2hexcolon (const void *buffer, size_t length, char *stringbuf) HEXSTRING. On success the function returns a pointer to the next character - after HEXSTRING (which is either end-of-string or a the next white + after HEXSTRING (which is either end-of-string or the next white space). If BUFLEN is not NULL the number of valid vytes in BUFFER is stored there (an extra Nul byte is not counted); this will even be done if BUFFER has been passed as NULL. */ @@ -264,3 +264,34 @@ hex2str_alloc (const char *hexstring, size_t *r_count) BUG (); return result; } + + + +/* Take the hex-encoded string HEXSTR and put it into the provided + * BUFFER in binary format. The length of the buffer is BUFEFR_SIZE + * and the expected size of the hex-string (sans leading and trailing + * spaces) is 2*BUFFER_SIZE. Returns the actual scanned length of + * HEXSTR including any leading and trailing spaces on success or 0 on + * error. The HEXSTR must be terminated by a Space or a Nul and may + * have leading spaces. */ +unsigned int +hex2fixedbuf (const char *hexstr, void *buffer_arg, size_t buffer_size) +{ + unsigned char *buffer = buffer_arg; + const char *s; + unsigned int leading_spaces, n; + + for (leading_spaces = 0; *hexstr && *hexstr == ' '; hexstr++) + leading_spaces++; + + for (s=hexstr, n=0; hexdigitp (s); s++, n++) + ; + if ((*s && *s != ' ') || !(n == 2*buffer_size)) + return 0; /* Invalid or wrong length. */ + for (s=hexstr, n=0; *s && n < buffer_size; s += 2, n++) + buffer[n] = xtoi_2 (s); + while (*s && *s == ' ') + s++; + + return leading_spaces + (s - hexstr); +} diff --git a/common/t-convert.c b/common/t-convert.c index e25de9012..c7ba8f6f7 100644 --- a/common/t-convert.c +++ b/common/t-convert.c @@ -445,6 +445,43 @@ test_hex2str (void) +static void +test_hex2fixedbuf (void) +{ + static struct { + const char *hex; + unsigned bufsize; + unsigned int resultlen; + const char *result; + } tests[] = { + /* Simple tests. */ + { "112233445566778899aabbccddeeff1122", 17, 34, + "\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa\xbb\xcc\xdd\xee\xff\x11\x22"}, + { " 112233445566778899aabbccddeeff1122", 17, 35, + "\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa\xbb\xcc\xdd\xee\xff\x11\x22"}, + { "112233445566778899aabbccddeeff1122 ", 17, 35, + "\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa\xbb\xcc\xdd\xee\xff\x11\x22"}, + { " 112233445566778899aabbccddeeff1122 ", 17, 37, + "\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa\xbb\xcc\xdd\xee\xff\x11\x22"}, + { " 112233445566778899aabbccddeeff11 ", 16, 35, + "\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa\xbb\xcc\xdd\xee\xff\x11"}, + { " 112233445566778899aabbccddeeff11", 16, 34, + "\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa\xbb\xcc\xdd\xee\xff\x11"} + }; + char buffer[100]; /* Large enough for all tests. */ + int idx; + unsigned int n; + + for (idx=0; idx < DIM (tests); idx++) + { + n = hex2fixedbuf (tests[idx].hex, buffer, tests[idx].bufsize); + if (n != tests[idx].resultlen) + fail (idx); + else if (memcmp (buffer, tests[idx].result, tests[idx].bufsize)) + fail (idx); + } + +} int @@ -458,6 +495,7 @@ main (int argc, char **argv) test_bin2hex (); test_bin2hexcolon (); test_hex2str (); + test_hex2fixedbuf (); return 0; } diff --git a/common/util.h b/common/util.h index 8f8a06a41..6c878083a 100644 --- a/common/util.h +++ b/common/util.h @@ -206,6 +206,7 @@ char *bin2hexcolon (const void *buffer, size_t length, char *stringbuf); const char *hex2str (const char *hexstring, char *buffer, size_t bufsize, size_t *buflen); char *hex2str_alloc (const char *hexstring, size_t *r_count); +unsigned int hex2fixedbuf (const char *hexstr, void *buffer, size_t bufsize); /*-- percent.c --*/ char *percent_plus_escape (const char *string);