From 4937b81a7b183d3c0e5c15aac5ac0834a3246b8f Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 11 May 2018 14:36:22 +0900 Subject: [PATCH 1/6] hexdecoct: ignore whitespace within the input hexadecimal text of unhexmem() --- src/basic/hexdecoct.c | 68 ++++++++++++++++++++++++++++++--------- src/test/test-hexdecoct.c | 40 +++++++++++++++++------ 2 files changed, 82 insertions(+), 26 deletions(-) diff --git a/src/basic/hexdecoct.c b/src/basic/hexdecoct.c index 7ab5c5f70b1..1c1949f1f03 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; - const char *x; +static int unhex_next(const char **p, size_t *l) { + int r; - assert(mem); - assert(len); + 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(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 18c9fb508d1..9f6b3a5e753 100644 --- a/src/test/test-hexdecoct.c +++ b/src/test/test-hexdecoct.c @@ -76,20 +76,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; - assert_se((hex2 = hexmem(mem, len))); - assert_se(streq(hex, hex2)); + 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"; + + 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 */ From aba135249ee664775c63dec61d8a3e54e736c694 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 11 May 2018 13:55:28 +0900 Subject: [PATCH 2/6] basic: fix comment style --- src/basic/hexdecoct.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/basic/hexdecoct.c b/src/basic/hexdecoct.c index 1c1949f1f03..7a7201b56a9 100644 --- a/src/basic/hexdecoct.c +++ b/src/basic/hexdecoct.c @@ -217,7 +217,7 @@ char *base32hexmem(const void *p, size_t l, bool padding) { for (x = p; x < (const uint8_t*) p + (l / 5) * 5; x += 5) { /* x[0] == XXXXXXXX; x[1] == YYYYYYYY; x[2] == ZZZZZZZZ - x[3] == QQQQQQQQ; x[4] == WWWWWWWW */ + * x[3] == QQQQQQQQ; x[4] == WWWWWWWW */ *(z++) = base32hexchar(x[0] >> 3); /* 000XXXXX */ *(z++) = base32hexchar((x[0] & 7) << 2 | x[1] >> 6); /* 000XXXYY */ *(z++) = base32hexchar((x[1] & 63) >> 1); /* 000YYYYY */ @@ -317,7 +317,7 @@ int unbase32hexmem(const char *p, size_t l, bool padding, void **mem, size_t *_l } /* a group of eight input bytes needs five output bytes, in case of - padding we need to add some extra bytes */ + * padding we need to add some extra bytes */ len = (l / 8) * 5; switch (l % 8) { @@ -345,7 +345,7 @@ int unbase32hexmem(const char *p, size_t l, bool padding, void **mem, size_t *_l for (x = p; x < p + (l / 8) * 8; x += 8) { /* a == 000XXXXX; b == 000YYYYY; c == 000ZZZZZ; d == 000WWWWW - e == 000SSSSS; f == 000QQQQQ; g == 000VVVVV; h == 000RRRRR */ + * e == 000SSSSS; f == 000QQQQQ; g == 000VVVVV; h == 000RRRRR */ a = unbase32hexchar(x[0]); if (a < 0) return -EINVAL; @@ -701,7 +701,7 @@ int unbase64mem(const char *p, size_t l, void **ret, size_t *ret_size) { l = strlen(p); /* A group of four input bytes needs three output bytes, in case of padding we need to add two or three extra - bytes. Note that this calculation is an upper boundary, as we ignore whitespace while decoding */ + * bytes. Note that this calculation is an upper boundary, as we ignore whitespace while decoding */ len = (l / 4) * 3 + (l % 4 != 0 ? (l % 4) - 1 : 0); buf = malloc(len + 1); From 9ec578a370c33f09c93f0a3f174dc27483c538c4 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 11 May 2018 13:56:28 +0900 Subject: [PATCH 3/6] hexdecoct: drop an unnecessary check --- src/basic/hexdecoct.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/basic/hexdecoct.c b/src/basic/hexdecoct.c index 7a7201b56a9..b3ea05ce53e 100644 --- a/src/basic/hexdecoct.c +++ b/src/basic/hexdecoct.c @@ -769,9 +769,7 @@ int unbase64mem(const char *p, size_t l, void **ret, size_t *ret_size) { *z = 0; - if (ret_size) - *ret_size = (size_t) (z - buf); - + *ret_size = (size_t) (z - buf); *ret = TAKE_PTR(buf); return 0; From 509685f91aadf6bc56c8298a40d4879494e4e3fe Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Wed, 9 May 2018 12:50:27 +0900 Subject: [PATCH 4/6] resolve: allow whitespaces in the DS digest or DNSKEY key data Fixes #3682. --- src/resolve/resolved-dns-trust-anchor.c | 35 ++++++++++++++----------- 1 file changed, 20 insertions(+), 15 deletions(-) diff --git a/src/resolve/resolved-dns-trust-anchor.c b/src/resolve/resolved-dns-trust-anchor.c index 57898dbbc12..51e28796c5b 100644 --- a/src/resolve/resolved-dns-trust-anchor.c +++ b/src/resolve/resolved-dns-trust-anchor.c @@ -242,18 +242,18 @@ static int dns_trust_anchor_load_positive(DnsTrustAnchor *d, const char *path, u } if (strcaseeq(type, "DS")) { - _cleanup_free_ char *key_tag = NULL, *algorithm = NULL, *digest_type = NULL, *digest = NULL; + _cleanup_free_ char *key_tag = NULL, *algorithm = NULL, *digest_type = NULL; _cleanup_free_ void *dd = NULL; uint16_t kt; int a, dt; size_t l; - r = extract_many_words(&p, NULL, 0, &key_tag, &algorithm, &digest_type, &digest, NULL); + r = extract_many_words(&p, NULL, 0, &key_tag, &algorithm, &digest_type, NULL); if (r < 0) { log_warning_errno(r, "Failed to parse DS parameters on line %s:%u: %m", path, line); return -EINVAL; } - if (r != 4) { + if (r != 3) { log_warning("Missing DS parameters on line %s:%u", path, line); return -EINVAL; } @@ -274,9 +274,14 @@ static int dns_trust_anchor_load_positive(DnsTrustAnchor *d, const char *path, u return -EINVAL; } - r = unhexmem(digest, strlen(digest), &dd, &l); + if (isempty(p)) { + log_warning("Missing DS digest on line %s:%u", path, line); + return -EINVAL; + } + + r = unhexmem(p, strlen(p), &dd, &l); if (r < 0) { - log_warning("Failed to parse DS digest %s on line %s:%u", digest, path, line); + log_warning("Failed to parse DS digest %s on line %s:%u", p, path, line); return -EINVAL; } @@ -291,16 +296,16 @@ static int dns_trust_anchor_load_positive(DnsTrustAnchor *d, const char *path, u rr->ds.digest = TAKE_PTR(dd); } else if (strcaseeq(type, "DNSKEY")) { - _cleanup_free_ char *flags = NULL, *protocol = NULL, *algorithm = NULL, *key = NULL; + _cleanup_free_ char *flags = NULL, *protocol = NULL, *algorithm = NULL; _cleanup_free_ void *k = NULL; uint16_t f; size_t l; int a; - r = extract_many_words(&p, NULL, 0, &flags, &protocol, &algorithm, &key, NULL); + r = extract_many_words(&p, NULL, 0, &flags, &protocol, &algorithm, NULL); if (r < 0) return log_warning_errno(r, "Failed to parse DNSKEY parameters on line %s:%u: %m", path, line); - if (r != 4) { + if (r != 3) { log_warning("Missing DNSKEY parameters on line %s:%u", path, line); return -EINVAL; } @@ -328,9 +333,14 @@ static int dns_trust_anchor_load_positive(DnsTrustAnchor *d, const char *path, u return -EINVAL; } - r = unbase64mem(key, strlen(key), &k, &l); + if (isempty(p)) { + log_warning("Missing DNSKEY key on line %s:%u", path, line); + return -EINVAL; + } + + r = unbase64mem(p, strlen(p), &k, &l); if (r < 0) - return log_warning_errno(r, "Failed to parse DNSKEY key data %s on line %s:%u", key, path, line); + return log_warning_errno(r, "Failed to parse DNSKEY key data %s on line %s:%u", p, path, line); rr = dns_resource_record_new_full(DNS_CLASS_IN, DNS_TYPE_DNSKEY, domain); if (!rr) @@ -347,11 +357,6 @@ static int dns_trust_anchor_load_positive(DnsTrustAnchor *d, const char *path, u return -EINVAL; } - if (!isempty(p)) { - log_warning("Trailing garbage on line %s:%u, ignoring line.", path, line); - return -EINVAL; - } - r = hashmap_ensure_allocated(&d->positive_by_key, &dns_resource_key_hash_ops); if (r < 0) return log_oom(); From ce088d6fb4a6363106e4b94ad749d3bce61aefc7 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 11 May 2018 14:44:03 +0900 Subject: [PATCH 5/6] sd-dhcp: drop deserialize_dhcp_option() as it is equivalent to unhexmem() --- src/libsystemd-network/network-internal.c | 11 ----------- src/libsystemd-network/network-internal.h | 2 +- src/libsystemd-network/sd-dhcp-lease.c | 6 +++--- 3 files changed, 4 insertions(+), 15 deletions(-) diff --git a/src/libsystemd-network/network-internal.c b/src/libsystemd-network/network-internal.c index 7c2bf962d65..f2acb281f5a 100644 --- a/src/libsystemd-network/network-internal.c +++ b/src/libsystemd-network/network-internal.c @@ -656,14 +656,3 @@ int serialize_dhcp_option(FILE *f, const char *key, const void *data, size_t siz return 0; } - -int deserialize_dhcp_option(void **data, size_t *data_len, const char *string) { - assert(data); - assert(data_len); - assert(string); - - if (strlen(string) % 2) - return -EINVAL; - - return unhexmem(string, strlen(string), (void **)data, data_len); -} diff --git a/src/libsystemd-network/network-internal.h b/src/libsystemd-network/network-internal.h index c7b659b7317..d0076f453d3 100644 --- a/src/libsystemd-network/network-internal.h +++ b/src/libsystemd-network/network-internal.h @@ -78,5 +78,5 @@ struct sd_dhcp_route; void serialize_dhcp_routes(FILE *f, const char *key, sd_dhcp_route **routes, size_t size); int deserialize_dhcp_routes(struct sd_dhcp_route **ret, size_t *ret_size, size_t *ret_allocated, const char *string); +/* It is not necessary to add deserialize_dhcp_option(). Use unhexmem() instead. */ int serialize_dhcp_option(FILE *f, const char *key, const void *data, size_t size); -int deserialize_dhcp_option(void **data, size_t *data_len, const char *string); diff --git a/src/libsystemd-network/sd-dhcp-lease.c b/src/libsystemd-network/sd-dhcp-lease.c index c4670503cc0..ed951aeb7dc 100644 --- a/src/libsystemd-network/sd-dhcp-lease.c +++ b/src/libsystemd-network/sd-dhcp-lease.c @@ -1193,13 +1193,13 @@ int dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file) { } if (client_id_hex) { - r = deserialize_dhcp_option(&lease->client_id, &lease->client_id_len, client_id_hex); + r = unhexmem(client_id_hex, (size_t) -1, &lease->client_id, &lease->client_id_len); if (r < 0) log_debug_errno(r, "Failed to parse client ID %s, ignoring: %m", client_id_hex); } if (vendor_specific_hex) { - r = deserialize_dhcp_option(&lease->vendor_specific, &lease->vendor_specific_len, vendor_specific_hex); + r = unhexmem(vendor_specific_hex, (size_t) -1, &lease->vendor_specific, &lease->vendor_specific_len); if (r < 0) log_debug_errno(r, "Failed to parse vendor specific data %s, ignoring: %m", vendor_specific_hex); } @@ -1211,7 +1211,7 @@ int dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file) { if (!options[i]) continue; - r = deserialize_dhcp_option(&data, &len, options[i]); + r = unhexmem(options[i], (size_t) -1, &data, &len); if (r < 0) { log_debug_errno(r, "Failed to parse private DHCP option %s, ignoring: %m", options[i]); continue; From 2d2c21afb209dab8a21ca4e6437bfe83d8fb8da7 Mon Sep 17 00:00:00 2001 From: Yu Watanabe Date: Fri, 11 May 2018 15:01:35 +0900 Subject: [PATCH 6/6] test: do not call alloca() inside the list of arguments --- src/test/test-hexdecoct.c | 129 +++++++++++++++----------------------- 1 file changed, 50 insertions(+), 79 deletions(-) diff --git a/src/test/test-hexdecoct.c b/src/test/test-hexdecoct.c index 9f6b3a5e753..fb98826c278 100644 --- a/src/test/test-hexdecoct.c +++ b/src/test/test-hexdecoct.c @@ -187,94 +187,65 @@ static void test_base32hexmem(void) { free(b32); } -static void test_unbase32hexmem(void) { - void *mem; +static void test_unbase32hexmem_one(const char *hex, bool padding, int retval, const char *ans) { + _cleanup_free_ void *mem = NULL; size_t len; - assert_se(unbase32hexmem("", STRLEN(""), true, &mem, &len) == 0); - assert_se(streq(strndupa(mem, len), "")); - free(mem); + assert_se(unbase32hexmem(hex, (size_t) -1, padding, &mem, &len) == retval); + if (retval == 0) { + char *str; - assert_se(unbase32hexmem("CO======", STRLEN("CO======"), true, &mem, &len) == 0); - assert_se(streq(strndupa(mem, len), "f")); - free(mem); + str = strndupa(mem, len); + assert_se(streq(str, ans)); + } +} - assert_se(unbase32hexmem("CPNG====", STRLEN("CPNG===="), true, &mem, &len) == 0); - assert_se(streq(strndupa(mem, len), "fo")); - free(mem); +static void test_unbase32hexmem(void) { + test_unbase32hexmem_one("", true, 0, ""); - assert_se(unbase32hexmem("CPNMU===", STRLEN("CPNMU==="), true, &mem, &len) == 0); - assert_se(streq(strndupa(mem, len), "foo")); - free(mem); + test_unbase32hexmem_one("CO======", true, 0, "f"); + test_unbase32hexmem_one("CPNG====", true, 0, "fo"); + test_unbase32hexmem_one("CPNMU===", true, 0, "foo"); + test_unbase32hexmem_one("CPNMUOG=", true, 0, "foob"); + test_unbase32hexmem_one("CPNMUOJ1", true, 0, "fooba"); + test_unbase32hexmem_one("CPNMUOJ1E8======", true, 0, "foobar"); - assert_se(unbase32hexmem("CPNMUOG=", STRLEN("CPNMUOG="), true, &mem, &len) == 0); - assert_se(streq(strndupa(mem, len), "foob")); - free(mem); + test_unbase32hexmem_one("A", true, -EINVAL, NULL); + test_unbase32hexmem_one("A=======", true, -EINVAL, NULL); + test_unbase32hexmem_one("AAA=====", true, -EINVAL, NULL); + test_unbase32hexmem_one("AAAAAA==", true, -EINVAL, NULL); + test_unbase32hexmem_one("AB======", true, -EINVAL, NULL); + test_unbase32hexmem_one("AAAB====", true, -EINVAL, NULL); + test_unbase32hexmem_one("AAAAB===", true, -EINVAL, NULL); + test_unbase32hexmem_one("AAAAAAB=", true, -EINVAL, NULL); - assert_se(unbase32hexmem("CPNMUOJ1", STRLEN("CPNMUOJ1"), true, &mem, &len) == 0); - assert_se(streq(strndupa(mem, len), "fooba")); - free(mem); + test_unbase32hexmem_one("XPNMUOJ1", true, -EINVAL, NULL); + test_unbase32hexmem_one("CXNMUOJ1", true, -EINVAL, NULL); + test_unbase32hexmem_one("CPXMUOJ1", true, -EINVAL, NULL); + test_unbase32hexmem_one("CPNXUOJ1", true, -EINVAL, NULL); + test_unbase32hexmem_one("CPNMXOJ1", true, -EINVAL, NULL); + test_unbase32hexmem_one("CPNMUXJ1", true, -EINVAL, NULL); + test_unbase32hexmem_one("CPNMUOX1", true, -EINVAL, NULL); + test_unbase32hexmem_one("CPNMUOJX", true, -EINVAL, NULL); - assert_se(unbase32hexmem("CPNMUOJ1E8======", STRLEN("CPNMUOJ1E8======"), true, &mem, &len) == 0); - assert_se(streq(strndupa(mem, len), "foobar")); - free(mem); + test_unbase32hexmem_one("", false, 0, ""); + test_unbase32hexmem_one("CO", false, 0, "f"); + test_unbase32hexmem_one("CPNG", false, 0, "fo"); + test_unbase32hexmem_one("CPNMU", false, 0, "foo"); + test_unbase32hexmem_one("CPNMUOG", false, 0, "foob"); + test_unbase32hexmem_one("CPNMUOJ1", false, 0, "fooba"); + test_unbase32hexmem_one("CPNMUOJ1E8", false, 0, "foobar"); + test_unbase32hexmem_one("CPNMUOG=", false, -EINVAL, NULL); + test_unbase32hexmem_one("CPNMUOJ1E8======", false, -EINVAL, NULL); - assert_se(unbase32hexmem("A", STRLEN("A"), true, &mem, &len) == -EINVAL); - assert_se(unbase32hexmem("A=======", STRLEN("A======="), true, &mem, &len) == -EINVAL); - assert_se(unbase32hexmem("AAA=====", STRLEN("AAA====="), true, &mem, &len) == -EINVAL); - assert_se(unbase32hexmem("AAAAAA==", STRLEN("AAAAAA=="), true, &mem, &len) == -EINVAL); - assert_se(unbase32hexmem("AB======", STRLEN("AB======"), true, &mem, &len) == -EINVAL); - assert_se(unbase32hexmem("AAAB====", STRLEN("AAAB===="), true, &mem, &len) == -EINVAL); - assert_se(unbase32hexmem("AAAAB===", STRLEN("AAAAB==="), true, &mem, &len) == -EINVAL); - assert_se(unbase32hexmem("AAAAAAB=", STRLEN("AAAAAAB="), true, &mem, &len) == -EINVAL); - - assert_se(unbase32hexmem("XPNMUOJ1", STRLEN("CPNMUOJ1"), true, &mem, &len) == -EINVAL); - assert_se(unbase32hexmem("CXNMUOJ1", STRLEN("CPNMUOJ1"), true, &mem, &len) == -EINVAL); - assert_se(unbase32hexmem("CPXMUOJ1", STRLEN("CPNMUOJ1"), true, &mem, &len) == -EINVAL); - assert_se(unbase32hexmem("CPNXUOJ1", STRLEN("CPNMUOJ1"), true, &mem, &len) == -EINVAL); - assert_se(unbase32hexmem("CPNMXOJ1", STRLEN("CPNMUOJ1"), true, &mem, &len) == -EINVAL); - assert_se(unbase32hexmem("CPNMUXJ1", STRLEN("CPNMUOJ1"), true, &mem, &len) == -EINVAL); - assert_se(unbase32hexmem("CPNMUOX1", STRLEN("CPNMUOJ1"), true, &mem, &len) == -EINVAL); - assert_se(unbase32hexmem("CPNMUOJX", STRLEN("CPNMUOJ1"), true, &mem, &len) == -EINVAL); - - assert_se(unbase32hexmem("", STRLEN(""), false, &mem, &len) == 0); - assert_se(streq(strndupa(mem, len), "")); - free(mem); - - assert_se(unbase32hexmem("CO", STRLEN("CO"), false, &mem, &len) == 0); - assert_se(streq(strndupa(mem, len), "f")); - free(mem); - - assert_se(unbase32hexmem("CPNG", STRLEN("CPNG"), false, &mem, &len) == 0); - assert_se(streq(strndupa(mem, len), "fo")); - free(mem); - - assert_se(unbase32hexmem("CPNMU", STRLEN("CPNMU"), false, &mem, &len) == 0); - assert_se(streq(strndupa(mem, len), "foo")); - free(mem); - - assert_se(unbase32hexmem("CPNMUOG", STRLEN("CPNMUOG"), false, &mem, &len) == 0); - assert_se(streq(strndupa(mem, len), "foob")); - free(mem); - - assert_se(unbase32hexmem("CPNMUOJ1", STRLEN("CPNMUOJ1"), false, &mem, &len) == 0); - assert_se(streq(strndupa(mem, len), "fooba")); - free(mem); - - assert_se(unbase32hexmem("CPNMUOJ1E8", STRLEN("CPNMUOJ1E8"), false, &mem, &len) == 0); - assert_se(streq(strndupa(mem, len), "foobar")); - free(mem); - - assert_se(unbase32hexmem("CPNMUOG=", STRLEN("CPNMUOG="), false, &mem, &len) == -EINVAL); - assert_se(unbase32hexmem("CPNMUOJ1E8======", STRLEN("CPNMUOJ1E8======"), false, &mem, &len) == -EINVAL); - assert_se(unbase32hexmem("A", STRLEN("A"), false, &mem, &len) == -EINVAL); - assert_se(unbase32hexmem("A", STRLEN("A"), false, &mem, &len) == -EINVAL); - assert_se(unbase32hexmem("AAA", STRLEN("AAA"), false, &mem, &len) == -EINVAL); - assert_se(unbase32hexmem("AAAAAA", STRLEN("AAAAAA"), false, &mem, &len) == -EINVAL); - assert_se(unbase32hexmem("AB", STRLEN("AB"), false, &mem, &len) == -EINVAL); - assert_se(unbase32hexmem("AAAB", STRLEN("AAAB"), false, &mem, &len) == -EINVAL); - assert_se(unbase32hexmem("AAAAB", STRLEN("AAAAB"), false, &mem, &len) == -EINVAL); - assert_se(unbase32hexmem("AAAAAAB", STRLEN("AAAAAAB"), false, &mem, &len) == -EINVAL); + test_unbase32hexmem_one("A", false, -EINVAL, NULL); + test_unbase32hexmem_one("A", false, -EINVAL, NULL); + test_unbase32hexmem_one("AAA", false, -EINVAL, NULL); + test_unbase32hexmem_one("AAAAAA", false, -EINVAL, NULL); + test_unbase32hexmem_one("AB", false, -EINVAL, NULL); + test_unbase32hexmem_one("AAAB", false, -EINVAL, NULL); + test_unbase32hexmem_one("AAAAB", false, -EINVAL, NULL); + test_unbase32hexmem_one("AAAAAAB", false, -EINVAL, NULL); } /* https://tools.ietf.org/html/rfc4648#section-10 */