From bdd173f22270ea0d40fbd4469a5146b1f46d432d Mon Sep 17 00:00:00 2001 From: Jyrki Vesterinen Date: Sun, 26 Feb 2017 18:13:25 +0200 Subject: [PATCH] Fix bug #25538: Monte Carlo damage prediction relies on UB IEEE 754 specifies that dividing a positive number with zero yields positive infinity, but the C++ language doesn't guarantee IEEE 754 semantics. As a result, UBSan complains about floating-point division by zero. Wesnoth requires IEEE 754 anyway, but it's still good to get rid of the UBSan warning. The code now avoids the division if the divisor is zero. --- src/attack_prediction.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/attack_prediction.cpp b/src/attack_prediction.cpp index f763faa6adb3..cdf00d9d7309 100644 --- a/src/attack_prediction.cpp +++ b/src/attack_prediction.cpp @@ -1278,10 +1278,10 @@ monte_carlo_combat_matrix::monte_carlo_combat_matrix(unsigned int a_max_hp, unsi a_split_(a_split), b_split_(b_split), rounds_(rounds), a_hit_chance_(a_hit_chance), b_hit_chance_(b_hit_chance), a_initially_slowed_chance_(a_initially_slowed_chance), b_initially_slowed_chance_(b_initially_slowed_chance) { - scale_probabilities(a_summary[0], a_initial_, 1.0 / (1.0 - a_initially_slowed_chance), a_hp); - scale_probabilities(a_summary[1], a_initial_slowed_, 1.0 / a_initially_slowed_chance, a_hp); - scale_probabilities(b_summary[0], b_initial_, 1.0 / (1.0 - b_initially_slowed_chance), b_hp); - scale_probabilities(b_summary[1], b_initial_slowed_, 1.0 / b_initially_slowed_chance, b_hp); + scale_probabilities(a_summary[0], a_initial_, 1.0 - a_initially_slowed_chance, a_hp); + scale_probabilities(a_summary[1], a_initial_slowed_, a_initially_slowed_chance, a_hp); + scale_probabilities(b_summary[0], b_initial_, 1.0 - b_initially_slowed_chance, b_hp); + scale_probabilities(b_summary[1], b_initial_slowed_, b_initially_slowed_chance, b_hp); clear(); } @@ -1435,9 +1435,9 @@ unsigned int monte_carlo_combat_matrix::calc_blows_b(unsigned int b_hp) const return it->strikes; } -void monte_carlo_combat_matrix::scale_probabilities(const std::vector& source, std::vector& target, double multiplier, unsigned int singular_hp) +void monte_carlo_combat_matrix::scale_probabilities(const std::vector& source, std::vector& target, double divisor, unsigned int singular_hp) { - if (std::isinf(multiplier)) + if (divisor == 0.0) { // Happens if the "target" HP distribution vector isn't used, // in which case it's not necessary to scale the probabilities. @@ -1451,7 +1451,7 @@ void monte_carlo_combat_matrix::scale_probabilities(const std::vector& s } else { - std::transform(source.begin(), source.end(), std::back_inserter(target), [=](double prob){ return multiplier * prob; }); + std::transform(source.begin(), source.end(), std::back_inserter(target), [=](double prob){ return prob / divisor; }); } assert(std::abs(std::accumulate(target.begin(), target.end(), 0.0) - 1.0) < 0.001);