From: Yu Watanabe Date: Fri, 11 May 2018 05:36:22 +0000 (+0900) Subject: hexdecoct: ignore whitespace within the input hexadecimal text of unhexmem() X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=commitdiff_plain;h=be15b89486397492cef33c86f51e248b55ba20dd;p=elogind.git hexdecoct: ignore whitespace within the input hexadecimal text of unhexmem() --- diff --git a/src/basic/hexdecoct.c b/src/basic/hexdecoct.c index 7ab5c5f70..1c1949f1f 100644 --- a/src/basic/hexdecoct.c +++ b/src/basic/hexdecoct.c @@ -77,33 +77,69 @@ char *hexmem(const void *p, size_t l) { return r; } -int unhexmem(const char *p, size_t l, void **mem, size_t *len) { - _cleanup_free_ uint8_t *r = NULL; - uint8_t *z; +static int unhex_next(const char **p, size_t *l) { + int r; + + assert(p); + assert(l); + + /* Find the next non-whitespace character, and decode it. We + * greedily skip all preceeding and all following whitespace. */ + + for (;;) { + if (*l == 0) + return -EPIPE; + + if (!strchr(WHITESPACE, **p)) + break; + + /* Skip leading whitespace */ + (*p)++, (*l)--; + } + + r = unhexchar(**p); + if (r < 0) + return r; + + for (;;) { + (*p)++, (*l)--; + + if (*l == 0 || !strchr(WHITESPACE, **p)) + break; + + /* Skip following whitespace */ + } + + return r; +} + +int unhexmem(const char *p, size_t l, void **ret, size_t *ret_len) { + _cleanup_free_ uint8_t *buf = NULL; const char *x; + uint8_t *z; - assert(mem); - assert(len); + assert(ret); + assert(ret_len); assert(p || l == 0); if (l == (size_t) -1) l = strlen(p); - if (l % 2 != 0) - return -EINVAL; - - z = r = malloc((l + 1) / 2 + 1); - if (!r) + /* Note that the calculation of memory size is an upper boundary, as we ignore whitespace while decoding */ + buf = malloc((l + 1) / 2 + 1); + if (!buf) return -ENOMEM; - for (x = p; x < p + l; x += 2) { + for (x = p, z = buf;;) { int a, b; - a = unhexchar(x[0]); + a = unhex_next(&x, &l); + if (a == -EPIPE) /* End of string */ + break; if (a < 0) return a; - b = unhexchar(x[1]); + b = unhex_next(&x, &l); if (b < 0) return b; @@ -112,8 +148,8 @@ int unhexmem(const char *p, size_t l, void **mem, size_t *len) { *z = 0; - *mem = TAKE_PTR(r); - *len = (l + 1) / 2; + *ret_len = (size_t) (z - buf); + *ret = TAKE_PTR(buf); return 0; } diff --git a/src/test/test-hexdecoct.c b/src/test/test-hexdecoct.c index 74b8e3b68..048e8cb82 100644 --- a/src/test/test-hexdecoct.c +++ b/src/test/test-hexdecoct.c @@ -79,20 +79,40 @@ static void test_undecchar(void) { assert_se(undecchar('9') == 9); } -static void test_unhexmem(void) { - const char *hex = "efa2149213"; - const char *hex_invalid = "efa214921o"; - _cleanup_free_ char *hex2 = NULL; +static void test_unhexmem_one(const char *s, size_t l, int retval) { + _cleanup_free_ char *hex = NULL; _cleanup_free_ void *mem = NULL; size_t len; - assert_se(unhexmem(hex_invalid, strlen(hex_invalid), &mem, &len) == -EINVAL); - assert_se(unhexmem(hex, strlen(hex) + 1, &mem, &len) == -EINVAL); - assert_se(unhexmem(hex, strlen(hex) - 1, &mem, &len) == -EINVAL); - assert_se(unhexmem(hex, strlen(hex), &mem, &len) == 0); + assert_se(unhexmem(s, l, &mem, &len) == retval); + if (retval == 0) { + char *answer; + + if (l == (size_t) - 1) + l = strlen(s); + + assert_se((hex = hexmem(mem, len))); + answer = strndupa(s, l); + assert_se(streq(delete_chars(answer, WHITESPACE), hex)); + } +} + +static void test_unhexmem(void) { + const char *hex = "efa2149213"; + const char *hex_space = " e f a\n 2\r 14\n\r\t9\t2 \n1\r3 \r\r\t"; + const char *hex_invalid = "efa214921o"; - assert_se((hex2 = hexmem(mem, len))); - assert_se(streq(hex, hex2)); + test_unhexmem_one(NULL, 0, 0); + test_unhexmem_one("", 0, 0); + test_unhexmem_one("", (size_t) -1, 0); + test_unhexmem_one(" \n \t\r \t\t \n\n\n", (size_t) -1, 0); + test_unhexmem_one(hex_invalid, strlen(hex_invalid), -EINVAL); + test_unhexmem_one(hex_invalid, (size_t) - 1, -EINVAL); + test_unhexmem_one(hex, strlen(hex) - 1, -EPIPE); + test_unhexmem_one(hex, strlen(hex), 0); + test_unhexmem_one(hex, (size_t) -1, 0); + test_unhexmem_one(hex_space, strlen(hex_space), 0); + test_unhexmem_one(hex_space, (size_t) -1, 0); } /* https://tools.ietf.org/html/rfc4648#section-10 */