chiark / gitweb /
Properly check for overflow in offsets
[elogind.git] / src / shared / util.c
index d0bbf78bf371cc2340bbb7952193df5bdda12c20..17928ec36ee287c4f2ffb2e9ef541cc3eeee5cf3 100644 (file)
@@ -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;