From 9f9c8d63a5822378e18f3f8f188df21c6104e18e Mon Sep 17 00:00:00 2001 From: Jan Hubicka Date: Fri, 26 Sep 2025 12:39:07 +0200 Subject: [PATCH] Fix integer overflow in profile_count::probability_in This patch fixes integer overflow in profile_count::probability_in which happens for very large counts. This was probably not that common in practice until scaled AutoFDO profiles were intorduces. This was introduced as cut&paste from profile_probability implementation. I reviewed multiplicaitons in the file for safety and noticed that in some cases the code is over-protective. In profile_probability::operator/ we alrady scale that m_val <= other.m_val and thus we know result will be in the range 0...max_probability. In profile_probability::apply_scale we deal with 30bit value from profile_probability so no overflow can happen. gcc/ChangeLog: * profile-count.h (profile_probability::operator/): Do not cap twice. (profile_probability::operator/=): Likewise. (profile_probability::apply_scale): Do not watch for overflow. (profile_count::probability_in): Watch overflow. --- gcc/profile-count.h | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/gcc/profile-count.h b/gcc/profile-count.h index 65c4596a2b0..89746c6749f 100644 --- a/gcc/profile-count.h +++ b/gcc/profile-count.h @@ -450,9 +450,7 @@ public: else { gcc_checking_assert (other.m_val); - ret.m_val = MIN (RDIV ((uint64_t)m_val * max_probability, - other.m_val), - max_probability); + ret.m_val = RDIV ((uint64_t)m_val * max_probability, other.m_val); } ret.set_quality (MIN (MIN (quality (), other.quality ()), ADJUSTED)); return ret; @@ -480,9 +478,7 @@ public: else { gcc_checking_assert (other.m_val); - m_val = MIN (RDIV ((uint64_t)m_val * max_probability, - other.m_val), - max_probability); + m_val = RDIV ((uint64_t)m_val * max_probability, other.m_val); } set_quality (MIN (MIN (quality (), other.quality ()), ADJUSTED)); } @@ -576,9 +572,8 @@ public: gcc_checking_assert (den.m_val); profile_probability ret; - uint64_t val; - safe_scale_64bit (m_val, num.m_val, den.m_val, &val); - ret.m_val = MIN (val, max_probability); + ret.m_val = MIN (RDIV ((uint64_t)m_val * num.m_val, den.m_val), + max_probability); ret.set_quality (MIN (MIN (MIN (quality (), ADJUSTED), num.quality ()), den.quality ())); return ret; @@ -1331,8 +1326,14 @@ public: return ret; } else - ret.m_val = RDIV (m_val * profile_probability::max_probability, - overall.m_val); + { + gcc_checking_assert (overall.m_val); + uint64_t tmp; + safe_scale_64bit (m_val, profile_probability::max_probability, + overall.m_val, &tmp); + gcc_checking_assert (tmp <= profile_probability::max_probability); + ret.m_val = tmp; + } ret.set_quality (MIN (MAX (MIN (m_quality, overall.m_quality), GUESSED), ADJUSTED)); return ret; -- 2.47.3