Quellcode durchsuchen

Avoid divide by zero and NaNs in scale_array_elements_to_u64

Patch from teor; part of 13104
Nick Mathewson vor 10 Jahren
Ursprung
Commit
59f9a5c786
2 geänderte Dateien mit 30 neuen und 2 gelöschten Zeilen
  1. 3 2
      src/or/routerlist.c
  2. 27 0
      src/test/test_dir.c

+ 3 - 2
src/or/routerlist.c

@@ -1802,7 +1802,7 @@ scale_array_elements_to_u64(u64_dbl_t *entries, int n_entries,
                             uint64_t *total_out)
 {
   double total = 0.0;
-  double scale_factor;
+  double scale_factor = 0.0;
   int i;
   /* big, but far away from overflowing an int64_t */
 #define SCALE_TO_U64_MAX (INT64_MAX / 4)
@@ -1810,7 +1810,8 @@ scale_array_elements_to_u64(u64_dbl_t *entries, int n_entries,
   for (i = 0; i < n_entries; ++i)
     total += entries[i].dbl;
 
-  scale_factor = SCALE_TO_U64_MAX / total;
+  if (total > 0.0)
+    scale_factor = SCALE_TO_U64_MAX / total;
 
   for (i = 0; i < n_entries; ++i)
     entries[i].u64 = tor_llround(entries[i].dbl * scale_factor);

+ 27 - 0
src/test/test_dir.c

@@ -1749,10 +1749,37 @@ test_dir_scale_bw(void *testdata)
   tt_assert(total <= (U64_LITERAL(1)<<62));
 
   for (i=0; i<8; ++i) {
+    /* vals[2].u64 is the scaled value of 1.0 */
     double ratio = ((double)vals[i].u64) / vals[2].u64;
     tt_double_op(fabs(ratio - v[i]), <, .00001);
   }
 
+  /* test handling of no entries */
+  total = 1;
+  scale_array_elements_to_u64(vals, 0, &total);
+  tt_assert(total == 0);
+
+  /* make sure we don't read the array when we have no entries
+   * may require compiler flags to catch NULL dereferences */
+  total = 1;
+  scale_array_elements_to_u64(NULL, 0, &total);
+  tt_assert(total == 0);
+
+  scale_array_elements_to_u64(NULL, 0, NULL);
+
+  /* test handling of zero totals */
+  total = 1;
+  vals[0].dbl = 0.0;
+  scale_array_elements_to_u64(vals, 1, &total);
+  tt_assert(total == 0);
+  tt_assert(vals[0].u64 == 0);
+
+  vals[0].dbl = 0.0;
+  vals[1].dbl = 0.0;
+  scale_array_elements_to_u64(vals, 2, NULL);
+  tt_assert(vals[0].u64 == 0);
+  tt_assert(vals[1].u64 == 0);
+
  done:
   ;
 }