From 65bcbf105bfc5f6510b8df8db09d9458f942c799 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Wed, 20 Mar 2019 13:12:25 +0100 Subject: 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 --- lib/cpuset.c | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) (limited to 'lib') 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 ] --mask | --range ", + "usage: %s [--ncpus ] --mask | --range \n", program_invocation_short_name); exit(EXIT_FAILURE); } -- cgit v1.2.3-55-g7522