diff --git a/utils/consts.go b/utils/consts.go index 8c93fbb9c..d09b8e813 100644 --- a/utils/consts.go +++ b/utils/consts.go @@ -2669,6 +2669,15 @@ const ( ToNearestTowardZero = "*toNearestTowardZero" ) +// Go type limits +const ( + AbsoluteMaxUint = ^uint(0) + AbsoluteMinUint = 0 + AbsoluteMaxInt = int(AbsoluteMaxUint >> 1) + AbsoluteMinInt = -AbsoluteMaxInt - 1 + AbsoluteMaxDuration = time.Duration(AbsoluteMaxInt) +) + func buildCacheInstRevPrefixes() { CachePrefixToInstance = make(map[string]string) for k, v := range CacheInstanceToPrefix { diff --git a/utils/coreutils.go b/utils/coreutils.go index 60312877d..71be8aef4 100644 --- a/utils/coreutils.go +++ b/utils/coreutils.go @@ -424,11 +424,13 @@ func copyFile(rc io.ReadCloser, path string, fm os.FileMode) (err error) { return } -// Fib returns successive Fibonacci numbers +// Fib returns successive Fibonacci numbers. func Fib() func() int { a, b := 0, 1 return func() int { - a, b = b, a+b + if b > 0 { + a, b = b, a+b // only increment Fibonacci numbers while b doesn't overflow + } return a } } @@ -438,7 +440,12 @@ func Fib() func() int { func FibDuration(durationUnit, maxDuration time.Duration) func() time.Duration { fib := Fib() return func() time.Duration { - fibNrAsDuration := time.Duration(fib()) * durationUnit + fibNrAsDuration := time.Duration(fib()) + if fibNrAsDuration > (AbsoluteMaxDuration / durationUnit) { // check if the current fibonacci nr. in the sequence would exceed the absolute maximum duration if multiplied by the duration unit value + fibNrAsDuration = AbsoluteMaxDuration + } else { + fibNrAsDuration *= durationUnit + } if maxDuration > 0 && maxDuration < fibNrAsDuration { return maxDuration } diff --git a/utils/coreutils_test.go b/utils/coreutils_test.go index 3b58239b1..10e71b62d 100644 --- a/utils/coreutils_test.go +++ b/utils/coreutils_test.go @@ -1661,3 +1661,28 @@ func TestAPITPDataGetPaginateOpts(t *testing.T) { t.Errorf("expected: <%+v>, \nreceived: <%+v>", experr, err) } } + +func TestCoreUtilsFibSeqNrOverflow(t *testing.T) { + fib := Fib() + for i := 0; i < 92; i++ { // the 93rd fibonacci number in the sequence would normally overflow + fib() + } + exp := fib() + for i := 0; i < 100; i++ { + if rcv := fib(); rcv != exp { + t.Errorf("expected: <%+v>, \nreceived: <%+v>", exp, rcv) + } + } +} + +func TestCoreUtilsFibDurationSeqNrOverflow(t *testing.T) { + fib := FibDuration(time.Second, 0) + for i := 0; i < 49; i++ { // the 50th fibonacci number in the sequence would normally overflow when multiplied with time.Second + fib() + } + for i := 0; i < 100; i++ { + if rcv := fib(); rcv != AbsoluteMaxDuration { + t.Errorf("expected: <%+v>, \nreceived: <%+v>", AbsoluteMaxDuration, rcv) + } + } +}