1
0
mirror of git://git.gnupg.org/gnupg.git synced 2024-06-02 22:38:02 +02:00

common: Minor change of hex2str to allow for embedded nul.

* common/convert.c (hex2str): Set ERRNO.  Return adjusted COUNT.
--

hex2str is only used at one place for in-place converting an hex
encoded passphrase.  This change does not affect this use.  The change
is however useful to use the function for in-place conversion of
arbitrary hex encoded strings.

Take care for in-place conversion of a hex string encoding binary data
you need to use it this way:

  if (hex2str (string, string, strlen (string) + 1, &length)
     oops ("probably out of memory but see ERRNO");
  for (i=0; i < length; i++)
     foo (string[i));

Note that strlen() + 1.

Signed-off-by: Werner Koch <wk@gnupg.org>
This commit is contained in:
Werner Koch 2015-04-23 14:31:04 +02:00
parent a7264e3a6a
commit ce11cc39ea
No known key found for this signature in database
GPG Key ID: E3FDFF218E45B72B
2 changed files with 56 additions and 45 deletions

View File

@ -175,21 +175,26 @@ bin2hexcolon (const void *buffer, size_t length, char *stringbuf)
/* Convert HEXSTRING consisting of hex characters into string and /* Convert HEXSTRING consisting of hex characters into string and
store that at BUFFER. HEXSTRING is either delimited by end of store that at BUFFER. HEXSTRING is either delimited by end of
string or a white space character. The function makes sure that string or a white space character. The function makes sure that
the resulting string in BUFFER is terminated by a Nul character. the resulting string in BUFFER is terminated by a Nul byte. Note
that the retruned string may include embedded Nul bytes; the extra
Nul byte at the end is used to make sure tha the result can always
be used as a C-string.
BUFSIZE is the availabe length of BUFFER; if the converted result BUFSIZE is the availabe length of BUFFER; if the converted result
plus a possible required Nul character does not fit into this plus a possible required extra Nul character does not fit into this
buffer, the function returns NULL and won't change the existing buffer, the function returns NULL and won't change the existing
conent of buffer. In-place conversion is possible as long as content of BUFFER. In-place conversion is possible as long as
BUFFER points to HEXSTRING. BUFFER points to HEXSTRING.
If BUFFER is NULL and bufsize is 0 the function scans HEXSTRING but If BUFFER is NULL and BUFSIZE is 0 the function scans HEXSTRING but
does not store anything. This may be used to find the end of does not store anything. This may be used to find the end of
hexstring. HEXSTRING.
On sucess the function returns a pointer to the next character On sucess 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 a the next white
space). If BUFLEN is not NULL the strlen of buffer is stored space). If BUFLEN is not NULL the number of valid vytes in BUFFER
there; this will even be done if BUFFER has been passed as NULL. */ is stored there (an extra Nul byte is not counted); this will even
be done if BUFFER has been passed as NULL. */
const char * const char *
hex2str (const char *hexstring, char *buffer, size_t bufsize, size_t *buflen) hex2str (const char *hexstring, char *buffer, size_t bufsize, size_t *buflen)
{ {
@ -203,7 +208,10 @@ hex2str (const char *hexstring, char *buffer, size_t bufsize, size_t *buflen)
for (s=hexstring, count=0; hexdigitp (s) && hexdigitp (s+1); s += 2, count++) for (s=hexstring, count=0; hexdigitp (s) && hexdigitp (s+1); s += 2, count++)
; ;
if (*s && (!isascii (*s) || !isspace (*s)) ) if (*s && (!isascii (*s) || !isspace (*s)) )
return NULL; /* Not followed by Nul or white space. */ {
gpg_err_set_errno (EINVAL);
return NULL; /* Not followed by Nul or white space. */
}
/* We need to append a nul character. However we don't want that if /* We need to append a nul character. However we don't want that if
the hexstring already ends with "00". */ the hexstring already ends with "00". */
need_nul = ((s == hexstring) || !(s[-2] == '0' && s[-1] == '0')); need_nul = ((s == hexstring) || !(s[-2] == '0' && s[-1] == '0'));
@ -213,7 +221,10 @@ hex2str (const char *hexstring, char *buffer, size_t bufsize, size_t *buflen)
if (buffer) if (buffer)
{ {
if (count > bufsize) if (count > bufsize)
return NULL; /* Too long. */ {
gpg_err_set_errno (EINVAL);
return NULL; /* Too long. */
}
for (s=hexstring, idx=0; hexdigitp (s) && hexdigitp (s+1); s += 2) for (s=hexstring, idx=0; hexdigitp (s) && hexdigitp (s+1); s += 2)
((unsigned char*)buffer)[idx++] = xtoi_2 (s); ((unsigned char*)buffer)[idx++] = xtoi_2 (s);
@ -222,7 +233,7 @@ hex2str (const char *hexstring, char *buffer, size_t bufsize, size_t *buflen)
} }
if (buflen) if (buflen)
*buflen = count - 1; *buflen = count - need_nul;
return s; return s;
} }
@ -242,7 +253,6 @@ hex2str_alloc (const char *hexstring, size_t *r_count)
{ {
if (r_count) if (r_count)
*r_count = 0; *r_count = 0;
gpg_err_set_errno (EINVAL);
return NULL; return NULL;
} }
if (r_count) if (r_count)

View File

@ -27,7 +27,7 @@
#define pass() do { ; } while(0) #define pass() do { ; } while(0)
#define fail(a) do { fprintf (stderr, "%s:%d: test %d failed\n",\ #define fail(a) do { fprintf (stderr, "%s:%d: test %d failed\n",\
__FILE__,__LINE__, (a)); \ __FILE__,__LINE__, (a)); \
exit (1); \ /*exit (1)*/; \
} while(0) } while(0)
@ -282,73 +282,74 @@ test_hex2str (void)
static struct { static struct {
const char *hex; const char *hex;
const char *str; const char *str;
int len; /* Length of STR. This may included embedded nuls. */
int off; int off;
int no_alloc_test; int no_alloc_test;
} tests[] = { } tests[] = {
/* Simple tests. */ /* Simple tests. */
{ "112233445566778899aabbccddeeff1122", { "112233445566778899aabbccddeeff1122",
"\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa\xbb\xcc\xdd\xee\xff\x11\x22", "\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa\xbb\xcc\xdd\xee\xff\x11\x22",
34 }, 17, 34 },
{ "112233445566778899aabbccddeeff1122 blah", { "112233445566778899aabbccddeeff1122 blah",
"\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa\xbb\xcc\xdd\xee\xff\x11\x22", "\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa\xbb\xcc\xdd\xee\xff\x11\x22",
34 }, 17, 34 },
{ "112233445566778899aabbccddeeff1122\tblah", { "112233445566778899aabbccddeeff1122\tblah",
"\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa\xbb\xcc\xdd\xee\xff\x11\x22", "\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa\xbb\xcc\xdd\xee\xff\x11\x22",
34 }, 17, 34 },
{ "112233445566778899aabbccddeeff1122\nblah", { "112233445566778899aabbccddeeff1122\nblah",
"\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa\xbb\xcc\xdd\xee\xff\x11\x22", "\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa\xbb\xcc\xdd\xee\xff\x11\x22",
34 }, 17, 34 },
/* Valid tests yielding an empty string. */ /* Valid tests yielding an empty string. */
{ "00", { "00",
"", "",
2 }, 1, 2 },
{ "00 x", { "00 x",
"", "",
2 }, 1, 2 },
{ "", { "",
"", "",
0 }, 0, 0 },
{ " ", { " ",
"", "",
0 }, 0, 0 },
/* Test trailing Nul feature. */ /* Test trailing Nul feature. */
{ "112233445566778899aabbccddeeff112200", { "112233445566778899aabbccddeeff1100",
"\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa\xbb\xcc\xdd\xee\xff\x11\x22", "\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa\xbb\xcc\xdd\xee\xff\x11\x00",
36 }, 17, 34 },
{ "112233445566778899aabbccddeeff112200 ", { "112233445566778899aabbccddeeff1100 ",
"\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa\xbb\xcc\xdd\xee\xff\x11\x22", "\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa\xbb\xcc\xdd\xee\xff\x11\x00",
36 }, 17, 34 },
/* Test buffer size. (buffer is of length 20) */ /* Test buffer size. (buffer is of length 20) */
{ "6162636465666768696A6b6c6D6e6f70717273", { "6162636465666768696A6b6c6D6e6f70717273",
"abcdefghijklmnopqrs", "abcdefghijklmnopqrs",
38 }, 19, 38 },
{ "6162636465666768696A6b6c6D6e6f7071727300", { "6162636465666768696A6b6c6D6e6f7071727300",
"abcdefghijklmnopqrs", "abcdefghijklmnopqrs",
40 }, 20, 40 },
{ "6162636465666768696A6b6c6D6e6f7071727374", { "6162636465666768696A6b6c6D6e6f7071727374",
NULL, NULL,
0, 1 }, 0, 0, 1 },
{ "6162636465666768696A6b6c6D6e6f707172737400", { "6162636465666768696A6b6c6D6e6f707172737400",
NULL, NULL,
0, 1 }, 0, 0, 1 },
{ "6162636465666768696A6b6c6D6e6f707172737475", { "6162636465666768696A6b6c6D6e6f707172737475",
NULL, NULL,
0, 1 }, 0, 0, 1 },
/* Invalid tests. */ /* Invalid tests. */
{ "112233445566778899aabbccddeeff1122334", NULL, 0 }, { "112233445566778899aabbccddeeff1122334", NULL, 0, 0 },
{ "112233445566778899AABBCCDDEEFF1122334", NULL, 0 }, { "112233445566778899AABBCCDDEEFF1122334", NULL, 0, 0 },
{ "112233445566778899AABBCCDDEEFG11223344", NULL, 0 }, { "112233445566778899AABBCCDDEEFG11223344", NULL, 0, 0 },
{ "0:0112233445566778899aabbccddeeff11223344", NULL, 0 }, { "0:0112233445566778899aabbccddeeff11223344", NULL, 0, 0 },
{ "112233445566778899aabbccddeeff11223344:", NULL, 0 }, { "112233445566778899aabbccddeeff11223344:", NULL, 0, 0 },
{ "112233445566778899aabbccddeeff112233445", NULL, 0 }, { "112233445566778899aabbccddeeff112233445", NULL, 0, 0 },
{ "112233445566778899aabbccddeeff1122334455", NULL, 0, 1 }, { "112233445566778899aabbccddeeff1122334455", NULL, 0, 0, 1 },
{ "112233445566778899aabbccddeeff11223344blah", NULL, 0 }, { "112233445566778899aabbccddeeff11223344blah", NULL, 0, 0 },
{ "0", NULL, 0 }, { "0", NULL, 0, 0 },
{ "00:", NULL, 0 }, { "00:", NULL, 0, 0 },
{ "00x", NULL, 0 }, { "00x", NULL, 0, 0 },
{ NULL, NULL, 0 } { NULL, NULL, 0, 0 }
}; };
int idx; int idx;
@ -369,7 +370,7 @@ test_hex2str (void)
fail (idx); fail (idx);
else if (tail - tests[idx].hex != tests[idx].off) else if (tail - tests[idx].hex != tests[idx].off)
fail (idx); fail (idx);
else if (strlen (buffer) != count) else if (tests[idx].len != count)
fail (idx); fail (idx);
} }
else else
@ -400,7 +401,7 @@ test_hex2str (void)
fail (idx); fail (idx);
else if (tail - tmpbuf != tests[idx].off) else if (tail - tmpbuf != tests[idx].off)
fail (idx); fail (idx);
else if (strlen (tmpbuf) != count) else if (tests[idx].len != count)
fail (idx); fail (idx);
} }
else else