| From b383b32717b43fc6cc7346fde0b8e3f0c46be365 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Thu, 30 Jan 2025 09:00:34 +0000 |
| Subject: power: supply: da9150-fg: fix potential overflow |
| |
| From: Andrey Vatoropin <a.vatoropin@crpt.ru> |
| |
| [ Upstream commit 3fb3cb4350befc4f901c54e0cb4a2a47b1302e08 ] |
| |
| Size of variable sd_gain equals four bytes - DA9150_QIF_SD_GAIN_SIZE. |
| Size of variable shunt_val equals two bytes - DA9150_QIF_SHUNT_VAL_SIZE. |
| |
| The expression sd_gain * shunt_val is currently being evaluated using |
| 32-bit arithmetic. So during the multiplication an overflow may occur. |
| |
| As the value of type 'u64' is used as storage for the eventual result, put |
| ULL variable at the first position of each expression in order to give the |
| compiler complete information about the proper arithmetic to use. According |
| to C99 the guaranteed width for a variable of type 'unsigned long long' >= |
| 64 bits. |
| |
| Remove the explicit cast to u64 as it is meaningless. |
| |
| Just for the sake of consistency, perform the similar trick with another |
| expression concerning 'iavg'. |
| |
| Found by Linux Verification Center (linuxtesting.org) with SVACE. |
| |
| Fixes: a419b4fd9138 ("power: Add support for DA9150 Fuel-Gauge") |
| Signed-off-by: Andrey Vatoropin <a.vatoropin@crpt.ru> |
| Link: https://lore.kernel.org/r/20250130090030.53422-1-a.vatoropin@crpt.ru |
| Signed-off-by: Sebastian Reichel <sebastian.reichel@collabora.com> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| drivers/power/supply/da9150-fg.c | 4 ++-- |
| 1 file changed, 2 insertions(+), 2 deletions(-) |
| |
| diff --git a/drivers/power/supply/da9150-fg.c b/drivers/power/supply/da9150-fg.c |
| index 6e367826aae92..d5e1fbac87f22 100644 |
| --- a/drivers/power/supply/da9150-fg.c |
| +++ b/drivers/power/supply/da9150-fg.c |
| @@ -247,9 +247,9 @@ static int da9150_fg_current_avg(struct da9150_fg *fg, |
| DA9150_QIF_SD_GAIN_SIZE); |
| da9150_fg_read_sync_end(fg); |
| |
| - div = (u64) (sd_gain * shunt_val * 65536ULL); |
| + div = 65536ULL * sd_gain * shunt_val; |
| do_div(div, 1000000); |
| - res = (u64) (iavg * 1000000ULL); |
| + res = 1000000ULL * iavg; |
| do_div(res, div); |
| |
| val->intval = (int) res; |
| -- |
| 2.39.5 |
| |