summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authorKarel Zak2019-03-20 13:12:25 +0100
committerKarel Zak2019-03-20 13:12:25 +0100
commit65bcbf105bfc5f6510b8df8db09d9458f942c799 (patch)
tree37845ed501bba2e920aaaadc955842cf06c7fa21 /lib
parentlscpu: (man) tiny changes (diff)
downloadkernel-qcow2-util-linux-65bcbf105bfc5f6510b8df8db09d9458f942c799.tar.gz
kernel-qcow2-util-linux-65bcbf105bfc5f6510b8df8db09d9458f942c799.tar.xz
kernel-qcow2-util-linux-65bcbf105bfc5f6510b8df8db09d9458f942c799.zip
taskset: fix cpuset list parser
taskset hangs when executed with badly formatted cpuset list, for example: $ taskset -c 0--1 true The current cpuset list parser is pretty weak as based on scanf() without strings verification ("-1" as input for "%u" returns unexpected number). It seems faster and better to use strtoul() and isdigit(). Addresses: https://github.com/karelzak/util-linux/issues/77 Signed-off-by: Karel Zak <kzak@redhat.com>
Diffstat (limited to 'lib')
-rw-r--r--lib/cpuset.c32
1 files changed, 24 insertions, 8 deletions
diff --git a/lib/cpuset.c b/lib/cpuset.c
index 011b6882b..2847db853 100644
--- a/lib/cpuset.c
+++ b/lib/cpuset.c
@@ -260,6 +260,19 @@ int cpumask_parse(const char *str, cpu_set_t *set, size_t setsize)
return 0;
}
+static int nextnumber(const char *str, char **end, unsigned int *result)
+{
+ errno = 0;
+ if (str == NULL || *str == '\0' || !isdigit(*str))
+ return -EINVAL;
+ *result = (unsigned int) strtoul(str, end, 10);
+ if (errno)
+ return -errno;
+ if (str == *end)
+ return -EINVAL;
+ return 0;
+}
+
/*
* Parses string with list of CPU ranges.
* Returns 0 on success.
@@ -272,7 +285,7 @@ int cpulist_parse(const char *str, cpu_set_t *set, size_t setsize, int fail)
{
size_t max = cpuset_nbits(setsize);
const char *p, *q;
- int r = 0;
+ char *end = NULL;
q = str;
CPU_ZERO_S(setsize, set);
@@ -282,21 +295,24 @@ int cpulist_parse(const char *str, cpu_set_t *set, size_t setsize, int fail)
unsigned int b; /* end of range */
unsigned int s; /* stride */
const char *c1, *c2;
- char c;
- if ((r = sscanf(p, "%u%c", &a, &c)) < 1)
+ if (nextnumber(p, &end, &a) != 0)
return 1;
b = a;
s = 1;
+ p = end;
c1 = nexttoken(p, '-');
c2 = nexttoken(p, ',');
+
if (c1 != NULL && (c2 == NULL || c1 < c2)) {
- if ((r = sscanf(c1, "%u%c", &b, &c)) < 1)
+ if (nextnumber(c1, &end, &b) != 0)
return 1;
- c1 = nexttoken(c1, ':');
+
+ c1 = end && *end ? nexttoken(end, ':') : NULL;
+
if (c1 != NULL && (c2 == NULL || c1 < c2)) {
- if ((r = sscanf(c1, "%u%c", &s, &c)) < 1)
+ if (nextnumber(c1, &end, &s) != 0)
return 1;
if (s == 0)
return 1;
@@ -313,7 +329,7 @@ int cpulist_parse(const char *str, cpu_set_t *set, size_t setsize, int fail)
}
}
- if (r == 2)
+ if (end && *end)
return 1;
return 0;
}
@@ -390,7 +406,7 @@ int main(int argc, char *argv[])
usage_err:
fprintf(stderr,
- "usage: %s [--ncpus <num>] --mask <mask> | --range <list>",
+ "usage: %s [--ncpus <num>] --mask <mask> | --range <list>\n",
program_invocation_short_name);
exit(EXIT_FAILURE);
}