diff options
author | Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> | 2013-06-05 19:33:45 -0400 |
---|---|---|
committer | Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> | 2013-06-10 10:10:06 -0400 |
commit | b32ff512191bf873266ee8067f6f6c8a30c96a5e (patch) | |
tree | ec7442f8e8967af14804e673adec4f4e0deb5c38 /src/shared/util.c | |
parent | 3001c74580c1713bd634990a0b2ab351fdec7a98 (diff) |
Properly check for overflow in offsets
Diffstat (limited to 'src/shared/util.c')
-rw-r--r-- | src/shared/util.c | 18 |
1 files changed, 14 insertions, 4 deletions
diff --git a/src/shared/util.c b/src/shared/util.c index d0bbf78bf3..17928ec36e 100644 --- a/src/shared/util.c +++ b/src/shared/util.c @@ -2261,7 +2261,7 @@ ssize_t loop_write(int fd, const void *buf, size_t nbytes, bool do_poll) { int parse_bytes(const char *t, off_t *bytes) { static const struct { const char *suffix; - off_t factor; + unsigned long long factor; } table[] = { { "B", 1 }, { "K", 1024ULL }, @@ -2274,7 +2274,7 @@ int parse_bytes(const char *t, off_t *bytes) { }; const char *p; - off_t r = 0; + unsigned long long r = 0; assert(t); assert(bytes); @@ -2301,7 +2301,17 @@ int parse_bytes(const char *t, off_t *bytes) { for (i = 0; i < ELEMENTSOF(table); i++) if (startswith(e, table[i].suffix)) { - r += (off_t) l * table[i].factor; + unsigned long long tmp; + if ((unsigned long long) l > ULLONG_MAX / table[i].factor) + return -ERANGE; + tmp = l * table[i].factor; + if (tmp > ULLONG_MAX - r) + return -ERANGE; + + r += tmp; + if ((unsigned long long) (off_t) r != r) + return -ERANGE; + p = e + strlen(table[i].suffix); break; } @@ -2309,7 +2319,7 @@ int parse_bytes(const char *t, off_t *bytes) { if (i >= ELEMENTSOF(table)) return -EINVAL; - } while (*p != 0); + } while (*p); *bytes = r; |