Message ID | 20241203162525.75156-1-abelova@astralinux.ru (mailing list archive) |
---|---|
State | New |
Headers | show |
Series | hw/timer/nrf51_timer: prevent integer overflow | expand |
On Tue, 3 Dec 2024 at 16:25, Anastasia Belova <abelova@astralinux.ru> wrote: > > Both counter and tick are uint32_t and the result > of their addition may not fit this type. Add > explicit casting to uint64_t. > > Found by Linux Verification Center (linuxtesting.org) with SVACE. > > Fixes: c5a4829c08 ("hw/timer/nrf51_timer: Add nRF51 Timer peripheral") > Signed-off-by: Anastasia Belova <abelova@astralinux.ru> > --- > hw/timer/nrf51_timer.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/hw/timer/nrf51_timer.c b/hw/timer/nrf51_timer.c > index 35b0e62d5b..b5ff235eb8 100644 > --- a/hw/timer/nrf51_timer.c > +++ b/hw/timer/nrf51_timer.c > @@ -44,7 +44,7 @@ static uint32_t update_counter(NRF51TimerState *s, int64_t now) > { > uint32_t ticks = ns_to_ticks(s, now - s->update_counter_ns); > > - s->counter = (s->counter + ticks) % BIT(bitwidths[s->bitmode]); > + s->counter = ((uint64_t)s->counter + ticks) % BIT(bitwidths[s->bitmode]); Can you explain when adding the cast makes a difference? Since s->counter is 32 bits and ticks is 32 bits and the RHS of the % is a power of 2, it's not clear to me that keeping the top 32 bits in the addition and then discarding it after the % is any different from only taking the bottom 32 bits of the addition. thanks -- PMM
On 12/3/24 7:46 PM, Peter Maydell wrote: > On Tue, 3 Dec 2024 at 16:25, Anastasia Belova <abelova@astralinux.ru> wrote: >> Both counter and tick are uint32_t and the result >> of their addition may not fit this type. Add >> explicit casting to uint64_t. >> >> Found by Linux Verification Center (linuxtesting.org) with SVACE. >> >> Fixes: c5a4829c08 ("hw/timer/nrf51_timer: Add nRF51 Timer peripheral") >> Signed-off-by: Anastasia Belova <abelova@astralinux.ru> >> --- >> hw/timer/nrf51_timer.c | 2 +- >> 1 file changed, 1 insertion(+), 1 deletion(-) >> >> diff --git a/hw/timer/nrf51_timer.c b/hw/timer/nrf51_timer.c >> index 35b0e62d5b..b5ff235eb8 100644 >> --- a/hw/timer/nrf51_timer.c >> +++ b/hw/timer/nrf51_timer.c >> @@ -44,7 +44,7 @@ static uint32_t update_counter(NRF51TimerState *s, int64_t now) >> { >> uint32_t ticks = ns_to_ticks(s, now - s->update_counter_ns); >> >> - s->counter = (s->counter + ticks) % BIT(bitwidths[s->bitmode]); >> + s->counter = ((uint64_t)s->counter + ticks) % BIT(bitwidths[s->bitmode]); > Can you explain when adding the cast makes a difference? > Since s->counter is 32 bits and ticks is 32 bits and > the RHS of the % is a power of 2, it's not clear to > me that keeping the top 32 bits in the addition and then > discarding it after the % is any different from only > taking the bottom 32 bits of the addition. > You're right. I was sure this situation invokes UB. Thanks for your patience, Anastasia Belova
diff --git a/hw/timer/nrf51_timer.c b/hw/timer/nrf51_timer.c index 35b0e62d5b..b5ff235eb8 100644 --- a/hw/timer/nrf51_timer.c +++ b/hw/timer/nrf51_timer.c @@ -44,7 +44,7 @@ static uint32_t update_counter(NRF51TimerState *s, int64_t now) { uint32_t ticks = ns_to_ticks(s, now - s->update_counter_ns); - s->counter = (s->counter + ticks) % BIT(bitwidths[s->bitmode]); + s->counter = ((uint64_t)s->counter + ticks) % BIT(bitwidths[s->bitmode]); /* * Only advance the sync time to the timestamp of the last tick, * not all the way to 'now', so we don't lose time if we do
Both counter and tick are uint32_t and the result of their addition may not fit this type. Add explicit casting to uint64_t. Found by Linux Verification Center (linuxtesting.org) with SVACE. Fixes: c5a4829c08 ("hw/timer/nrf51_timer: Add nRF51 Timer peripheral") Signed-off-by: Anastasia Belova <abelova@astralinux.ru> --- hw/timer/nrf51_timer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)