]> git.ipfire.org Git - thirdparty/libbsd.git/commitdiff
Fix dehumanize_number() to correctly detect overflows
authorGuillem Jover <guillem@hadrons.org>
Sun, 14 Jul 2013 23:44:30 +0000 (01:44 +0200)
committerGuillem Jover <guillem@hadrons.org>
Mon, 21 Oct 2013 03:29:37 +0000 (05:29 +0200)
Do not allow numbers greated than INT64_MAX and smaller than INT64_MIN.
Clarify the positive sign value by prefixing it with an explicit +.

Fixes: https://bugs.freedesktop.org/show_bug.cgi?id=66909
src/dehumanize_number.c
test/humanize.c

index 640f1fbd96c5b1af766684f0ce7782eb3df3be2e..632bf1d81a305b2db9ab9d1c82f6a4f658bbf59f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright © 2012 Guillem Jover <guillem@hadrons.org>
+ * Copyright © 2012-2013 Guillem Jover <guillem@hadrons.org>
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -35,8 +35,8 @@
 int
 dehumanize_number(const char *buf, int64_t *num)
 {
-       uint64_t rval;
-       int sign = 1;
+       uint64_t rval, rmax;
+       int sign = +1;
        int rc;
 
        /* The current expand_number() implementation uses bit shifts, so
@@ -52,7 +52,13 @@ dehumanize_number(const char *buf, int64_t *num)
        rc = expand_number(buf, &rval);
        if (rc < 0)
                return rc;
-       if (rval == UINT64_MAX && sign == -1) {
+
+       /* The sign has been stripped, so rval has the absolute value.
+        * Error out, regardless of the sign, if rval is greater than
+        * abs(INT64_MIN) (== INT64_MAX + 1), or if the sign is positive
+        * and the value has overflown by one (INT64_MAX + 1). */
+       rmax = INT64_MAX + 1ULL;
+       if (rval > rmax || (rval == rmax && sign == +1)) {
                errno = ERANGE;
                return -1;
        }
index 0e8f0cf1a4751305bef81e33172cba3c8e757de4..59e4cde86919036d36817226f8b523b3ae18bbe9 100644 (file)
@@ -25,6 +25,7 @@
  */
 
 #include <assert.h>
+#include <errno.h>
 #include <stdlib.h>
 
 int
@@ -60,5 +61,17 @@ main(int argc, char **argv)
        assert(dehumanize_number("-3G", &val) == 0);
        assert(val == -3221225472LL);
 
+       assert(dehumanize_number("9223372036854775807", &val) == 0);
+       assert(val == INT64_MAX);
+
+       assert(dehumanize_number("9223372036854775808", &val) == -1);
+       assert(errno == ERANGE);
+
+       assert(dehumanize_number("-9223372036854775808", &val) == 0);
+       assert(val == INT64_MIN);
+
+       assert(dehumanize_number("-9223372036854775809", &val) == -1);
+       assert(errno == ERANGE);
+
        return 0;
 }