mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-10 21:23:58 +01:00
Avoid divide by zero and NaNs in scale_array_elements_to_u64
Patch from teor; part of 13104
This commit is contained in:
parent
5126bc2ebd
commit
59f9a5c786
@ -1802,7 +1802,7 @@ scale_array_elements_to_u64(u64_dbl_t *entries, int n_entries,
|
|||||||
uint64_t *total_out)
|
uint64_t *total_out)
|
||||||
{
|
{
|
||||||
double total = 0.0;
|
double total = 0.0;
|
||||||
double scale_factor;
|
double scale_factor = 0.0;
|
||||||
int i;
|
int i;
|
||||||
/* big, but far away from overflowing an int64_t */
|
/* big, but far away from overflowing an int64_t */
|
||||||
#define SCALE_TO_U64_MAX (INT64_MAX / 4)
|
#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)
|
for (i = 0; i < n_entries; ++i)
|
||||||
total += entries[i].dbl;
|
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)
|
for (i = 0; i < n_entries; ++i)
|
||||||
entries[i].u64 = tor_llround(entries[i].dbl * scale_factor);
|
entries[i].u64 = tor_llround(entries[i].dbl * scale_factor);
|
||||||
|
@ -1749,10 +1749,37 @@ test_dir_scale_bw(void *testdata)
|
|||||||
tt_assert(total <= (U64_LITERAL(1)<<62));
|
tt_assert(total <= (U64_LITERAL(1)<<62));
|
||||||
|
|
||||||
for (i=0; i<8; ++i) {
|
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;
|
double ratio = ((double)vals[i].u64) / vals[2].u64;
|
||||||
tt_double_op(fabs(ratio - v[i]), <, .00001);
|
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:
|
done:
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user