parse_bytes prevent out of range value 36/226436/4
authorAgnieszka Baumann <a.baumann@samsung.com>
Mon, 2 Mar 2020 12:16:15 +0000 (13:16 +0100)
committerAgnieszka Baumann <a.baumann@samsung.com>
Wed, 4 Mar 2020 09:32:08 +0000 (10:32 +0100)
Change-Id: I65fd241855fa480ffea53b94f6914c925fde9cda

src/common/util.c

index 9dde4b3..c1ae720 100644 (file)
 #include <assert.h>
 #include <sys/types.h>
 #include <sys/wait.h>
+#include <stdlib.h>
 
 #include "util.h"
 #include "trace.h"
 #include "resourced.h"
 
+#define GIGA_SHIFT 30
+#define MEGA_SHIFT 20
+#define KILO_SHIFT 10
+
 static int parent(pid_t pid)
 {
        int status;
@@ -124,9 +129,10 @@ int parse_boolean(const char *v)
 int parse_bytes(const char *b, size_t *s)
 {
        _cleanup_free_ char *num = NULL;
-       size_t len, num_l, unit_l;
+       size_t len, num_l, unit_l, r;
 
        assert(b);
+       assert(s);
 
        len = strlen(b);
 
@@ -145,22 +151,34 @@ int parse_bytes(const char *b, size_t *s)
        if (!num)
                return -ENOMEM;
 
+       errno = 0;
+       r = strtol(num, NULL, 10);
+       if (errno != 0)
+               return -errno;
+
+       int shift;
+
        switch (b[len - 1]) {
        case 'G':
-               *s = atoi(num) << 30;
+               shift = GIGA_SHIFT;
                break;
        case 'M':
-               *s = atoi(num) << 20;
+               shift = MEGA_SHIFT;
                break;
        case 'K':
-               *s = atoi(num) << 10;
+               shift = KILO_SHIFT;
                break;
        case 'B':
        default:
-               *s = atoi(num);
-               break;
+               *s = r;
+               return 0;
        }
 
+       /* Prevent overflow */
+       if (r >= (1 << ((CHAR_BIT * sizeof r) - shift)))
+               return -ERANGE;
+       *s = r << shift;
+
        return 0;
 }