From 00e41888b09783acd7372c309360bf22f45bd3ef Mon Sep 17 00:00:00 2001 From: Anirudh Date: Wed, 24 Aug 2016 16:47:08 -0700 Subject: [PATCH] Fixed integer overflow bug in rate limiter. --- pkg/util/workqueue/default_rate_limiters.go | 9 ++++- .../workqueue/default_rate_limiters_test.go | 33 +++++++++++++++++++ 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/pkg/util/workqueue/default_rate_limiters.go b/pkg/util/workqueue/default_rate_limiters.go index cf3c4d94eac..8b281158147 100644 --- a/pkg/util/workqueue/default_rate_limiters.go +++ b/pkg/util/workqueue/default_rate_limiters.go @@ -90,9 +90,16 @@ func (r *ItemExponentialFailureRateLimiter) When(item interface{}) time.Duration r.failuresLock.Lock() defer r.failuresLock.Unlock() + exp := r.failures[item] r.failures[item] = r.failures[item] + 1 - calculated := r.baseDelay * time.Duration(math.Pow10(r.failures[item]-1)) + // The backoff is capped such that 'calculated' value never overflows. + backoff := float64(r.baseDelay.Nanoseconds()) * math.Pow10(exp) + if backoff > math.MaxInt64 { + return r.maxDelay + } + + calculated := time.Duration(backoff) if calculated > r.maxDelay { return r.maxDelay } diff --git a/pkg/util/workqueue/default_rate_limiters_test.go b/pkg/util/workqueue/default_rate_limiters_test.go index 3ce3144ff6d..e50cf453f03 100644 --- a/pkg/util/workqueue/default_rate_limiters_test.go +++ b/pkg/util/workqueue/default_rate_limiters_test.go @@ -63,6 +63,39 @@ func TestItemExponentialFailureRateLimiter(t *testing.T) { } +func TestItemExponentialFailureRateLimiterOverFlow(t *testing.T) { + limiter := NewItemExponentialFailureRateLimiter(1*time.Millisecond, 1000*time.Second) + for i := 0; i < 5; i++ { + limiter.When("one") + } + if e, a := 100000*time.Millisecond, limiter.When("one"); e != a { + t.Errorf("expected %v, got %v", e, a) + } + + for i := 0; i < 1000; i++ { + limiter.When("overflow1") + } + if e, a := 1000*time.Second, limiter.When("overflow1"); e != a { + t.Errorf("expected %v, got %v", e, a) + } + + limiter = NewItemExponentialFailureRateLimiter(1*time.Minute, 1000*time.Hour) + for i := 0; i < 2; i++ { + limiter.When("two") + } + if e, a := 100*time.Minute, limiter.When("two"); e != a { + t.Errorf("expected %v, got %v", e, a) + } + + for i := 0; i < 1000; i++ { + limiter.When("overflow2") + } + if e, a := 1000*time.Hour, limiter.When("overflow2"); e != a { + t.Errorf("expected %v, got %v", e, a) + } + +} + func TestItemFastSlowRateLimiter(t *testing.T) { limiter := NewItemFastSlowRateLimiter(5*time.Millisecond, 10*time.Second, 3)