Details
-
Bug
-
Status: Resolved
-
Minor
-
Resolution: Fixed
-
None
-
None
-
Patch Available
-
Novice
Description
When a Throttler has not been used for longer than Integer#MAX_VALUE, casting the result of the ThrottlePermit comparison to an int causes a bit overflow.
Using a value comparison prevents this issue.
Current :
private static class ThrottlePermit implements Delayed { @Override public int compareTo(final Delayed o) { return (int) (getDelay(TimeUnit.MILLISECONDS) - o.getDelay(TimeUnit.MILLISECONDS)); } }
Proposal :
private static class ThrottlePermit implements Delayed { @Override public int compareTo(final Delayed o) { return Long.compare(getDelay(TimeUnit.MILLISECONDS), o.getDelay(TimeUnit.MILLISECONDS)); } }
Unit Test :
public class ThrottlerPermitTest { /** * When a Throttler has not been used for longer than {@link java.lang.Integer#MAX_VALUE}, * casting the result of the {@link ThrottlePermit} comparison to an int causes a bit overflow. * Using a value comparison prevents this issue. **/ @Test public void testThrottlerPermitWithOldScheduledTime() { long timeMillis = System.currentTimeMillis(); // 30 days in the past ThrottlePermit throttlePermitOld = new ThrottlePermit(timeMillis -2592000000L); // Now ThrottlePermit throttlePermitNow = new ThrottlePermit(timeMillis); ThrottlePermit throttlePermitNow2 = new ThrottlePermit(timeMillis); // Future ThrottlePermit throttlePermitFuture = new ThrottlePermit(timeMillis + 1000); assertEquals(-1, throttlePermitOld.compareTo(throttlePermitNow)); assertEquals(0, throttlePermitNow.compareTo(throttlePermitNow2)); assertEquals(1, throttlePermitFuture.compareTo(throttlePermitNow)); } private final class ThrottlePermit implements Delayed { private volatile long scheduledTime; ThrottlePermit(final long delayMs) { setDelayMs(delayMs); } public void setDelayMs(final long delayMs) { this.scheduledTime = System.currentTimeMillis() + delayMs; } @Override public long getDelay(final TimeUnit unit) { return unit.convert(scheduledTime - System.currentTimeMillis(), TimeUnit.MILLISECONDS); } @Override public int compareTo(final Delayed o) { return Long.compare(getDelay(TimeUnit.MILLISECONDS), o.getDelay(TimeUnit.MILLISECONDS)); } } }