From 4419afb9c90155d61df9df5cbc00a216cf53c1ba Mon Sep 17 00:00:00 2001 From: Kezz Date: Sat, 21 Jun 2025 11:58:46 +0100 Subject: [PATCH] fix: Safely handle nanosecond overflow in ClickCallback (#12686) If you are creating a click callback using e.g. ChronoUnit.FOREVER.getDuration() this code will throw an ArithmeticException because toNanos overflows. The only way toNanos throws this exception is if the nanos overflow, so we can just safely cap it here as the max value for a long. --- .../adventure/providers/ClickCallbackProviderImpl.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/paper-server/src/main/java/io/papermc/paper/adventure/providers/ClickCallbackProviderImpl.java b/paper-server/src/main/java/io/papermc/paper/adventure/providers/ClickCallbackProviderImpl.java index 23432eea86..40a7ab04f8 100644 --- a/paper-server/src/main/java/io/papermc/paper/adventure/providers/ClickCallbackProviderImpl.java +++ b/paper-server/src/main/java/io/papermc/paper/adventure/providers/ClickCallbackProviderImpl.java @@ -65,8 +65,14 @@ public class ClickCallbackProviderImpl implements ClickCallback.Provider { private int remainingUses; private StoredCallback(final @NotNull ClickCallback callback, final ClickCallback.@NotNull Options options, final UUID id) { + long lifetimeValue; this.callback = callback; - this.lifetime = options.lifetime().toNanos(); + try { + lifetimeValue = options.lifetime().toNanos(); + } catch (final ArithmeticException ex) { + lifetimeValue = Long.MAX_VALUE; + } + this.lifetime = lifetimeValue; this.remainingUses = options.uses(); this.id = id; } @@ -82,6 +88,7 @@ public class ClickCallbackProviderImpl implements ClickCallback.Provider { } public boolean expired() { + if (this.lifetime == Long.MAX_VALUE) return false; return System.nanoTime() - this.startedAt >= this.lifetime; }