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.
This commit is contained in:
Lennart Poettering 2018-06-29 11:58:24 +02:00
parent fa583ab176
commit de06c0cf77
2 changed files with 22 additions and 6 deletions

View File

@ -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;
if (s[n] != ':')
return -EINVAL;
d = makedev(x, y);
if ((unsigned) major(d) != x || (unsigned) minor(d) != y)
return -EINVAL;
major = strndupa(s, n);
r = safe_atou(major, &x);
if (r < 0)
return r;
*ret = d;
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;
}

View File

@ -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) {