Browse Source

Detect overflow or underflow on double config values.

Any floating point value too positive or negative to distinguish
from +/-Inf, or too small to distinguish from +/-0, is an
over/underflow.
Nick Mathewson 4 years ago
parent
commit
bfc5f09979
2 changed files with 23 additions and 2 deletions
  1. 11 2
      src/lib/confmgt/type_defs.c
  2. 12 0
      src/test/test_confparse.c

+ 11 - 2
src/lib/confmgt/type_defs.c

@@ -37,6 +37,7 @@
 
 #include <stddef.h>
 #include <string.h>
+#include <errno.h>
 
 //////
 // CONFIG_TYPE_STRING
@@ -284,15 +285,23 @@ double_parse(void *target, const char *value, char **errmsg,
   (void)errmsg;
   double *v = (double*)target;
   char *endptr=NULL;
+  errno = 0;
   *v = strtod(value, &endptr);
   if (endptr == value || *endptr != '\0') {
     // Either there are no converted characters, or there were some characters
     // that didn't get converted.
     tor_asprintf(errmsg, "Could not convert %s to a number.", escaped(value));
     return -1;
-  } else {
-    return 0;
   }
+  if (errno == ERANGE) {
+    // strtod will set errno to ERANGE on underflow or overflow.
+    bool underflow = -.00001 < *v && *v < .00001;
+    tor_asprintf(errmsg,
+                 "%s is too %s to express as a floating-point number.",
+                 escaped(value), underflow ? "small" : "large");
+    return -1;
+  }
+  return 0;
 }
 
 static char *

+ 12 - 0
src/test/test_confparse.c

@@ -490,6 +490,14 @@ static const badval_test_t bv_negint = { "pos -10\n", "out of bounds" };
 static const badval_test_t bv_badu64 = { "u64 u64\n", "malformed" };
 static const badval_test_t bv_dbl1 = { "dbl xxx\n", "Could not convert" };
 static const badval_test_t bv_dbl2 = { "dbl 1.0 xx\n", "Could not convert" };
+static const badval_test_t bv_dbl3 = {
+   "dbl 1e-10000\n", "too small to express" };
+static const badval_test_t bv_dbl4 = {
+   "dbl 1e1000\n", "too large to express" };
+static const badval_test_t bv_dbl5 = {
+   "dbl -1e-10000\n", "too small to express" };
+static const badval_test_t bv_dbl6 = {
+   "dbl -1e1000\n", "too large to express" };
 static const badval_test_t bv_badcsvi1 =
   { "csv_interval 10 wl\n", "malformed" };
 static const badval_test_t bv_badcsvi2 =
@@ -1049,6 +1057,10 @@ struct testcase_t confparse_tests[] = {
   BADVAL_TEST(badu64),
   BADVAL_TEST(dbl1),
   BADVAL_TEST(dbl2),
+  BADVAL_TEST(dbl3),
+  BADVAL_TEST(dbl4),
+  BADVAL_TEST(dbl5),
+  BADVAL_TEST(dbl6),
   BADVAL_TEST(badcsvi1),
   BADVAL_TEST(badcsvi2),
   BADVAL_TEST(nonoption),