From 6fd343ab08d489034e4a69742dbe0c3e2b700620 Mon Sep 17 00:00:00 2001 From: Josh Rickmar Date: Tue, 15 Oct 2024 16:06:44 +0000 Subject: [PATCH] mixclient: Avoid jitter calculation panic rand.Duration may not be called with a negative or zero upper bound, but this was seen to occur in (*Client).prDelay(). Two notable possible bugs stood out. First, if sendBefore is exactly equal to now, then it will not be incremented by another epoch duration, leading to a potential invalid rand.Duration parameter. This is corrected by also checking for the times equaling exactly. Second, time.Until() causes an additional call to time.Now(), which we have already fetched and all calculations must be based on it. If sendBefore.Sub(now) is an extremely small value, it is possible that time.Until(sendBefore) now returns a small negative or zero duration. This is corrected by replacing the time.Until call with sendBefore.Sub(now). --- mixing/mixclient/client.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mixing/mixclient/client.go b/mixing/mixclient/client.go index ff6fac9f8..00baa5355 100644 --- a/mixing/mixclient/client.go +++ b/mixing/mixclient/client.go @@ -516,11 +516,11 @@ func (c *Client) prDelay(ctx context.Context, p *peer) error { sendBefore := epoch.Add(-timeoutDuration - maxJitter) sendAfter := epoch.Add(timeoutDuration) var wait time.Duration - if now.After(sendBefore) { + if !now.Before(sendBefore) { wait = sendAfter.Sub(now) sendBefore = sendBefore.Add(c.epoch) } - wait += p.msgJitter() + rand.Duration(time.Until(sendBefore)) + wait += p.msgJitter() + rand.Duration(sendBefore.Sub(now)) timer := time.NewTimer(wait) select { case <-ctx.Done():