]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
parse-util: rework parse_dev() based on safe_atou() and DEVICE_MAJOR_VALID()/DEVICE_M...
authorLennart Poettering <lennart@poettering.net>
Fri, 29 Jun 2018 09:58:24 +0000 (11:58 +0200)
committerLennart Poettering <lennart@poettering.net>
Thu, 29 Nov 2018 19:02:39 +0000 (20:02 +0100)
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.

src/basic/parse-util.c
src/test/test-parse-util.c

index ce8bb12670bea1cb2f584670bb97b49b4515d78a..718357e290f6d98c31696113075d2da13fb0a5aa 100644 (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;
-
-        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;
 }
 
index e9aef5e88269e7903f46a0c7693fcd948a1381ed..d732f402f0b9091769cc3a3666b0ea442f433c92 100644 (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) {