Fix fixed integer arithmetics handling
authorHenning Rogge <henning.rogge@fkie.fraunhofer.de>
Tue, 29 May 2018 11:46:40 +0000 (13:46 +0200)
committerHenning Rogge <henning.rogge@fkie.fraunhofer.de>
Tue, 29 May 2018 11:46:40 +0000 (13:46 +0200)
include/oonf/libconfig/cfg_tobin.h
src/libcommon/isonumber.c
src/libconfig/cfg_help.c
src/libconfig/cfg_tobin.c
src/libconfig/cfg_validate.c
src/tests/common/test_common_isonumber.c

index 205aa8b..fd5ca0a 100644 (file)
@@ -16,7 +16,7 @@ EXPORT int cfg_tobin_strarray(void *reference, size_t bin_size, const struct con
 EXPORT int cfg_tobin_choice(void *reference, size_t bin_size, const struct const_strarray *value,
   const char *(*callback)(size_t idx, const void *ptr), size_t choices_count, const void *ptr);
 EXPORT int cfg_tobin_int(
-  void *reference, size_t bin_size, const struct const_strarray *value, int fractions, size_t int_size);
+  void *reference, size_t bin_size, const struct const_strarray *value, uint16_t fractions, size_t int_size);
 EXPORT int cfg_tobin_netaddr(void *reference, size_t bin_size, const struct const_strarray *value);
 EXPORT int cfg_tobin_acl(void *reference, size_t bin_size, const struct const_strarray *value);
 EXPORT int cfg_tobin_bitmap256(void *reference, size_t bin_size, const struct const_strarray *value);
index 91c2a6d..0af6fe4 100644 (file)
@@ -186,10 +186,9 @@ isonumber_to_u64(uint64_t *dst, const char *iso, uint64_t scaling) {
       next++;
     }
   }
-  while (fraction_scale < scaling && (scaling % 10) == 0) {
+  while (fraction_scale < scaling) {
     num *= 10;
     fraction_scale *= 10;
-    scaling /= 10;
   }
 
   /* handle spaces */
@@ -215,7 +214,7 @@ isonumber_to_u64(uint64_t *dst, const char *iso, uint64_t scaling) {
     }
   }
 
-  while (fraction_scale > scaling) {
+  while (fraction_scale > scaling && fraction_scale >= 1000) {
     fraction_scale /= 1000;
     if (factor > 1) {
       factor /= 1000;
@@ -225,12 +224,12 @@ isonumber_to_u64(uint64_t *dst, const char *iso, uint64_t scaling) {
     }
   }
 
-  if (num > UINT64_MAX / (factor*scaling)) {
+  if (num > UINT64_MAX / factor) {
     /* this would be an integer overflow */
     return -1;
   }
 
-  *dst = num * factor * scaling;
+  *dst = num * factor * scaling / fraction_scale;
   return 0;
 }
 
index ea3c7d8..f967cee 100644 (file)
@@ -117,26 +117,29 @@ void
 cfg_help_int(struct autobuf *out, int64_t min, int64_t max, uint16_t bytelen, uint16_t fraction) {
   struct isonumber_str hbuf1, hbuf2;
   int64_t min64, max64;
+  uint64_t j, scaling;
 
   min64 = INT64_MIN >> (8 * (8 - bytelen));
   max64 = INT64_MAX >> (8 * (8 - bytelen));
 
+  for (j = 0, scaling = 1; j < fraction; j++, scaling*=10);
+
   /* get string representation of min/max */
-  isonumber_from_s64(&hbuf1, min, "", fraction, true);
-  isonumber_from_s64(&hbuf2, max, "", fraction, true);
+  isonumber_from_s64(&hbuf1, min, "", scaling, true);
+  isonumber_from_s64(&hbuf2, max, "", scaling, true);
 
   if (min > min64) {
     if (max < max64) {
       cfg_append_printable_line(out,
         CFG_HELP_INDENT_PREFIX "Parameter must be a %d-byte fractional integer"
                                " between %s and %s with a maximum of %d fractional digits",
-        bytelen, hbuf1.buf, hbuf2.buf, fraction);
+        bytelen, hbuf1.buf, hbuf2.buf, fraction );
     }
     else {
       cfg_append_printable_line(out,
         CFG_HELP_INDENT_PREFIX "Parameter must be a %d-byte fractional integer"
                                " larger or equal than %s with a maximum of %d fractional digits",
-        bytelen, hbuf1.buf, fraction);
+        bytelen, hbuf1.buf, fraction );
     }
   }
   else {
@@ -144,13 +147,13 @@ cfg_help_int(struct autobuf *out, int64_t min, int64_t max, uint16_t bytelen, ui
       cfg_append_printable_line(out,
         CFG_HELP_INDENT_PREFIX "Parameter must be a %d-byte fractional integer"
                                " smaller or equal than %s with a maximum of %d fractional digits",
-        bytelen, hbuf2.buf, fraction);
+        bytelen, hbuf2.buf, fraction );
     }
     else {
       cfg_append_printable_line(out,
         CFG_HELP_INDENT_PREFIX "Parameter must be a %d-byte signed integer"
                                " with a maximum of %d fractional digits",
-        bytelen, fraction);
+        bytelen, fraction );
     }
   }
 }
