From 7f83ba2fbc962b0022ed2e05e774234ca8aa96b9 Mon Sep 17 00:00:00 2001 From: _tud <98935832+UnderscoreTud@users.noreply.github.com> Date: Sun, 14 Jan 2024 08:25:44 +0300 Subject: [PATCH 1/2] Fix timespan addition --- .../skript/classes/data/DefaultOperations.java | 3 ++- src/main/java/ch/njol/util/Math2.java | 14 ++++++++++++++ ...imespan addition causes exception when overflow | 2 ++ 3 files changed, 18 insertions(+), 1 deletion(-) create mode 100644 src/test/skript/tests/regressions/6328-timespan addition causes exception when overflow diff --git a/src/main/java/ch/njol/skript/classes/data/DefaultOperations.java b/src/main/java/ch/njol/skript/classes/data/DefaultOperations.java index d3f51b29bb9..24ce6a4e2a9 100644 --- a/src/main/java/ch/njol/skript/classes/data/DefaultOperations.java +++ b/src/main/java/ch/njol/skript/classes/data/DefaultOperations.java @@ -21,6 +21,7 @@ import ch.njol.skript.util.Date; import ch.njol.skript.util.Timespan; import ch.njol.skript.util.Utils; +import ch.njol.util.Math2; import org.bukkit.util.Vector; import org.skriptlang.skript.lang.arithmetic.Arithmetics; import org.skriptlang.skript.lang.arithmetic.Operator; @@ -84,7 +85,7 @@ public class DefaultOperations { }); // Timespan - Timespan - Arithmetics.registerOperation(Operator.ADDITION, Timespan.class, (left, right) -> new Timespan(left.getMilliSeconds() + right.getMilliSeconds())); + Arithmetics.registerOperation(Operator.ADDITION, Timespan.class, (left, right) -> new Timespan(Math2.addClamped(left.getMilliSeconds(), right.getMilliSeconds()))); Arithmetics.registerOperation(Operator.SUBTRACTION, Timespan.class, (left, right) -> new Timespan(Math.max(0, left.getMilliSeconds() - right.getMilliSeconds()))); Arithmetics.registerDifference(Timespan.class, (left, right) -> new Timespan(Math.abs(left.getMilliSeconds() - right.getMilliSeconds()))); Arithmetics.registerDefaultValue(Timespan.class, Timespan::new); diff --git a/src/main/java/ch/njol/util/Math2.java b/src/main/java/ch/njol/util/Math2.java index c16018d341e..5091ec70679 100644 --- a/src/main/java/ch/njol/util/Math2.java +++ b/src/main/java/ch/njol/util/Math2.java @@ -155,6 +155,20 @@ public static long round(double value) { public static float safe(float value) { return Float.isFinite(value) ? value : 0; } + + /** + * @param x the first value + * @param y the second value + * @return the sum of x and y, or {@link Long#MAX_VALUE} in case of an overflow + */ + public static long addClamped(long x, long y) { + long result = x + y; + // Logic extracted from Math#addExact to avoid having to catch an expensive exception + boolean causedOverflow = ((x ^ result) & (y ^ result)) < 0; + if (causedOverflow) + return Long.MAX_VALUE; + return result; + } @Deprecated @ScheduledForRemoval diff --git a/src/test/skript/tests/regressions/6328-timespan addition causes exception when overflow b/src/test/skript/tests/regressions/6328-timespan addition causes exception when overflow new file mode 100644 index 00000000000..98694c4bd1f --- /dev/null +++ b/src/test/skript/tests/regressions/6328-timespan addition causes exception when overflow @@ -0,0 +1,2 @@ +test "timespan addition": + assert 1000000000 years + 10000000 years is set with "timespan addition overflow did not return max value" \ No newline at end of file From 7cfc15cc46302fb5eb338b751d3390a83f2e09eb Mon Sep 17 00:00:00 2001 From: _tud <98935832+UnderscoreTud@users.noreply.github.com> Date: Mon, 29 Jan 2024 16:56:51 +0300 Subject: [PATCH 2/2] Fix timespan-number multiplication --- .../njol/skript/classes/data/DefaultOperations.java | 2 +- src/main/java/ch/njol/util/Math2.java | 11 +++++++++++ ...8-timespan addition causes exception when overflow | 2 -- ...ons can cause exceptions if there's an overflow.sk | 3 +++ 4 files changed, 15 insertions(+), 3 deletions(-) delete mode 100644 src/test/skript/tests/regressions/6328-timespan addition causes exception when overflow create mode 100644 src/test/skript/tests/regressions/6328-timespan operations can cause exceptions if there's an overflow.sk diff --git a/src/main/java/ch/njol/skript/classes/data/DefaultOperations.java b/src/main/java/ch/njol/skript/classes/data/DefaultOperations.java index 24ce6a4e2a9..e6397a1e767 100644 --- a/src/main/java/ch/njol/skript/classes/data/DefaultOperations.java +++ b/src/main/java/ch/njol/skript/classes/data/DefaultOperations.java @@ -96,7 +96,7 @@ public class DefaultOperations { long scalar = right.longValue(); if (scalar < 0) return null; - return new Timespan(left.getMilliSeconds() * scalar); + return new Timespan(Math2.multiplyClamped(left.getMilliSeconds(), scalar)); }, (left, right) -> { long scalar = left.longValue(); if (scalar < 0) diff --git a/src/main/java/ch/njol/util/Math2.java b/src/main/java/ch/njol/util/Math2.java index 5091ec70679..d17ac6910d1 100644 --- a/src/main/java/ch/njol/util/Math2.java +++ b/src/main/java/ch/njol/util/Math2.java @@ -170,6 +170,17 @@ public static long addClamped(long x, long y) { return result; } + public static long multiplyClamped(long x, long y) { + long result = x * y; + long ax = Math.abs(x); + long ay = Math.abs(y); + // Logic extracted from Math#multiplyExact to avoid having to catch an expensive exception + if (((ax | ay) >>> 31 != 0) && (((y != 0) && (result / y != x)) || (x == Long.MIN_VALUE && y == -1))) + // If either x or y is negative return the min value, otherwise return the max value + return x < 0 == y < 0 ? Long.MAX_VALUE : Long.MIN_VALUE; + return result; + } + @Deprecated @ScheduledForRemoval public static int floorI(double value) { diff --git a/src/test/skript/tests/regressions/6328-timespan addition causes exception when overflow b/src/test/skript/tests/regressions/6328-timespan addition causes exception when overflow deleted file mode 100644 index 98694c4bd1f..00000000000 --- a/src/test/skript/tests/regressions/6328-timespan addition causes exception when overflow +++ /dev/null @@ -1,2 +0,0 @@ -test "timespan addition": - assert 1000000000 years + 10000000 years is set with "timespan addition overflow did not return max value" \ No newline at end of file diff --git a/src/test/skript/tests/regressions/6328-timespan operations can cause exceptions if there's an overflow.sk b/src/test/skript/tests/regressions/6328-timespan operations can cause exceptions if there's an overflow.sk new file mode 100644 index 00000000000..1267fc7c081 --- /dev/null +++ b/src/test/skript/tests/regressions/6328-timespan operations can cause exceptions if there's an overflow.sk @@ -0,0 +1,3 @@ +test "timespan overflow exception": + assert 1000000000 years + 10000000 years is set with "timespan addition overflow did not return max value" + assert 1000000000 years * 10000000 is set with "timespan addition overflow did not return max value" \ No newline at end of file