From: Lennart Poettering Date: Fri, 29 Jun 2018 09:58:24 +0000 (+0200) Subject: parse-util: rework parse_dev() based on safe_atou() and DEVICE_MAJOR_VALID()/DEVICE_M... X-Git-Tag: v240~168^2~14 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=de06c0cf77e2a58b4655ad5608f85ff8a6e724c7;p=thirdparty%2Fsystemd.git parse-util: rework parse_dev() based on safe_atou() and DEVICE_MAJOR_VALID()/DEVICE_MINOR_VALID() Let's be a bit more careful when parsing major/minor pairs, and filter out more corner cases. This also means using safe_atou() rather than sscanf() to avoid weird negative unsigned handling and such. --- diff --git a/src/basic/parse-util.c b/src/basic/parse-util.c index ce8bb12670b..718357e290f 100644 --- a/src/basic/parse-util.c +++ b/src/basic/parse-util.c @@ -16,6 +16,7 @@ #include "missing.h" #include "parse-util.h" #include "process-util.h" +#include "stat-util.h" #include "string-util.h" int parse_boolean(const char *v) { @@ -731,17 +732,30 @@ int parse_ip_port_range(const char *s, uint16_t *low, uint16_t *high) { } int parse_dev(const char *s, dev_t *ret) { + const char *major; unsigned x, y; - dev_t d; + size_t n; + int r; - if (sscanf(s, "%u:%u", &x, &y) != 2) + n = strspn(s, DIGITS); + if (n == 0) return -EINVAL; - - d = makedev(x, y); - if ((unsigned) major(d) != x || (unsigned) minor(d) != y) + if (s[n] != ':') return -EINVAL; - *ret = d; + major = strndupa(s, n); + r = safe_atou(major, &x); + if (r < 0) + return r; + + r = safe_atou(s + n + 1, &y); + if (r < 0) + return r; + + if (!DEVICE_MAJOR_VALID(x) || !DEVICE_MINOR_VALID(y)) + return -ERANGE; + + *ret = makedev(x, y); return 0; } diff --git a/src/test/test-parse-util.c b/src/test/test-parse-util.c index e9aef5e8826..d732f402f0b 100644 --- a/src/test/test-parse-util.c +++ b/src/test/test-parse-util.c @@ -726,10 +726,12 @@ static void test_parse_dev(void) { assert_se(parse_dev("5", &dev) == -EINVAL); assert_se(parse_dev("5:", &dev) == -EINVAL); assert_se(parse_dev(":5", &dev) == -EINVAL); + assert_se(parse_dev("-1:-1", &dev) == -EINVAL); #if SIZEOF_DEV_T < 8 assert_se(parse_dev("4294967295:4294967295", &dev) == -EINVAL); #endif assert_se(parse_dev("8:11", &dev) >= 0 && major(dev) == 8 && minor(dev) == 11); + assert_se(parse_dev("0:0", &dev) >= 0 && major(dev) == 0 && minor(dev) == 0); } static void test_parse_errno(void) {