mirror of
https://github.com/systemd/systemd.git
synced 2024-11-02 10:51:20 +03:00
Properly check for overflow in offsets
This commit is contained in:
parent
3001c74580
commit
b32ff51219
@ -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;
|
||||
|
||||
|
@ -439,6 +439,44 @@ static void test_protect_errno(void) {
|
||||
assert(errno == 12);
|
||||
}
|
||||
|
||||
static void test_parse_bytes(void) {
|
||||
off_t bytes;
|
||||
|
||||
assert_se(parse_bytes("111", &bytes) == 0);
|
||||
assert_se(bytes == 111);
|
||||
|
||||
assert_se(parse_bytes(" 112 B", &bytes) == 0);
|
||||
assert_se(bytes == 112);
|
||||
|
||||
assert_se(parse_bytes("3 K", &bytes) == 0);
|
||||
assert_se(bytes == 3*1024);
|
||||
|
||||
assert_se(parse_bytes(" 4 M 11K", &bytes) == 0);
|
||||
assert_se(bytes == 4*1024*1024 + 11 * 1024);
|
||||
|
||||
assert_se(parse_bytes("3B3G", &bytes) == 0);
|
||||
assert_se(bytes == 3ULL*1024*1024*1024 + 3);
|
||||
|
||||
assert_se(parse_bytes("3B3G4T", &bytes) == 0);
|
||||
assert_se(bytes == (4ULL*1024 + 3)*1024*1024*1024 + 3);
|
||||
|
||||
assert_se(parse_bytes("12P", &bytes) == 0);
|
||||
assert_se(bytes == 12ULL * 1024*1024*1024*1024*1024);
|
||||
|
||||
assert_se(parse_bytes("3E 2P", &bytes) == 0);
|
||||
assert_se(bytes == (3 * 1024 + 2ULL) * 1024*1024*1024*1024*1024);
|
||||
|
||||
assert_se(parse_bytes("12X", &bytes) == -EINVAL);
|
||||
|
||||
assert_se(parse_bytes("1024E", &bytes) == -ERANGE);
|
||||
assert_se(parse_bytes("-1", &bytes) == -ERANGE);
|
||||
assert_se(parse_bytes("-1024E", &bytes) == -ERANGE);
|
||||
|
||||
assert_se(parse_bytes("-1024P", &bytes) == -ERANGE);
|
||||
|
||||
assert_se(parse_bytes("-10B 20K", &bytes) == -ERANGE);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
test_streq_ptr();
|
||||
test_first_word();
|
||||
@ -467,6 +505,7 @@ int main(int argc, char *argv[]) {
|
||||
test_u64log2();
|
||||
test_get_process_comm();
|
||||
test_protect_errno();
|
||||
test_parse_bytes();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user