summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/basic/util.c24
-rw-r--r--src/basic/util.h2
-rw-r--r--src/libsystemd-network/sd-dhcp-lease.c9
-rw-r--r--src/libsystemd/sd-bus/bus-socket.c20
-rw-r--r--src/test/test-util.c25
5 files changed, 60 insertions, 20 deletions
diff --git a/src/basic/util.c b/src/basic/util.c
index 13a67e9ab8..61dd6c4227 100644
--- a/src/basic/util.c
+++ b/src/basic/util.c
@@ -916,30 +916,42 @@ char *hexmem(const void *p, size_t l) {
return r;
}
-void *unhexmem(const char *p, size_t l) {
- uint8_t *r, *z;
+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;
+ assert(mem);
+ assert(len);
assert(p);
z = r = malloc((l + 1) / 2 + 1);
if (!r)
- return NULL;
+ return -ENOMEM;
for (x = p; x < p + l; x += 2) {
int a, b;
a = unhexchar(x[0]);
- if (x+1 < p + l)
+ if (a < 0)
+ return a;
+ else if (x+1 < p + l) {
b = unhexchar(x[1]);
- else
+ if (b < 0)
+ return b;
+ } else
b = 0;
*(z++) = (uint8_t) a << 4 | (uint8_t) b;
}
*z = 0;
- return r;
+
+ *mem = r;
+ r = NULL;
+ *len = (l + 1) / 2;
+
+ return 0;
}
char octchar(int x) {
diff --git a/src/basic/util.h b/src/basic/util.h
index a1d1dd15c3..ea77907f7f 100644
--- a/src/basic/util.h
+++ b/src/basic/util.h
@@ -614,7 +614,7 @@ static inline void *mempset(void *s, int c, size_t n) {
}
char *hexmem(const void *p, size_t l);
-void *unhexmem(const char *p, size_t l);
+int unhexmem(const char *p, size_t l, void **mem, size_t *len);
char *strextend(char **x, ...) _sentinel_;
char *strrep(const char *s, unsigned n);
diff --git a/src/libsystemd-network/sd-dhcp-lease.c b/src/libsystemd-network/sd-dhcp-lease.c
index d8bc76edda..7548e50b7d 100644
--- a/src/libsystemd-network/sd-dhcp-lease.c
+++ b/src/libsystemd-network/sd-dhcp-lease.c
@@ -811,13 +811,12 @@ int sd_dhcp_lease_load(sd_dhcp_lease **ret, const char *lease_file) {
}
if (client_id_hex) {
- if (strlen (client_id_hex) % 2)
+ if (strlen(client_id_hex) % 2)
return -EINVAL;
- lease->client_id = unhexmem (client_id_hex, strlen (client_id_hex));
- if (!lease->client_id)
- return -ENOMEM;
- lease->client_id_len = strlen (client_id_hex) / 2;
+ r = unhexmem(client_id_hex, strlen(client_id_hex), (void**) &lease->client_id, &lease->client_id_len);
+ if (r < 0)
+ return r;
}
*ret = lease;
diff --git a/src/libsystemd/sd-bus/bus-socket.c b/src/libsystemd/sd-bus/bus-socket.c
index 322d57ddbb..735a775cb4 100644
--- a/src/libsystemd/sd-bus/bus-socket.c
+++ b/src/libsystemd/sd-bus/bus-socket.c
@@ -264,6 +264,8 @@ static bool line_begins(const char *s, size_t m, const char *word) {
static int verify_anonymous_token(sd_bus *b, const char *p, size_t l) {
_cleanup_free_ char *token = NULL;
+ size_t len;
+ int r;
if (!b->anonymous_auth)
return 0;
@@ -276,11 +278,12 @@ static int verify_anonymous_token(sd_bus *b, const char *p, size_t l) {
if (l % 2 != 0)
return 0;
- token = unhexmem(p, l);
- if (!token)
- return -ENOMEM;
- if (memchr(token, 0, l/2))
+ r = unhexmem(p, l, (void **) &token, &len);
+ if (r < 0)
+ return 0;
+
+ if (memchr(token, 0, len))
return 0;
return !!utf8_is_valid(token);
@@ -288,6 +291,7 @@ static int verify_anonymous_token(sd_bus *b, const char *p, size_t l) {
static int verify_external_token(sd_bus *b, const char *p, size_t l) {
_cleanup_free_ char *token = NULL;
+ size_t len;
uid_t u;
int r;
@@ -307,11 +311,11 @@ static int verify_external_token(sd_bus *b, const char *p, size_t l) {
if (l % 2 != 0)
return 0;
- token = unhexmem(p, l);
- if (!token)
- return -ENOMEM;
+ r = unhexmem(p, l, (void**) &token, &len);
+ if (r < 0)
+ return 0;
- if (memchr(token, 0, l/2))
+ if (memchr(token, 0, len))
return 0;
r = parse_uid(token, &u);
diff --git a/src/test/test-util.c b/src/test/test-util.c
index 9fbfece14f..f7949ebaac 100644
--- a/src/test/test-util.c
+++ b/src/test/test-util.c
@@ -410,6 +410,30 @@ static void test_undecchar(void) {
assert_se(undecchar('9') == 9);
}
+static void test_unhexmem(void) {
+ const char *hex = "efa214921";
+ const char *hex_invalid = "efa214921o";
+ _cleanup_free_ char *hex2 = NULL;
+ _cleanup_free_ void *mem = NULL;
+ size_t len;
+
+ assert_se(unhexmem(hex, strlen(hex), &mem, &len) == 0);
+ assert_se(unhexmem(hex, strlen(hex) + 1, &mem, &len) == -EINVAL);
+ assert_se(unhexmem(hex_invalid, strlen(hex_invalid), &mem, &len) == -EINVAL);
+
+ assert_se((hex2 = hexmem(mem, len)));
+
+ free(mem);
+
+ assert_se(memcmp(hex, hex2, strlen(hex)) == 0);
+
+ free(hex2);
+
+ assert_se(unhexmem(hex, strlen(hex) - 1, &mem, &len) == 0);
+ assert_se((hex2 = hexmem(mem, len)));
+ assert_se(memcmp(hex, hex2, strlen(hex) - 1) == 0);
+}
+
static void test_cescape(void) {
_cleanup_free_ char *escaped;
@@ -1808,6 +1832,7 @@ int main(int argc, char *argv[]) {
test_unoctchar();
test_decchar();
test_undecchar();
+ test_unhexmem();
test_cescape();
test_cunescape();
test_foreach_word();