index b88047f..e88c026 100644 (file)
@@ -100,21 +100,22 @@ cfg_tobin_choice(void *reference, size_t bin_size, const struct const_strarray *
  * @param reference pointer to binary output buffer.
  * @param bin_size size of reference memory
  * @param value pointer to value of configuration entry.
- * @param fractions number of fractional digits
+ * @param fraction number of fractional digits
  * @param int_size size of signed integer to read
  * @return 0 if conversion succeeded, -1 otherwise.
  */
 int
-cfg_tobin_int(void *reference, size_t bin_size, const struct const_strarray *value, int fractions, size_t int_size) {
+cfg_tobin_int(void *reference, size_t bin_size, const struct const_strarray *value, uint16_t fraction, size_t int_size) {
   int64_t i;
   int result;
-  uint64_t scaling;
+  uint64_t j, scaling;
 
   if (bin_size != int_size) {
     return -1;
   }
 
-  for (scaling = 1; fractions > 0; fractions--, scaling*=10);
+  for (j = 0, scaling = 1; j < fraction; j++, scaling*=10);
+
   result = isonumber_to_s64(&i, strarray_get_first_c(value), scaling);
   if (result == 0) {
     switch (int_size) {
index d3ee669..2bb17a3 100644 (file)
@@ -147,10 +147,10 @@ int
 cfg_validate_int(struct autobuf *out, const char *section_name, const char *entry_name, const char *value, int64_t min,
   int64_t max, uint16_t bytelen, uint16_t fraction) {
   int64_t i, min64, max64;
-  uint64_t scaling;
+  uint64_t j, scaling;
   struct isonumber_str hbuf;
 
-  for (scaling = 1; fraction > 0; fraction--, scaling*=10);
+  for (j = 0, scaling = 1; j < fraction; j++, scaling*=10);
   if (isonumber_to_s64(&i, value, scaling)) {
     if (fraction) {
       cfg_append_printable_line(out,
index 86551ab..d2cb3bd 100644 (file)
@@ -93,9 +93,9 @@ test_str_from_isonumber_u64(void) {
 static void
 test_isonumber_to_u64_to_string(void) {
   static const char *tests[] = {
-      "1k", "1.024k", "1M", "1.024M", "1.023k"
+      "1.0", "1k", "1.024k", "1M", "1.024M", "1.023k"
   };
-  static uint64_t results[] = { 1000, 1024, 1000*1000, 1000*1024, 1023 };
+  static uint64_t results[] = { 1, 1000, 1024, 1000*1000, 1000*1024, 1023 };
 
   size_t i;
   int64_t scaling;