mirror of
https://github.com/systemd/systemd
synced 2024-07-21 10:17:21 +00:00
parse-util: really refuse parsing negative values as positive ones, even on x86-32
strtoull() doesn't make it particularly easy to detect passed-in negative numbers, as it silently converts them to positive ones without generating any error. Since we are not interested in negative values we should hence explicitly filter them out by looking at the string directly and returning ERANGE if we see a leading "-". Fixes: #1829
This commit is contained in:
parent
b374689c02
commit
2d49a208f8
|
@ -67,11 +67,14 @@ int parse_mode(const char *s, mode_t *ret) {
|
|||
assert(s);
|
||||
assert(ret);
|
||||
|
||||
s += strspn(s, WHITESPACE);
|
||||
if (s[0] == '-')
|
||||
return -ERANGE;
|
||||
|
||||
errno = 0;
|
||||
l = strtol(s, &x, 8);
|
||||
if (errno != 0)
|
||||
return -errno;
|
||||
|
||||
if (!x || x == s || *x)
|
||||
return -EINVAL;
|
||||
if (l < 0 || l > 07777)
|
||||
|
@ -162,15 +165,15 @@ int parse_size(const char *t, uint64_t base, uint64_t *size) {
|
|||
unsigned i;
|
||||
|
||||
p += strspn(p, WHITESPACE);
|
||||
if (*p == '-')
|
||||
return -ERANGE;
|
||||
|
||||
errno = 0;
|
||||
l = strtoull(p, &e, 10);
|
||||
if (errno > 0)
|
||||
if (errno != 0)
|
||||
return -errno;
|
||||
if (e == p)
|
||||
return -EINVAL;
|
||||
if (*p == '-')
|
||||
return -ERANGE;
|
||||
|
||||
if (*e == '.') {
|
||||
e++;
|
||||
|
@ -181,7 +184,7 @@ int parse_size(const char *t, uint64_t base, uint64_t *size) {
|
|||
char *e2;
|
||||
|
||||
l2 = strtoull(e, &e2, 10);
|
||||
if (errno > 0)
|
||||
if (errno != 0)
|
||||
return -errno;
|
||||
|
||||
/* Ignore failure. E.g. 10.M is valid */
|
||||
|
@ -307,12 +310,24 @@ int safe_atou(const char *s, unsigned *ret_u) {
|
|||
assert(s);
|
||||
assert(ret_u);
|
||||
|
||||
/* strtoul() is happy to parse negative values, and silently
|
||||
* converts them to unsigned values without generating an
|
||||
* error. We want a clean error, hence let's look for the "-"
|
||||
* prefix on our own, and generate an error. But let's do so
|
||||
* only after strtoul() validated that the string is clean
|
||||
* otherwise, so that we return EINVAL preferably over
|
||||
* ERANGE. */
|
||||
|
||||
s += strspn(s, WHITESPACE);
|
||||
|
||||
errno = 0;
|
||||
l = strtoul(s, &x, 0);
|
||||
|
||||
if (!x || x == s || *x || errno)
|
||||
return errno > 0 ? -errno : -EINVAL;
|
||||
|
||||
if (errno != 0)
|
||||
return -errno;
|
||||
if (!x || x == s || *x)
|
||||
return -EINVAL;
|
||||
if (s[0] == '-')
|
||||
return -ERANGE;
|
||||
if ((unsigned long) (unsigned) l != l)
|
||||
return -ERANGE;
|
||||
|
||||
|
@ -329,10 +344,10 @@ int safe_atoi(const char *s, int *ret_i) {
|
|||
|
||||
errno = 0;
|
||||
l = strtol(s, &x, 0);
|
||||
|
||||
if (!x || x == s || *x || errno)
|
||||
return errno > 0 ? -errno : -EINVAL;
|
||||
|
||||
if (errno != 0)
|
||||
return -errno;
|
||||
if (!x || x == s || *x)
|
||||
return -EINVAL;
|
||||
if ((long) (int) l != l)
|
||||
return -ERANGE;
|
||||
|
||||
|
@ -347,11 +362,16 @@ int safe_atollu(const char *s, long long unsigned *ret_llu) {
|
|||
assert(s);
|
||||
assert(ret_llu);
|
||||
|
||||
s += strspn(s, WHITESPACE);
|
||||
|
||||
errno = 0;
|
||||
l = strtoull(s, &x, 0);
|
||||
|
||||
if (!x || x == s || *x || errno)
|
||||
return errno ? -errno : -EINVAL;
|
||||
if (errno != 0)
|
||||
return -errno;
|
||||
if (!x || x == s || *x)
|
||||
return -EINVAL;
|
||||
if (*s == '-')
|
||||
return -ERANGE;
|
||||
|
||||
*ret_llu = l;
|
||||
return 0;
|
||||
|
@ -366,9 +386,10 @@ int safe_atolli(const char *s, long long int *ret_lli) {
|
|||
|
||||
errno = 0;
|
||||
l = strtoll(s, &x, 0);
|
||||
|
||||
if (!x || x == s || *x || errno)
|
||||
return errno ? -errno : -EINVAL;
|
||||
if (errno != 0)
|
||||
return -errno;
|
||||
if (!x || x == s || *x)
|
||||
return -EINVAL;
|
||||
|
||||
*ret_lli = l;
|
||||
return 0;
|
||||
|
@ -381,12 +402,16 @@ int safe_atou8(const char *s, uint8_t *ret) {
|
|||
assert(s);
|
||||
assert(ret);
|
||||
|
||||
s += strspn(s, WHITESPACE);
|
||||
|
||||
errno = 0;
|
||||
l = strtoul(s, &x, 0);
|
||||
|
||||
if (!x || x == s || *x || errno)
|
||||
return errno > 0 ? -errno : -EINVAL;
|
||||
|
||||
if (errno != 0)
|
||||
return -errno;
|
||||
if (!x || x == s || *x)
|
||||
return -EINVAL;
|
||||
if (s[0] == '-')
|
||||
return -ERANGE;
|
||||
if ((unsigned long) (uint8_t) l != l)
|
||||
return -ERANGE;
|
||||
|
||||
|
@ -401,12 +426,16 @@ int safe_atou16(const char *s, uint16_t *ret) {
|
|||
assert(s);
|
||||
assert(ret);
|
||||
|
||||
s += strspn(s, WHITESPACE);
|
||||
|
||||
errno = 0;
|
||||
l = strtoul(s, &x, 0);
|
||||
|
||||
if (!x || x == s || *x || errno)
|
||||
return errno > 0 ? -errno : -EINVAL;
|
||||
|
||||
if (errno != 0)
|
||||
return -errno;
|
||||
if (!x || x == s || *x)
|
||||
return -EINVAL;
|
||||
if (s[0] == '-')
|
||||
return -ERANGE;
|
||||
if ((unsigned long) (uint16_t) l != l)
|
||||
return -ERANGE;
|
||||
|
||||
|
@ -423,10 +452,10 @@ int safe_atoi16(const char *s, int16_t *ret) {
|
|||
|
||||
errno = 0;
|
||||
l = strtol(s, &x, 0);
|
||||
|
||||
if (!x || x == s || *x || errno)
|
||||
return errno > 0 ? -errno : -EINVAL;
|
||||
|
||||
if (errno != 0)
|
||||
return -errno;
|
||||
if (!x || x == s || *x)
|
||||
return -EINVAL;
|
||||
if ((long) (int16_t) l != l)
|
||||
return -ERANGE;
|
||||
|
||||
|
@ -448,10 +477,13 @@ int safe_atod(const char *s, double *ret_d) {
|
|||
|
||||
errno = 0;
|
||||
d = strtod_l(s, &x, loc);
|
||||
|
||||
if (!x || x == s || *x || errno) {
|
||||
if (errno != 0) {
|
||||
freelocale(loc);
|
||||
return errno ? -errno : -EINVAL;
|
||||
return -errno;
|
||||
}
|
||||
if (!x || x == s || *x) {
|
||||
freelocale(loc);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
freelocale(loc);
|
||||
|
|
Loading…
Reference in a new issue