From 59f9a5c78695213442599e8f2e8a535e8a9cc666 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Wed, 10 Sep 2014 23:59:21 -0400 Subject: [PATCH] Avoid divide by zero and NaNs in scale_array_elements_to_u64 Patch from teor; part of 13104 --- src/or/routerlist.c | 5 +++-- src/test/test_dir.c | 27 +++++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/src/or/routerlist.c b/src/or/routerlist.c index 32cbe19379..0df411b822 100644 --- a/src/or/routerlist.c +++ b/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); diff --git a/src/test/test_dir.c b/src/test/test_dir.c index c03b63be27..1b56bcdd3d 100644 --- a/src/test/test_dir.c +++ b/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: ; }