diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/CompilerSettings.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/CompilerSettings.java index 9ec26bf345a..4cafe32bb56 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/CompilerSettings.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/CompilerSettings.java @@ -24,47 +24,16 @@ package org.elasticsearch.painless; */ public final class CompilerSettings { - /** - * Constant to be used when specifying numeric overflow when compiling a script. - */ - public static final String NUMERIC_OVERFLOW = "numeric_overflow"; - /** * Constant to be used when specifying the maximum loop counter when compiling a script. */ public static final String MAX_LOOP_COUNTER = "max_loop_counter"; - /** - * Whether or not to allow numeric values to overflow without exception. - */ - private boolean numericOverflow = true; - /** * The maximum number of statements allowed to be run in a loop. */ private int maxLoopCounter = 10000; - /** - * Returns {@code true} if numeric operations should overflow, {@code false} - * if they should signal an exception. - *

- * If this value is {@code true} (default), then things behave like java: - * overflow for integer types can result in unexpected values / unexpected - * signs, and overflow for floating point types can result in infinite or - * {@code NaN} values. - */ - public final boolean getNumericOverflow() { - return numericOverflow; - } - - /** - * Set {@code true} for numerics to overflow, false to deliver exceptions. - * @see #getNumericOverflow - */ - public final void setNumericOverflow(boolean allow) { - this.numericOverflow = allow; - } - /** * Returns the value for the cumulative total number of statements that can be made in all loops * in a script before an exception is thrown. This attempts to prevent infinite loops. Note if diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/MethodWriter.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/MethodWriter.java index bb362558796..cda8c23e3bf 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/MethodWriter.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/MethodWriter.java @@ -34,10 +34,6 @@ import java.util.ArrayList; import java.util.Deque; import java.util.List; -import static org.elasticsearch.painless.WriterConstants.ADDEXACT_INT; -import static org.elasticsearch.painless.WriterConstants.ADDEXACT_LONG; -import static org.elasticsearch.painless.WriterConstants.ADDWOOVERLOW_DOUBLE; -import static org.elasticsearch.painless.WriterConstants.ADDWOOVERLOW_FLOAT; import static org.elasticsearch.painless.WriterConstants.DEF_ADD_CALL; import static org.elasticsearch.painless.WriterConstants.DEF_AND_CALL; import static org.elasticsearch.painless.WriterConstants.DEF_DIV_CALL; @@ -49,19 +45,9 @@ import static org.elasticsearch.painless.WriterConstants.DEF_RSH_CALL; import static org.elasticsearch.painless.WriterConstants.DEF_SUB_CALL; import static org.elasticsearch.painless.WriterConstants.DEF_USH_CALL; import static org.elasticsearch.painless.WriterConstants.DEF_XOR_CALL; -import static org.elasticsearch.painless.WriterConstants.DIVWOOVERLOW_DOUBLE; -import static org.elasticsearch.painless.WriterConstants.DIVWOOVERLOW_FLOAT; -import static org.elasticsearch.painless.WriterConstants.DIVWOOVERLOW_INT; -import static org.elasticsearch.painless.WriterConstants.DIVWOOVERLOW_LONG; import static org.elasticsearch.painless.WriterConstants.INDY_STRING_CONCAT_BOOTSTRAP_HANDLE; import static org.elasticsearch.painless.WriterConstants.MAX_INDY_STRING_CONCAT_ARGS; -import static org.elasticsearch.painless.WriterConstants.MULEXACT_INT; -import static org.elasticsearch.painless.WriterConstants.MULEXACT_LONG; -import static org.elasticsearch.painless.WriterConstants.MULWOOVERLOW_DOUBLE; -import static org.elasticsearch.painless.WriterConstants.MULWOOVERLOW_FLOAT; import static org.elasticsearch.painless.WriterConstants.PAINLESS_ERROR_TYPE; -import static org.elasticsearch.painless.WriterConstants.REMWOOVERLOW_DOUBLE; -import static org.elasticsearch.painless.WriterConstants.REMWOOVERLOW_FLOAT; import static org.elasticsearch.painless.WriterConstants.STRINGBUILDER_APPEND_BOOLEAN; import static org.elasticsearch.painless.WriterConstants.STRINGBUILDER_APPEND_CHAR; import static org.elasticsearch.painless.WriterConstants.STRINGBUILDER_APPEND_DOUBLE; @@ -74,28 +60,6 @@ import static org.elasticsearch.painless.WriterConstants.STRINGBUILDER_CONSTRUCT import static org.elasticsearch.painless.WriterConstants.STRINGBUILDER_TOSTRING; import static org.elasticsearch.painless.WriterConstants.STRINGBUILDER_TYPE; import static org.elasticsearch.painless.WriterConstants.STRING_TYPE; -import static org.elasticsearch.painless.WriterConstants.SUBEXACT_INT; -import static org.elasticsearch.painless.WriterConstants.SUBEXACT_LONG; -import static org.elasticsearch.painless.WriterConstants.SUBWOOVERLOW_DOUBLE; -import static org.elasticsearch.painless.WriterConstants.SUBWOOVERLOW_FLOAT; -import static org.elasticsearch.painless.WriterConstants.TOBYTEEXACT_INT; -import static org.elasticsearch.painless.WriterConstants.TOBYTEEXACT_LONG; -import static org.elasticsearch.painless.WriterConstants.TOBYTEWOOVERFLOW_DOUBLE; -import static org.elasticsearch.painless.WriterConstants.TOBYTEWOOVERFLOW_FLOAT; -import static org.elasticsearch.painless.WriterConstants.TOCHAREXACT_INT; -import static org.elasticsearch.painless.WriterConstants.TOCHAREXACT_LONG; -import static org.elasticsearch.painless.WriterConstants.TOCHARWOOVERFLOW_DOUBLE; -import static org.elasticsearch.painless.WriterConstants.TOCHARWOOVERFLOW_FLOAT; -import static org.elasticsearch.painless.WriterConstants.TOFLOATWOOVERFLOW_DOUBLE; -import static org.elasticsearch.painless.WriterConstants.TOINTEXACT_LONG; -import static org.elasticsearch.painless.WriterConstants.TOINTWOOVERFLOW_DOUBLE; -import static org.elasticsearch.painless.WriterConstants.TOINTWOOVERFLOW_FLOAT; -import static org.elasticsearch.painless.WriterConstants.TOLONGWOOVERFLOW_DOUBLE; -import static org.elasticsearch.painless.WriterConstants.TOLONGWOOVERFLOW_FLOAT; -import static org.elasticsearch.painless.WriterConstants.TOSHORTEXACT_INT; -import static org.elasticsearch.painless.WriterConstants.TOSHORTEXACT_LONG; -import static org.elasticsearch.painless.WriterConstants.TOSHORTWOOVERFLOW_DOUBLE; -import static org.elasticsearch.painless.WriterConstants.TOSHORTWOOVERFLOW_FLOAT; /** * Extension of {@link GeneratorAdapter} with some utility methods. @@ -236,231 +200,53 @@ public final class MethodWriter extends GeneratorAdapter { } } - public void writeBinaryInstruction(final CompilerSettings settings, final Definition definition, + public void writeBinaryInstruction(final Definition definition, final String location, final Type type, final Operation operation) { final Sort sort = type.sort; - boolean exact = !settings.getNumericOverflow() && - ((sort == Sort.INT || sort == Sort.LONG) && - (operation == Operation.MUL || operation == Operation.DIV || - operation == Operation.ADD || operation == Operation.SUB) || - (sort == Sort.FLOAT || sort == Sort.DOUBLE) && - (operation == Operation.MUL || operation == Operation.DIV || operation == Operation.REM || - operation == Operation.ADD || operation == Operation.SUB)); - - if (exact) { - switch (sort) { - case INT: - switch (operation) { - case MUL: invokeStatic(definition.getType("Math").type, MULEXACT_INT); break; - case DIV: invokeStatic(definition.getType("Utility").type, DIVWOOVERLOW_INT); break; - case ADD: invokeStatic(definition.getType("Math").type, ADDEXACT_INT); break; - case SUB: invokeStatic(definition.getType("Math").type, SUBEXACT_INT); break; - } - - break; - case LONG: - switch (operation) { - case MUL: invokeStatic(definition.getType("Math").type, MULEXACT_LONG); break; - case DIV: invokeStatic(definition.getType("Utility").type, DIVWOOVERLOW_LONG); break; - case ADD: invokeStatic(definition.getType("Math").type, ADDEXACT_LONG); break; - case SUB: invokeStatic(definition.getType("Math").type, SUBEXACT_LONG); break; - } - - break; - case FLOAT: - switch (operation) { - case MUL: invokeStatic(definition.getType("Utility").type, MULWOOVERLOW_FLOAT); break; - case DIV: invokeStatic(definition.getType("Utility").type, DIVWOOVERLOW_FLOAT); break; - case REM: invokeStatic(definition.getType("Utility").type, REMWOOVERLOW_FLOAT); break; - case ADD: invokeStatic(definition.getType("Utility").type, ADDWOOVERLOW_FLOAT); break; - case SUB: invokeStatic(definition.getType("Utility").type, SUBWOOVERLOW_FLOAT); break; - default: - throw new IllegalStateException("Error " + location + ": Illegal tree structure."); - } - - break; - case DOUBLE: - switch (operation) { - case MUL: invokeStatic(definition.getType("Utility").type, MULWOOVERLOW_DOUBLE); break; - case DIV: invokeStatic(definition.getType("Utility").type, DIVWOOVERLOW_DOUBLE); break; - case REM: invokeStatic(definition.getType("Utility").type, REMWOOVERLOW_DOUBLE); break; - case ADD: invokeStatic(definition.getType("Utility").type, ADDWOOVERLOW_DOUBLE); break; - case SUB: invokeStatic(definition.getType("Utility").type, SUBWOOVERLOW_DOUBLE); break; - default: - throw new IllegalStateException("Error " + location + ": Illegal tree structure."); - } - - break; + + if ((sort == Sort.FLOAT || sort == Sort.DOUBLE) && + (operation == Operation.LSH || operation == Operation.USH || + operation == Operation.RSH || operation == Operation.BWAND || + operation == Operation.XOR || operation == Operation.BWOR)) { + throw new IllegalStateException("Error " + location + ": Illegal tree structure."); + } + + if (sort == Sort.DEF) { + switch (operation) { + case MUL: invokeStatic(definition.getType("Def").type, DEF_MUL_CALL); break; + case DIV: invokeStatic(definition.getType("Def").type, DEF_DIV_CALL); break; + case REM: invokeStatic(definition.getType("Def").type, DEF_REM_CALL); break; + case ADD: invokeStatic(definition.getType("Def").type, DEF_ADD_CALL); break; + case SUB: invokeStatic(definition.getType("Def").type, DEF_SUB_CALL); break; + case LSH: invokeStatic(definition.getType("Def").type, DEF_LSH_CALL); break; + case USH: invokeStatic(definition.getType("Def").type, DEF_RSH_CALL); break; + case RSH: invokeStatic(definition.getType("Def").type, DEF_USH_CALL); break; + case BWAND: invokeStatic(definition.getType("Def").type, DEF_AND_CALL); break; + case XOR: invokeStatic(definition.getType("Def").type, DEF_XOR_CALL); break; + case BWOR: invokeStatic(definition.getType("Def").type, DEF_OR_CALL); break; default: throw new IllegalStateException("Error " + location + ": Illegal tree structure."); } } else { - if ((sort == Sort.FLOAT || sort == Sort.DOUBLE) && - (operation == Operation.LSH || operation == Operation.USH || - operation == Operation.RSH || operation == Operation.BWAND || - operation == Operation.XOR || operation == Operation.BWOR)) { - throw new IllegalStateException("Error " + location + ": Illegal tree structure."); - } - - if (sort == Sort.DEF) { - switch (operation) { - case MUL: invokeStatic(definition.getType("Def").type, DEF_MUL_CALL); break; - case DIV: invokeStatic(definition.getType("Def").type, DEF_DIV_CALL); break; - case REM: invokeStatic(definition.getType("Def").type, DEF_REM_CALL); break; - case ADD: invokeStatic(definition.getType("Def").type, DEF_ADD_CALL); break; - case SUB: invokeStatic(definition.getType("Def").type, DEF_SUB_CALL); break; - case LSH: invokeStatic(definition.getType("Def").type, DEF_LSH_CALL); break; - case USH: invokeStatic(definition.getType("Def").type, DEF_RSH_CALL); break; - case RSH: invokeStatic(definition.getType("Def").type, DEF_USH_CALL); break; - case BWAND: invokeStatic(definition.getType("Def").type, DEF_AND_CALL); break; - case XOR: invokeStatic(definition.getType("Def").type, DEF_XOR_CALL); break; - case BWOR: invokeStatic(definition.getType("Def").type, DEF_OR_CALL); break; - default: - throw new IllegalStateException("Error " + location + ": Illegal tree structure."); - } - } else { - switch (operation) { - case MUL: math(GeneratorAdapter.MUL, type.type); break; - case DIV: math(GeneratorAdapter.DIV, type.type); break; - case REM: math(GeneratorAdapter.REM, type.type); break; - case ADD: math(GeneratorAdapter.ADD, type.type); break; - case SUB: math(GeneratorAdapter.SUB, type.type); break; - case LSH: math(GeneratorAdapter.SHL, type.type); break; - case USH: math(GeneratorAdapter.USHR, type.type); break; - case RSH: math(GeneratorAdapter.SHR, type.type); break; - case BWAND: math(GeneratorAdapter.AND, type.type); break; - case XOR: math(GeneratorAdapter.XOR, type.type); break; - case BWOR: math(GeneratorAdapter.OR, type.type); break; - default: - throw new IllegalStateException("Error " + location + ": Illegal tree structure."); - } + switch (operation) { + case MUL: math(GeneratorAdapter.MUL, type.type); break; + case DIV: math(GeneratorAdapter.DIV, type.type); break; + case REM: math(GeneratorAdapter.REM, type.type); break; + case ADD: math(GeneratorAdapter.ADD, type.type); break; + case SUB: math(GeneratorAdapter.SUB, type.type); break; + case LSH: math(GeneratorAdapter.SHL, type.type); break; + case USH: math(GeneratorAdapter.USHR, type.type); break; + case RSH: math(GeneratorAdapter.SHR, type.type); break; + case BWAND: math(GeneratorAdapter.AND, type.type); break; + case XOR: math(GeneratorAdapter.XOR, type.type); break; + case BWOR: math(GeneratorAdapter.OR, type.type); break; + default: + throw new IllegalStateException("Error " + location + ": Illegal tree structure."); } } } - /** - * Called for any compound assignment (including increment/decrement instructions). - * We have to be stricter than writeBinary and do overflow checks against the original type's size - * instead of the promoted type's size, since the result will be implicitly cast back. - * - * @return This will be true if an instruction is written, false otherwise. - */ - public boolean writeExactInstruction( - final Definition definition, final Sort fsort, final Sort tsort) { - if (fsort == Sort.DOUBLE) { - if (tsort == Sort.FLOAT) { - invokeStatic(definition.getType("Utility").type, TOFLOATWOOVERFLOW_DOUBLE); - } else if (tsort == Sort.FLOAT_OBJ) { - invokeStatic(definition.getType("Utility").type, TOFLOATWOOVERFLOW_DOUBLE); - checkCast(definition.getType("Float").type); - } else if (tsort == Sort.LONG) { - invokeStatic(definition.getType("Utility").type, TOLONGWOOVERFLOW_DOUBLE); - } else if (tsort == Sort.LONG_OBJ) { - invokeStatic(definition.getType("Utility").type, TOLONGWOOVERFLOW_DOUBLE); - checkCast(definition.getType("Long").type); - } else if (tsort == Sort.INT) { - invokeStatic(definition.getType("Utility").type, TOINTWOOVERFLOW_DOUBLE); - } else if (tsort == Sort.INT_OBJ) { - invokeStatic(definition.getType("Utility").type, TOINTWOOVERFLOW_DOUBLE); - checkCast(definition.getType("Integer").type); - } else if (tsort == Sort.CHAR) { - invokeStatic(definition.getType("Utility").type, TOCHARWOOVERFLOW_DOUBLE); - } else if (tsort == Sort.CHAR_OBJ) { - invokeStatic(definition.getType("Utility").type, TOCHARWOOVERFLOW_DOUBLE); - checkCast(definition.getType("Character").type); - } else if (tsort == Sort.SHORT) { - invokeStatic(definition.getType("Utility").type, TOSHORTWOOVERFLOW_DOUBLE); - } else if (tsort == Sort.SHORT_OBJ) { - invokeStatic(definition.getType("Utility").type, TOSHORTWOOVERFLOW_DOUBLE); - checkCast(definition.getType("Short").type); - } else if (tsort == Sort.BYTE) { - invokeStatic(definition.getType("Utility").type, TOBYTEWOOVERFLOW_DOUBLE); - } else if (tsort == Sort.BYTE_OBJ) { - invokeStatic(definition.getType("Utility").type, TOBYTEWOOVERFLOW_DOUBLE); - checkCast(definition.getType("Byte").type); - } else { - return false; - } - } else if (fsort == Sort.FLOAT) { - if (tsort == Sort.LONG) { - invokeStatic(definition.getType("Utility").type, TOLONGWOOVERFLOW_FLOAT); - } else if (tsort == Sort.LONG_OBJ) { - invokeStatic(definition.getType("Utility").type, TOLONGWOOVERFLOW_FLOAT); - checkCast(definition.getType("Long").type); - } else if (tsort == Sort.INT) { - invokeStatic(definition.getType("Utility").type, TOINTWOOVERFLOW_FLOAT); - } else if (tsort == Sort.INT_OBJ) { - invokeStatic(definition.getType("Utility").type, TOINTWOOVERFLOW_FLOAT); - checkCast(definition.getType("Integer").type); - } else if (tsort == Sort.CHAR) { - invokeStatic(definition.getType("Utility").type, TOCHARWOOVERFLOW_FLOAT); - } else if (tsort == Sort.CHAR_OBJ) { - invokeStatic(definition.getType("Utility").type, TOCHARWOOVERFLOW_FLOAT); - checkCast(definition.getType("Character").type); - } else if (tsort == Sort.SHORT) { - invokeStatic(definition.getType("Utility").type, TOSHORTWOOVERFLOW_FLOAT); - } else if (tsort == Sort.SHORT_OBJ) { - invokeStatic(definition.getType("Utility").type, TOSHORTWOOVERFLOW_FLOAT); - checkCast(definition.getType("Short").type); - } else if (tsort == Sort.BYTE) { - invokeStatic(definition.getType("Utility").type, TOBYTEWOOVERFLOW_FLOAT); - } else if (tsort == Sort.BYTE_OBJ) { - invokeStatic(definition.getType("Utility").type, TOBYTEWOOVERFLOW_FLOAT); - checkCast(definition.getType("Byte").type); - } else { - return false; - } - } else if (fsort == Sort.LONG) { - if (tsort == Sort.INT) { - invokeStatic(definition.getType("Math").type, TOINTEXACT_LONG); - } else if (tsort == Sort.INT_OBJ) { - invokeStatic(definition.getType("Math").type, TOINTEXACT_LONG); - checkCast(definition.getType("Integer").type); - } else if (tsort == Sort.CHAR) { - invokeStatic(definition.getType("Utility").type, TOCHAREXACT_LONG); - } else if (tsort == Sort.CHAR_OBJ) { - invokeStatic(definition.getType("Utility").type, TOCHAREXACT_LONG); - checkCast(definition.getType("Character").type); - } else if (tsort == Sort.SHORT) { - invokeStatic(definition.getType("Utility").type, TOSHORTEXACT_LONG); - } else if (tsort == Sort.SHORT_OBJ) { - invokeStatic(definition.getType("Utility").type, TOSHORTEXACT_LONG); - checkCast(definition.getType("Short").type); - } else if (tsort == Sort.BYTE) { - invokeStatic(definition.getType("Utility").type, TOBYTEEXACT_LONG); - } else if (tsort == Sort.BYTE_OBJ) { - invokeStatic(definition.getType("Utility").type, TOBYTEEXACT_LONG); - checkCast(definition.getType("Byte").type); - } else { - return false; - } - } else if (fsort == Sort.INT) { - if (tsort == Sort.CHAR) { - invokeStatic(definition.getType("Utility").type, TOCHAREXACT_INT); - } else if (tsort == Sort.CHAR_OBJ) { - invokeStatic(definition.getType("Utility").type, TOCHAREXACT_INT); - checkCast(definition.getType("Character").type); - } else if (tsort == Sort.SHORT) { - invokeStatic(definition.getType("Utility").type, TOSHORTEXACT_INT); - } else if (tsort == Sort.SHORT_OBJ) { - invokeStatic(definition.getType("Utility").type, TOSHORTEXACT_INT); - checkCast(definition.getType("Short").type); - } else if (tsort == Sort.BYTE) { - invokeStatic(definition.getType("Utility").type, TOBYTEEXACT_INT); - } else if (tsort == Sort.BYTE_OBJ) { - invokeStatic(definition.getType("Utility").type, TOBYTEEXACT_INT); - checkCast(definition.getType("Byte").type); - } else { - return false; - } - } else { - return false; - } - - return true; - } - public void writeDup(final int size, final int xsize) { if (size == 1) { if (xsize == 2) { diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/PainlessScriptEngineService.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/PainlessScriptEngineService.java index 1d11dae720f..4c627d08eca 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/PainlessScriptEngineService.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/PainlessScriptEngineService.java @@ -115,13 +115,7 @@ public final class PainlessScriptEngineService extends AbstractComponent impleme // Use custom settings specified by params. compilerSettings = new CompilerSettings(); Map copy = new HashMap<>(params); - String value = copy.remove(CompilerSettings.NUMERIC_OVERFLOW); - - if (value != null) { - compilerSettings.setNumericOverflow(Boolean.parseBoolean(value)); - } - - value = copy.remove(CompilerSettings.MAX_LOOP_COUNTER); + String value = copy.remove(CompilerSettings.MAX_LOOP_COUNTER); if (value != null) { compilerSettings.setMaxLoopCounter(Integer.parseInt(value)); diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/Utility.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/Utility.java index 32641649827..559e909ed77 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/Utility.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/Utility.java @@ -481,347 +481,6 @@ public class Utility { return value.charAt(0); } - // although divide by zero is guaranteed, the special overflow case is not caught. - // its not needed for remainder because it is not possible there. - // see https://docs.oracle.com/javase/specs/jls/se8/html/jls-15.html#jls-15.17.2 - - /** - * Integer divide without overflow - * @throws ArithmeticException on overflow or divide-by-zero - */ - public static int divideWithoutOverflow(int x, int y) { - if (x == Integer.MIN_VALUE && y == -1) { - throw new ArithmeticException("integer overflow"); - } - return x / y; - } - - /** - * Long divide without overflow - * @throws ArithmeticException on overflow or divide-by-zero - */ - public static long divideWithoutOverflow(long x, long y) { - if (x == Long.MIN_VALUE && y == -1L) { - throw new ArithmeticException("long overflow"); - } - return x / y; - } - - // byte, short, and char are promoted to int for normal operations, - // so the JDK exact methods are typically used, and the result has a wider range. - // but compound assignments and increment/decrement operators (e.g. byte b = Byte.MAX_VALUE; b++;) - // implicitly cast back to the original type: so these need to be checked against the original range. - - /** - * Like {@link Math#toIntExact(long)} but for byte range. - */ - public static byte toByteExact(int value) { - byte s = (byte) value; - if (s != value) { - throw new ArithmeticException("byte overflow"); - } - return s; - } - - /** - * Like {@link Math#toIntExact(long)} but for byte range. - */ - public static byte toByteExact(long value) { - byte s = (byte) value; - if (s != value) { - throw new ArithmeticException("byte overflow"); - } - return s; - } - - /** - * Like {@link Math#toIntExact(long)} but for byte range. - */ - public static byte toByteWithoutOverflow(float value) { - if (value < Byte.MIN_VALUE || value > Byte.MAX_VALUE) { - throw new ArithmeticException("byte overflow"); - } - return (byte)value; - } - - /** - * Like {@link Math#toIntExact(long)} but for byte range. - */ - public static byte toByteWithoutOverflow(double value) { - if (value < Byte.MIN_VALUE || value > Byte.MAX_VALUE) { - throw new ArithmeticException("byte overflow"); - } - return (byte)value; - } - - /** - * Like {@link Math#toIntExact(long)} but for short range. - */ - public static short toShortExact(int value) { - short s = (short) value; - if (s != value) { - throw new ArithmeticException("short overflow"); - } - return s; - } - - /** - * Like {@link Math#toIntExact(long)} but for short range. - */ - public static short toShortExact(long value) { - short s = (short) value; - if (s != value) { - throw new ArithmeticException("short overflow"); - } - return s; - } - - /** - * Like {@link Math#toIntExact(long)} but for short range. - */ - public static short toShortWithoutOverflow(float value) { - if (value < Short.MIN_VALUE || value > Short.MAX_VALUE) { - throw new ArithmeticException("short overflow"); - } - return (short)value; - } - - /** - * Like {@link Math#toIntExact(long)} but for short range. - */ - public static short toShortExact(double value) { - if (value < Short.MIN_VALUE || value > Short.MAX_VALUE) { - throw new ArithmeticException("short overflow"); - } - return (short)value; - } - - /** - * Like {@link Math#toIntExact(long)} but for char range. - */ - public static char toCharExact(int value) { - char s = (char) value; - if (s != value) { - throw new ArithmeticException("char overflow"); - } - return s; - } - - /** - * Like {@link Math#toIntExact(long)} but for char range. - */ - public static char toCharExact(long value) { - char s = (char) value; - if (s != value) { - throw new ArithmeticException("char overflow"); - } - return s; - } - - /** - * Like {@link Math#toIntExact(long)} but for char range. - */ - public static char toCharWithoutOverflow(float value) { - if (value < Character.MIN_VALUE || value > Character.MAX_VALUE) { - throw new ArithmeticException("char overflow"); - } - return (char)value; - } - - /** - * Like {@link Math#toIntExact(long)} but for char range. - */ - public static char toCharWithoutOverflow(double value) { - if (value < Character.MIN_VALUE || value > Character.MAX_VALUE) { - throw new ArithmeticException("char overflow"); - } - return (char)value; - } - - /** - * Like {@link Math#toIntExact(long)} but for int range. - */ - public static int toIntWithoutOverflow(float value) { - if (value < Integer.MIN_VALUE || value > Integer.MAX_VALUE) { - throw new ArithmeticException("int overflow"); - } - return (int)value; - } - - /** - * Like {@link Math#toIntExact(long)} but for int range. - */ - public static int toIntWithoutOverflow(double value) { - if (value < Integer.MIN_VALUE || value > Integer.MAX_VALUE) { - throw new ArithmeticException("int overflow"); - } - return (int)value; - } - - /** - * Like {@link Math#toIntExact(long)} but for long range. - */ - public static long toLongWithoutOverflow(float value) { - if (value < Long.MIN_VALUE || value > Long.MAX_VALUE) { - throw new ArithmeticException("long overflow"); - } - return (long)value; - } - - /** - * Like {@link Math#toIntExact(long)} but for long range. - */ - public static float toLongWithoutOverflow(double value) { - if (value < Long.MIN_VALUE || value > Long.MAX_VALUE) { - throw new ArithmeticException("long overflow"); - } - return (long)value; - } - - /** - * Like {@link Math#toIntExact(long)} but for float range. - */ - public static float toFloatWithoutOverflow(double value) { - if (value < Float.MIN_VALUE || value > Float.MAX_VALUE) { - throw new ArithmeticException("float overflow"); - } - return (float)value; - } - - /** - * Checks for overflow, result is infinite but operands are finite - * @throws ArithmeticException if overflow occurred - */ - private static float checkInfFloat(float x, float y, float z) { - if (Float.isInfinite(z)) { - if (Float.isFinite(x) && Float.isFinite(y)) { - throw new ArithmeticException("float overflow"); - } - } - return z; - } - - /** - * Checks for NaN, result is NaN but operands are finite - * @throws ArithmeticException if overflow occurred - */ - private static float checkNaNFloat(float x, float y, float z) { - if (Float.isNaN(z)) { - if (Float.isFinite(x) && Float.isFinite(y)) { - throw new ArithmeticException("NaN"); - } - } - return z; - } - - /** - * Checks for NaN, result is infinite but operands are finite - * @throws ArithmeticException if overflow occurred - */ - private static double checkInfDouble(double x, double y, double z) { - if (Double.isInfinite(z)) { - if (Double.isFinite(x) && Double.isFinite(y)) { - throw new ArithmeticException("double overflow"); - } - } - return z; - } - - /** - * Checks for NaN, result is NaN but operands are finite - * @throws ArithmeticException if overflow occurred - */ - private static double checkNaNDouble(double x, double y, double z) { - if (Double.isNaN(z)) { - if (Double.isFinite(x) && Double.isFinite(y)) { - throw new ArithmeticException("NaN"); - } - } - return z; - } - - /** - * Adds two floats but throws {@code ArithmeticException} - * if the result overflows. - */ - public static float addWithoutOverflow(float x, float y) { - return checkInfFloat(x, y, x + y); - } - - /** - * Adds two doubles but throws {@code ArithmeticException} - * if the result overflows. - */ - public static double addWithoutOverflow(double x, double y) { - return checkInfDouble(x, y, x + y); - } - - /** - * Subtracts two floats but throws {@code ArithmeticException} - * if the result overflows. - */ - public static float subtractWithoutOverflow(float x, float y) { - return checkInfFloat(x, y, x - y); - } - - /** - * Subtracts two doubles but throws {@code ArithmeticException} - * if the result overflows. - */ - public static double subtractWithoutOverflow(double x, double y) { - return checkInfDouble(x, y , x - y); - } - - /** - * Multiplies two floats but throws {@code ArithmeticException} - * if the result overflows. - */ - public static float multiplyWithoutOverflow(float x, float y) { - return checkInfFloat(x, y, x * y); - } - - /** - * Multiplies two doubles but throws {@code ArithmeticException} - * if the result overflows. - */ - public static double multiplyWithoutOverflow(double x, double y) { - return checkInfDouble(x, y, x * y); - } - - /** - * Divides two floats but throws {@code ArithmeticException} - * if the result overflows, or would create NaN from finite - * inputs ({@code x == 0, y == 0}) - */ - public static float divideWithoutOverflow(float x, float y) { - return checkNaNFloat(x, y, checkInfFloat(x, y, x / y)); - } - - /** - * Divides two doubles but throws {@code ArithmeticException} - * if the result overflows, or would create NaN from finite - * inputs ({@code x == 0, y == 0}) - */ - public static double divideWithoutOverflow(double x, double y) { - return checkNaNDouble(x, y, checkInfDouble(x, y, x / y)); - } - - /** - * Takes remainder two floats but throws {@code ArithmeticException} - * if the result would create NaN from finite inputs ({@code y == 0}) - */ - public static float remainderWithoutOverflow(float x, float y) { - return checkNaNFloat(x, y, x % y); - } - - /** - * Divides two doubles but throws {@code ArithmeticException} - * if the result would create NaN from finite inputs ({@code y == 0}) - */ - public static double remainderWithoutOverflow(double x, double y) { - return checkNaNDouble(x, y, x % y); - } - public static boolean checkEquals(final Object left, final Object right) { if (left != null) { return left.equals(right); diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/WriterConstants.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/WriterConstants.java index 6bdb9856114..d167646e9dd 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/WriterConstants.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/WriterConstants.java @@ -27,7 +27,6 @@ import org.objectweb.asm.Type; import org.objectweb.asm.commons.Method; import java.lang.invoke.CallSite; -import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; import java.util.Map; @@ -116,59 +115,8 @@ public final class WriterConstants { public final static Method STRINGBUILDER_APPEND_OBJECT = getAsmMethod(StringBuilder.class, "append", Object.class); public final static Method STRINGBUILDER_TOSTRING = getAsmMethod(String.class, "toString"); - public final static Method TOINTEXACT_LONG = getAsmMethod(int.class, "toIntExact", long.class); - public final static Method NEGATEEXACT_INT = getAsmMethod(int.class, "negateExact", int.class); - public final static Method NEGATEEXACT_LONG = getAsmMethod(long.class, "negateExact", long.class); - public final static Method MULEXACT_INT = getAsmMethod(int.class, "multiplyExact", int.class, int.class); - public final static Method MULEXACT_LONG = getAsmMethod(long.class, "multiplyExact", long.class, long.class); - public final static Method ADDEXACT_INT = getAsmMethod(int.class, "addExact", int.class, int.class); - public final static Method ADDEXACT_LONG = getAsmMethod(long.class, "addExact", long.class, long.class); - public final static Method SUBEXACT_INT = getAsmMethod(int.class, "subtractExact", int.class, int.class); - public final static Method SUBEXACT_LONG = getAsmMethod(long.class, "subtractExact", long.class, long.class); - public final static Method CHECKEQUALS = getAsmMethod(boolean.class, "checkEquals", Object.class, Object.class); - public final static Method TOBYTEEXACT_INT = getAsmMethod(byte.class, "toByteExact", int.class); - public final static Method TOBYTEEXACT_LONG = getAsmMethod(byte.class, "toByteExact", long.class); - public final static Method TOBYTEWOOVERFLOW_FLOAT = getAsmMethod(byte.class, "toByteWithoutOverflow", float.class); - public final static Method TOBYTEWOOVERFLOW_DOUBLE = getAsmMethod(byte.class, "toByteWithoutOverflow", double.class); - public final static Method TOSHORTEXACT_INT = getAsmMethod(short.class, "toShortExact", int.class); - public final static Method TOSHORTEXACT_LONG = getAsmMethod(short.class, "toShortExact", long.class); - public final static Method TOSHORTWOOVERFLOW_FLOAT = getAsmMethod(short.class, "toShortWithoutOverflow", float.class); - public final static Method TOSHORTWOOVERFLOW_DOUBLE = getAsmMethod(short.class, "toShortWihtoutOverflow", double.class); - public final static Method TOCHAREXACT_INT = getAsmMethod(char.class, "toCharExact", int.class); - public final static Method TOCHAREXACT_LONG = getAsmMethod(char.class, "toCharExact", long.class); - public final static Method TOCHARWOOVERFLOW_FLOAT = getAsmMethod(char.class, "toCharWithoutOverflow", float.class); - public final static Method TOCHARWOOVERFLOW_DOUBLE = getAsmMethod(char.class, "toCharWithoutOverflow", double.class); - public final static Method TOINTWOOVERFLOW_FLOAT = getAsmMethod(int.class, "toIntWithoutOverflow", float.class); - public final static Method TOINTWOOVERFLOW_DOUBLE = getAsmMethod(int.class, "toIntWithoutOverflow", double.class); - public final static Method TOLONGWOOVERFLOW_FLOAT = getAsmMethod(long.class, "toLongWithoutOverflow", float.class); - public final static Method TOLONGWOOVERFLOW_DOUBLE = getAsmMethod(long.class, "toLongWithoutOverflow", double.class); - public final static Method TOFLOATWOOVERFLOW_DOUBLE = getAsmMethod(float.class , "toFloatWihtoutOverflow", double.class); - public final static Method MULWOOVERLOW_FLOAT = - getAsmMethod(float.class, "multiplyWithoutOverflow", float.class, float.class); - public final static Method MULWOOVERLOW_DOUBLE = - getAsmMethod(double.class, "multiplyWithoutOverflow", double.class, double.class); - public final static Method DIVWOOVERLOW_INT = - getAsmMethod(int.class, "divideWithoutOverflow", int.class, int.class); - public final static Method DIVWOOVERLOW_LONG = - getAsmMethod(long.class, "divideWithoutOverflow", long.class, long.class); - public final static Method DIVWOOVERLOW_FLOAT = - getAsmMethod(float.class, "divideWithoutOverflow", float.class, float.class); - public final static Method DIVWOOVERLOW_DOUBLE = - getAsmMethod(double.class, "divideWithoutOverflow", double.class, double.class); - public final static Method REMWOOVERLOW_FLOAT = - getAsmMethod(float.class, "remainderWithoutOverflow", float.class, float.class); - public final static Method REMWOOVERLOW_DOUBLE = - getAsmMethod(double.class, "remainderWithoutOverflow", double.class, double.class); - public final static Method ADDWOOVERLOW_FLOAT = - getAsmMethod(float.class, "addWithoutOverflow", float.class, float.class); - public final static Method ADDWOOVERLOW_DOUBLE = - getAsmMethod(double.class, "addWithoutOverflow", double.class, double.class); - public final static Method SUBWOOVERLOW_FLOAT = - getAsmMethod(float.class, "subtractWithoutOverflow", float.class, float.class); - public final static Method SUBWOOVERLOW_DOUBLE = - getAsmMethod(double.class, "subtractWithoutOverflow", double.class, double.class); private static Method getAsmMethod(final Class rtype, final String name, final Class... ptypes) { return new Method(name, MethodType.methodType(rtype, ptypes).toMethodDescriptorString()); diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EBinary.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EBinary.java index 18b9de80fb6..f22b7394ca0 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EBinary.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EBinary.java @@ -94,21 +94,16 @@ public final class EBinary extends AExpression { right = right.cast(settings, definition, variables); if (left.constant != null && right.constant != null) { - final boolean overflow = settings.getNumericOverflow(); final Sort sort = promote.sort; if (sort == Sort.INT) { - constant = overflow ? (int)left.constant * (int)right.constant : - Math.multiplyExact((int)left.constant, (int)right.constant); + constant = (int)left.constant * (int)right.constant; } else if (sort == Sort.LONG) { - constant = overflow ? (long)left.constant * (long)right.constant : - Math.multiplyExact((long)left.constant, (long)right.constant); + constant = (long)left.constant * (long)right.constant; } else if (sort == Sort.FLOAT) { - constant = overflow ? (float)left.constant * (float)right.constant : - org.elasticsearch.painless.Utility.multiplyWithoutOverflow((float)left.constant, (float)right.constant); + constant = (float)left.constant * (float)right.constant; } else if (sort == Sort.DOUBLE) { - constant = overflow ? (double)left.constant * (double)right.constant : - org.elasticsearch.painless.Utility.multiplyWithoutOverflow((double)left.constant, (double)right.constant); + constant = (double)left.constant * (double)right.constant; } else { throw new IllegalStateException(error("Illegal tree structure.")); } @@ -135,21 +130,16 @@ public final class EBinary extends AExpression { right = right.cast(settings, definition, variables); if (left.constant != null && right.constant != null) { - final boolean overflow = settings.getNumericOverflow(); final Sort sort = promote.sort; if (sort == Sort.INT) { - constant = overflow ? (int)left.constant / (int)right.constant : - org.elasticsearch.painless.Utility.divideWithoutOverflow((int)left.constant, (int)right.constant); + constant = (int)left.constant / (int)right.constant; } else if (sort == Sort.LONG) { - constant = overflow ? (long)left.constant / (long)right.constant : - org.elasticsearch.painless.Utility.divideWithoutOverflow((long)left.constant, (long)right.constant); + constant = (long)left.constant / (long)right.constant; } else if (sort == Sort.FLOAT) { - constant = overflow ? (float)left.constant / (float)right.constant : - org.elasticsearch.painless.Utility.divideWithoutOverflow((float)left.constant, (float)right.constant); + constant = (float)left.constant / (float)right.constant; } else if (sort == Sort.DOUBLE) { - constant = overflow ? (double)left.constant / (double)right.constant : - org.elasticsearch.painless.Utility.divideWithoutOverflow((double)left.constant, (double)right.constant); + constant = (double)left.constant / (double)right.constant; } else { throw new IllegalStateException(error("Illegal tree structure.")); } @@ -176,7 +166,6 @@ public final class EBinary extends AExpression { right = right.cast(settings, definition, variables); if (left.constant != null && right.constant != null) { - final boolean overflow = settings.getNumericOverflow(); final Sort sort = promote.sort; if (sort == Sort.INT) { @@ -184,11 +173,9 @@ public final class EBinary extends AExpression { } else if (sort == Sort.LONG) { constant = (long)left.constant % (long)right.constant; } else if (sort == Sort.FLOAT) { - constant = overflow ? (float)left.constant % (float)right.constant : - org.elasticsearch.painless.Utility.remainderWithoutOverflow((float)left.constant, (float)right.constant); + constant = (float)left.constant % (float)right.constant; } else if (sort == Sort.DOUBLE) { - constant = overflow ? (double)left.constant % (double)right.constant : - org.elasticsearch.painless.Utility.remainderWithoutOverflow((double)left.constant, (double)right.constant); + constant = (double)left.constant % (double)right.constant; } else { throw new IllegalStateException(error("Illegal tree structure.")); } @@ -231,20 +218,14 @@ public final class EBinary extends AExpression { right = right.cast(settings, definition, variables); if (left.constant != null && right.constant != null) { - final boolean overflow = settings.getNumericOverflow(); - if (sort == Sort.INT) { - constant = overflow ? (int)left.constant + (int)right.constant : - Math.addExact((int)left.constant, (int)right.constant); + constant = (int)left.constant + (int)right.constant; } else if (sort == Sort.LONG) { - constant = overflow ? (long)left.constant + (long)right.constant : - Math.addExact((long)left.constant, (long)right.constant); + constant = (long)left.constant + (long)right.constant; } else if (sort == Sort.FLOAT) { - constant = overflow ? (float)left.constant + (float)right.constant : - org.elasticsearch.painless.Utility.addWithoutOverflow((float)left.constant, (float)right.constant); + constant = (float)left.constant + (float)right.constant; } else if (sort == Sort.DOUBLE) { - constant = overflow ? (double)left.constant + (double)right.constant : - org.elasticsearch.painless.Utility.addWithoutOverflow((double)left.constant, (double)right.constant); + constant = (double)left.constant + (double)right.constant; } else if (sort == Sort.STRING) { constant = "" + left.constant + right.constant; } else { @@ -273,21 +254,16 @@ public final class EBinary extends AExpression { right = right.cast(settings, definition, variables); if (left.constant != null && right.constant != null) { - final boolean overflow = settings.getNumericOverflow(); final Sort sort = promote.sort; if (sort == Sort.INT) { - constant = overflow ? (int)left.constant - (int)right.constant : - Math.subtractExact((int)left.constant, (int)right.constant); + constant = (int)left.constant - (int)right.constant; } else if (sort == Sort.LONG) { - constant = overflow ? (long)left.constant - (long)right.constant : - Math.subtractExact((long)left.constant, (long)right.constant); + constant = (long)left.constant - (long)right.constant; } else if (sort == Sort.FLOAT) { - constant = overflow ? (float)left.constant - (float)right.constant : - org.elasticsearch.painless.Utility.subtractWithoutOverflow((float)left.constant, (float)right.constant); + constant = (float)left.constant - (float)right.constant; } else if (sort == Sort.DOUBLE) { - constant = overflow ? (double)left.constant - (double)right.constant : - org.elasticsearch.painless.Utility.subtractWithoutOverflow((double)left.constant, (double)right.constant); + constant = (double)left.constant - (double)right.constant; } else { throw new IllegalStateException(error("Illegal tree structure.")); } @@ -519,7 +495,7 @@ public final class EBinary extends AExpression { left.write(settings, definition, adapter); right.write(settings, definition, adapter); - adapter.writeBinaryInstruction(settings, definition, location, actual, operation); + adapter.writeBinaryInstruction(definition, location, actual, operation); } adapter.writeBranch(tru, fals); diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EChain.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EChain.java index 763005d17ba..933295f9beb 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EChain.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EChain.java @@ -44,7 +44,6 @@ public final class EChain extends AExpression { boolean cat = false; Type promote = null; - boolean exact = false; Cast there = null; Cast back = null; @@ -208,9 +207,6 @@ public final class EChain extends AExpression { expression = expression.cast(settings, definition, variables); - exact = !settings.getNumericOverflow() && - (operation == Operation.MUL || operation == Operation.DIV || operation == Operation.REM || - operation == Operation.ADD || operation == Operation.SUB); there = AnalyzerCaster.getLegalCast(definition, location, last.after, promote, false); back = AnalyzerCaster.getLegalCast(definition, location, promote, last.after, true); @@ -293,11 +289,9 @@ public final class EChain extends AExpression { adapter.writeCast(there); expression.write(settings, definition, adapter); - adapter.writeBinaryInstruction(settings, definition, location, promote, operation); + adapter.writeBinaryInstruction(definition, location, promote, operation); - if (!exact || !adapter.writeExactInstruction(definition, promote.sort, link.after.sort)) { - adapter.writeCast(back); - } + adapter.writeCast(back); if (link.load && !post) { adapter.writeDup(link.after.sort.size, link.size); diff --git a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EUnary.java b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EUnary.java index cbf76373136..409d1081ae9 100644 --- a/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EUnary.java +++ b/modules/lang-painless/src/main/java/org/elasticsearch/painless/node/EUnary.java @@ -31,8 +31,6 @@ import org.elasticsearch.painless.MethodWriter; import static org.elasticsearch.painless.WriterConstants.DEF_NEG_CALL; import static org.elasticsearch.painless.WriterConstants.DEF_NOT_CALL; -import static org.elasticsearch.painless.WriterConstants.NEGATEEXACT_INT; -import static org.elasticsearch.painless.WriterConstants.NEGATEEXACT_LONG; /** * Represents a unary math expression. @@ -147,14 +145,13 @@ public final class EUnary extends AExpression { child = child.cast(settings, definition, variables); if (child.constant != null) { - final boolean overflow = settings.getNumericOverflow(); final Sort sort = promote.sort; if (sort == Sort.INT) { - constant = overflow ? -(int)child.constant : Math.negateExact((int)child.constant); + constant = -(int)child.constant; } else if (sort == Sort.LONG) { - constant = overflow ? -(long)child.constant : Math.negateExact((long)child.constant); + constant = -(long)child.constant; } else if (sort == Sort.FLOAT) { constant = -(float)child.constant; } else if (sort == Sort.DOUBLE) { @@ -211,17 +208,7 @@ public final class EUnary extends AExpression { if (sort == Sort.DEF) { adapter.invokeStatic(definition.getType("Def").type, DEF_NEG_CALL); } else { - if (settings.getNumericOverflow()) { - adapter.math(MethodWriter.NEG, type); - } else { - if (sort == Sort.INT) { - adapter.invokeStatic(definition.getType("Math").type, NEGATEEXACT_INT); - } else if (sort == Sort.LONG) { - adapter.invokeStatic(definition.getType("Math").type, NEGATEEXACT_LONG); - } else { - throw new IllegalStateException(error("Illegal tree structure.")); - } - } + adapter.math(MethodWriter.NEG, type); } } else if (operation != Operation.ADD) { throw new IllegalStateException(error("Illegal tree structure.")); diff --git a/modules/lang-painless/src/test/java/org/elasticsearch/painless/FloatOverflowDisabledTests.java b/modules/lang-painless/src/test/java/org/elasticsearch/painless/FloatOverflowDisabledTests.java deleted file mode 100644 index 7bec0b110df..00000000000 --- a/modules/lang-painless/src/test/java/org/elasticsearch/painless/FloatOverflowDisabledTests.java +++ /dev/null @@ -1,293 +0,0 @@ -/* - * Licensed to Elasticsearch under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.elasticsearch.painless; - -import java.util.Collections; -import java.util.Map; - -/** Tests floating point overflow with numeric overflow disabled */ -public class FloatOverflowDisabledTests extends ScriptTestCase { - - /** wire overflow to false for all tests */ - @Override - public Object exec(String script, Map vars) { - return exec(script, vars, Collections.singletonMap(CompilerSettings.NUMERIC_OVERFLOW, "false")); - } - - public void testAssignmentAdditionOverflow() { - // float - try { - exec("float x = 3.4028234663852886E38f; x += 3.4028234663852886E38f; return x;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - try { - exec("float x = -3.4028234663852886E38f; x += -3.4028234663852886E38f; return x;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - - // double - try { - exec("double x = 1.7976931348623157E308; x += 1.7976931348623157E308; return x;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - try { - exec("double x = -1.7976931348623157E308; x += -1.7976931348623157E308; return x;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - } - - public void testAssignmentSubtractionOverflow() { - // float - try { - exec("float x = 3.4028234663852886E38f; x -= -3.4028234663852886E38f; return x;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - try { - exec("float x = -3.4028234663852886E38f; x -= 3.4028234663852886E38f; return x;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - - // double - try { - exec("double x = 1.7976931348623157E308; x -= -1.7976931348623157E308; return x;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - try { - exec("double x = -1.7976931348623157E308; x -= 1.7976931348623157E308; return x;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - } - - public void testAssignmentMultiplicationOverflow() { - // float - try { - exec("float x = 3.4028234663852886E38f; x *= 3.4028234663852886E38f; return x;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - try { - exec("float x = 3.4028234663852886E38f; x *= -3.4028234663852886E38f; return x;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - - // double - try { - exec("double x = 1.7976931348623157E308; x *= 1.7976931348623157E308; return x;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - try { - exec("double x = 1.7976931348623157E308; x *= -1.7976931348623157E308; return x;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - } - - public void testAssignmentDivisionOverflow() { - // float - try { - exec("float x = 3.4028234663852886E38f; x /= 1.401298464324817E-45f; return x;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - try { - exec("float x = 3.4028234663852886E38f; x /= -1.401298464324817E-45f; return x;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - try { - exec("float x = 1.0f; x /= 0.0f; return x;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - - // double - try { - exec("double x = 1.7976931348623157E308; x /= 4.9E-324; return x;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - try { - exec("double x = 1.7976931348623157E308; x /= -4.9E-324; return x;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - try { - exec("double x = 1.0f; x /= 0.0; return x;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - } - - public void testAddition() throws Exception { - try { - exec("float x = 3.4028234663852886E38f; float y = 3.4028234663852886E38f; return x + y;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - try { - exec("double x = 1.7976931348623157E308; double y = 1.7976931348623157E308; return x + y;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - } - - public void testAdditionConst() throws Exception { - try { - exec("return 3.4028234663852886E38f + 3.4028234663852886E38f;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - try { - exec("return 1.7976931348623157E308 + 1.7976931348623157E308;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - } - - public void testSubtraction() throws Exception { - try { - exec("float x = -3.4028234663852886E38f; float y = 3.4028234663852886E38f; return x - y;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - try { - exec("double x = -1.7976931348623157E308; double y = 1.7976931348623157E308; return x - y;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - } - - public void testSubtractionConst() throws Exception { - try { - exec("return -3.4028234663852886E38f - 3.4028234663852886E38f;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - try { - exec("return -1.7976931348623157E308 - 1.7976931348623157E308;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - } - - public void testMultiplication() throws Exception { - try { - exec("float x = 3.4028234663852886E38f; float y = 3.4028234663852886E38f; return x * y;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - try { - exec("double x = 1.7976931348623157E308; double y = 1.7976931348623157E308; return x * y;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - } - - public void testMultiplicationConst() throws Exception { - try { - exec("return 3.4028234663852886E38f * 3.4028234663852886E38f;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - try { - exec("return 1.7976931348623157E308 * 1.7976931348623157E308;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - } - - public void testDivision() throws Exception { - try { - exec("float x = 3.4028234663852886E38f; float y = 1.401298464324817E-45f; return x / y;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - try { - exec("float x = 1.0f; float y = 0.0f; return x / y;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - try { - exec("double x = 1.7976931348623157E308; double y = 4.9E-324; return x / y;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - try { - exec("double x = 1.0; double y = 0.0; return x / y;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - } - - public void testDivisionConst() throws Exception { - try { - exec("return 3.4028234663852886E38f / 1.401298464324817E-45f;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - try { - exec("return 1.0f / 0.0f;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - try { - exec("return 1.7976931348623157E308 / 4.9E-324;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - try { - exec("return 1.0 / 0.0;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - } - - public void testDivisionNaN() throws Exception { - // float division, constant division, and assignment - try { - exec("float x = 0f; float y = 0f; return x / y;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - try { - exec("return 0f / 0f;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - try { - exec("float x = 0f; x /= 0f; return x;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - - // double division, constant division, and assignment - try { - exec("double x = 0.0; double y = 0.0; return x / y;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - try { - exec("return 0.0 / 0.0;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - try { - exec("double x = 0.0; x /= 0.0; return x;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - } - - public void testRemainderNaN() throws Exception { - // float division, constant division, and assignment - try { - exec("float x = 1f; float y = 0f; return x % y;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - try { - exec("return 1f % 0f;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - try { - exec("float x = 1f; x %= 0f; return x;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - - // double division, constant division, and assignment - try { - exec("double x = 1.0; double y = 0.0; return x % y;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - try { - exec("return 1.0 % 0.0;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - try { - exec("double x = 1.0; x %= 0.0; return x;"); - fail("didn't hit expected exception"); - } catch (ArithmeticException expected) {} - } -} diff --git a/modules/lang-painless/src/test/java/org/elasticsearch/painless/FloatOverflowEnabledTests.java b/modules/lang-painless/src/test/java/org/elasticsearch/painless/FloatOverflowTests.java similarity index 94% rename from modules/lang-painless/src/test/java/org/elasticsearch/painless/FloatOverflowEnabledTests.java rename to modules/lang-painless/src/test/java/org/elasticsearch/painless/FloatOverflowTests.java index ccfd2232e88..4b3eb8f0e7f 100644 --- a/modules/lang-painless/src/test/java/org/elasticsearch/painless/FloatOverflowEnabledTests.java +++ b/modules/lang-painless/src/test/java/org/elasticsearch/painless/FloatOverflowTests.java @@ -19,17 +19,8 @@ package org.elasticsearch.painless; -import java.util.Collections; -import java.util.Map; - -/** Tests floating point overflow with numeric overflow enabled */ -public class FloatOverflowEnabledTests extends ScriptTestCase { - - /** wire overflow to true for all tests */ - @Override - public Object exec(String script, Map vars) { - return exec(script, vars, Collections.singletonMap(CompilerSettings.NUMERIC_OVERFLOW, "true")); - } +/** Tests floating point overflow cases */ +public class FloatOverflowTests extends ScriptTestCase { public void testAssignmentAdditionOverflow() { // float diff --git a/modules/lang-painless/src/test/java/org/elasticsearch/painless/IntegerOverflowDisabledTests.java b/modules/lang-painless/src/test/java/org/elasticsearch/painless/IntegerOverflowDisabledTests.java deleted file mode 100644 index f4adcfce878..00000000000 --- a/modules/lang-painless/src/test/java/org/elasticsearch/painless/IntegerOverflowDisabledTests.java +++ /dev/null @@ -1,444 +0,0 @@ -/* - * Licensed to Elasticsearch under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.elasticsearch.painless; - -import java.util.Collections; -import java.util.Map; - -/** Tests integer overflow with numeric overflow disabled */ -public class IntegerOverflowDisabledTests extends ScriptTestCase { - - /** wire overflow to true for all tests */ - @Override - public Object exec(String script, Map vars) { - return exec(script, vars, Collections.singletonMap(CompilerSettings.NUMERIC_OVERFLOW, "false")); - } - - public void testAssignmentAdditionOverflow() { - // byte - try { - exec("byte x = 0; x += 128; return x;"); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - try { - exec("byte x = 0; x += -129; return x;"); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - // short - try { - exec("short x = 0; x += 32768; return x;"); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - try { - exec("byte x = 0; x += -32769; return x;"); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - // char - try { - exec("char x = 0; x += 65536; return x;"); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - try { - exec("char x = 0; x += -65536; return x;"); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - // int - try { - exec("int x = 1; x += 2147483647; return x;"); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - try { - exec("int x = -2; x += -2147483647; return x;"); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - // long - try { - exec("long x = 1; x += 9223372036854775807L; return x;"); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - try { - exec("long x = -2; x += -9223372036854775807L; return x;"); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - } - - public void testAssignmentSubtractionOverflow() { - // byte - try { - exec("byte x = 0; x -= -128; return x;"); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - try { - exec("byte x = 0; x -= 129; return x;"); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - // short - try { - exec("short x = 0; x -= -32768; return x;"); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - try { - exec("byte x = 0; x -= 32769; return x;"); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - // char - try { - exec("char x = 0; x -= -65536; return x;"); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - try { - exec("char x = 0; x -= 65536; return x;"); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - // int - try { - exec("int x = 1; x -= -2147483647; return x;"); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - try { - exec("int x = -2; x -= 2147483647; return x;"); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - // long - try { - exec("long x = 1; x -= -9223372036854775807L; return x;"); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - try { - exec("long x = -2; x -= 9223372036854775807L; return x;"); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - } - - public void testAssignmentMultiplicationOverflow() { - // byte - try { - exec("byte x = 2; x *= 128; return x;"); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - try { - exec("byte x = 2; x *= -128; return x;"); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - // char - try { - exec("char x = 2; x *= 65536; return x;"); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - try { - exec("char x = 2; x *= -65536; return x;"); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - // int - try { - exec("int x = 2; x *= 2147483647; return x;"); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - try { - exec("int x = 2; x *= -2147483647; return x;"); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - // long - try { - exec("long x = 2; x *= 9223372036854775807L; return x;"); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - try { - exec("long x = 2; x *= -9223372036854775807L; return x;"); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - } - - public void testAssignmentDivisionOverflow() { - // byte - try { - exec("byte x = (byte) -128; x /= -1; return x;"); - fail("should have hit exception"); - } catch (ArithmeticException expected) {} - - // short - try { - exec("short x = (short) -32768; x /= -1; return x;"); - fail("should have hit exception"); - } catch (ArithmeticException expected) {} - - // cannot happen for char: unsigned - - // int - try { - exec("int x = -2147483647 - 1; x /= -1; return x;"); - fail("should have hit exception"); - } catch (ArithmeticException expected) {} - - // long - try { - exec("long x = -9223372036854775807L - 1L; x /=-1L; return x;"); - fail("should have hit exception"); - } catch (ArithmeticException expected) {} - } - - public void testIncrementOverFlow() throws Exception { - // byte - try { - exec("byte x = 127; ++x; return x;"); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - try { - exec("byte x = 127; x++; return x;"); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - try { - exec("byte x = (byte) -128; --x; return x;"); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - try { - exec("byte x = (byte) -128; x--; return x;"); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - // short - try { - exec("short x = 32767; ++x; return x;"); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - try { - exec("short x = 32767; x++; return x;"); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - try { - exec("short x = (short) -32768; --x; return x;"); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - try { - exec("short x = (short) -32768; x--; return x;"); - } catch (ArithmeticException expected) {} - - // char - try { - exec("char x = 65535; ++x; return x;"); - } catch (ArithmeticException expected) {} - - try { - exec("char x = 65535; x++; return x;"); - } catch (ArithmeticException expected) {} - - try { - exec("char x = (char) 0; --x; return x;"); - } catch (ArithmeticException expected) {} - - try { - exec("char x = (char) 0; x--; return x;"); - } catch (ArithmeticException expected) {} - - // int - try { - exec("int x = 2147483647; ++x; return x;"); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - try { - exec("int x = 2147483647; x++; return x;"); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - try { - exec("int x = (int) -2147483648L; --x; return x;"); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - try { - exec("int x = (int) -2147483648L; x--; return x;"); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - // long - try { - exec("long x = 9223372036854775807L; ++x; return x;"); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - try { - exec("long x = 9223372036854775807L; x++; return x;"); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - try { - exec("long x = -9223372036854775807L - 1L; --x; return x;"); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - try { - exec("long x = -9223372036854775807L - 1L; x--; return x;"); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - } - - public void testAddition() throws Exception { - try { - exec("int x = 2147483647; int y = 2147483647; return x + y;"); - fail("should have hit exception"); - } catch (ArithmeticException expected) {} - - try { - exec("long x = 9223372036854775807L; long y = 9223372036854775807L; return x + y;"); - fail("should have hit exception"); - } catch (ArithmeticException expected) {} - } - - public void testAdditionConst() throws Exception { - try { - exec("return 2147483647 + 2147483647;"); - fail("should have hit exception"); - } catch (ArithmeticException expected) {} - - try { - exec("return 9223372036854775807L + 9223372036854775807L;"); - fail("should have hit exception"); - } catch (ArithmeticException expected) {} - } - - - public void testSubtraction() throws Exception { - try { - exec("int x = -10; int y = 2147483647; return x - y;"); - fail("should have hit exception"); - } catch (ArithmeticException expected) {} - - try { - exec("long x = -10L; long y = 9223372036854775807L; return x - y;"); - fail("should have hit exception"); - } catch (ArithmeticException expected) {} - } - - public void testSubtractionConst() throws Exception { - try { - exec("return -10 - 2147483647;"); - fail("should have hit exception"); - } catch (ArithmeticException expected) {} - - try { - exec("return -10L - 9223372036854775807L;"); - fail("should have hit exception"); - } catch (ArithmeticException expected) {} - } - - public void testMultiplication() throws Exception { - try { - exec("int x = 2147483647; int y = 2147483647; return x * y;"); - fail("should have hit exception"); - } catch (ArithmeticException expected) {} - - try { - exec("long x = 9223372036854775807L; long y = 9223372036854775807L; return x * y;"); - fail("should have hit exception"); - } catch (ArithmeticException expected) {} - } - - public void testMultiplicationConst() throws Exception { - try { - exec("return 2147483647 * 2147483647;"); - fail("should have hit exception"); - } catch (ArithmeticException expected) {} - - try { - exec("return 9223372036854775807L * 9223372036854775807L;"); - fail("should have hit exception"); - } catch (ArithmeticException expected) {} - } - - public void testDivision() throws Exception { - try { - exec("int x = -2147483647 - 1; int y = -1; return x / y;"); - fail("should have hit exception"); - } catch (ArithmeticException expected) {} - - try { - exec("long x = -9223372036854775808L; long y = -1L; return x / y;"); - fail("should have hit exception"); - } catch (ArithmeticException expected) {} - } - - public void testDivisionConst() throws Exception { - try { - exec("return (-2147483648) / -1;"); - fail("should have hit exception"); - } catch (ArithmeticException expected) {} - - try { - exec("return (-9223372036854775808L) / -1L;"); - fail("should have hit exception"); - } catch (ArithmeticException expected) {} - } - - public void testNegationOverflow() throws Exception { - try { - exec("int x = -2147483648; x = -x; return x;"); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - try { - exec("long x = -9223372036854775808L; x = -x; return x;"); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - } - - public void testNegationOverflowConst() throws Exception { - try { - exec("int x = -(-2147483648); return x;"); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - try { - exec("long x = -(-9223372036854775808L); return x;"); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - } -} diff --git a/modules/lang-painless/src/test/java/org/elasticsearch/painless/IntegerOverflowEnabledTests.java b/modules/lang-painless/src/test/java/org/elasticsearch/painless/IntegerOverflowTests.java similarity index 95% rename from modules/lang-painless/src/test/java/org/elasticsearch/painless/IntegerOverflowEnabledTests.java rename to modules/lang-painless/src/test/java/org/elasticsearch/painless/IntegerOverflowTests.java index 41b3f857c0a..1165547bf5a 100644 --- a/modules/lang-painless/src/test/java/org/elasticsearch/painless/IntegerOverflowEnabledTests.java +++ b/modules/lang-painless/src/test/java/org/elasticsearch/painless/IntegerOverflowTests.java @@ -19,17 +19,8 @@ package org.elasticsearch.painless; -import java.util.Collections; -import java.util.Map; - -/** Tests integer overflow with numeric overflow enabled */ -public class IntegerOverflowEnabledTests extends ScriptTestCase { - - /** wire overflow to true for all tests */ - @Override - public Object exec(String script, Map vars) { - return exec(script, vars, Collections.singletonMap(CompilerSettings.NUMERIC_OVERFLOW, "true")); - } +/** Tests integer overflow cases */ +public class IntegerOverflowTests extends ScriptTestCase { public void testAssignmentAdditionOverflow() { // byte diff --git a/modules/lang-painless/src/test/java/org/elasticsearch/painless/ScriptTestCase.java b/modules/lang-painless/src/test/java/org/elasticsearch/painless/ScriptTestCase.java index 2ccd2f1460a..c3ce127034e 100644 --- a/modules/lang-painless/src/test/java/org/elasticsearch/painless/ScriptTestCase.java +++ b/modules/lang-painless/src/test/java/org/elasticsearch/painless/ScriptTestCase.java @@ -48,7 +48,7 @@ public abstract class ScriptTestCase extends ESTestCase { /** Compiles and returns the result of {@code script} with access to {@code vars} */ public Object exec(String script, Map vars) { - return exec(script, vars, Collections.singletonMap(CompilerSettings.NUMERIC_OVERFLOW, Boolean.toString(random().nextBoolean()))); + return exec(script, vars, Collections.emptyMap()); } /** Compiles and returns the result of {@code script} with access to {@code vars} and compile-time parameters */ diff --git a/modules/lang-painless/src/test/java/org/elasticsearch/painless/UtilityTests.java b/modules/lang-painless/src/test/java/org/elasticsearch/painless/UtilityTests.java deleted file mode 100644 index ba476fac7f2..00000000000 --- a/modules/lang-painless/src/test/java/org/elasticsearch/painless/UtilityTests.java +++ /dev/null @@ -1,250 +0,0 @@ -/* - * Licensed to Elasticsearch under one or more contributor - * license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright - * ownership. Elasticsearch licenses this file to you under - * the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package org.elasticsearch.painless; - -import org.elasticsearch.test.ESTestCase; - -/** - * Tests utility methods (typically built-ins) - */ -public class UtilityTests extends ESTestCase { - - public void testDivideWithoutOverflowInt() { - assertEquals(5 / 2, Utility.divideWithoutOverflow(5, 2)); - - try { - Utility.divideWithoutOverflow(Integer.MIN_VALUE, -1); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - try { - Utility.divideWithoutOverflow(5, 0); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - } - - public void testDivideWithoutOverflowLong() { - assertEquals(5L / 2L, Utility.divideWithoutOverflow(5L, 2L)); - - try { - Utility.divideWithoutOverflow(Long.MIN_VALUE, -1L); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - try { - Utility.divideWithoutOverflow(5L, 0L); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - } - - public void testToByteExact() { - for (int b = Byte.MIN_VALUE; b < Byte.MAX_VALUE; b++) { - assertEquals((byte)b, Utility.toByteExact(b)); - } - - try { - Utility.toByteExact(Byte.MIN_VALUE - 1); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - try { - Utility.toByteExact(Byte.MAX_VALUE + 1); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - } - - public void testToShortExact() { - for (int s = Short.MIN_VALUE; s < Short.MAX_VALUE; s++) { - assertEquals((short)s, Utility.toShortExact(s)); - } - - try { - Utility.toShortExact(Short.MIN_VALUE - 1); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - try { - Utility.toShortExact(Short.MAX_VALUE + 1); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - } - - public void testToCharExact() { - for (int c = Character.MIN_VALUE; c < Character.MAX_VALUE; c++) { - assertEquals((char)c, Utility.toCharExact(c)); - } - - try { - Utility.toCharExact(Character.MIN_VALUE - 1); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - try { - Utility.toCharExact(Character.MAX_VALUE + 1); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - } - - public void testAddWithoutOverflowFloat() { - assertEquals(10F, Utility.addWithoutOverflow(5F, 5F), 0F); - assertTrue(Float.isNaN(Utility.addWithoutOverflow(5F, Float.NaN))); - assertTrue(Float.isNaN(Utility.addWithoutOverflow(Float.POSITIVE_INFINITY, Float.NEGATIVE_INFINITY))); - - try { - Utility.addWithoutOverflow(Float.MAX_VALUE, Float.MAX_VALUE); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - try { - Utility.addWithoutOverflow(-Float.MAX_VALUE, -Float.MAX_VALUE); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - } - - public void testAddWithoutOverflowDouble() { - assertEquals(10D, Utility.addWithoutOverflow(5D, 5D), 0D); - assertTrue(Double.isNaN(Utility.addWithoutOverflow(5D, Double.NaN))); - assertTrue(Double.isNaN(Utility.addWithoutOverflow(Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY))); - - try { - Utility.addWithoutOverflow(Double.MAX_VALUE, Double.MAX_VALUE); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - try { - Utility.addWithoutOverflow(-Double.MAX_VALUE, -Double.MAX_VALUE); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - } - - public void testSubtractWithoutOverflowFloat() { - assertEquals(5F, Utility.subtractWithoutOverflow(10F, 5F), 0F); - assertTrue(Float.isNaN(Utility.subtractWithoutOverflow(5F, Float.NaN))); - assertTrue(Float.isNaN(Utility.subtractWithoutOverflow(Float.POSITIVE_INFINITY, Float.POSITIVE_INFINITY))); - - try { - Utility.subtractWithoutOverflow(Float.MAX_VALUE, -Float.MAX_VALUE); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - try { - Utility.subtractWithoutOverflow(-Float.MAX_VALUE, Float.MAX_VALUE); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - } - - public void testSubtractWithoutOverflowDouble() { - assertEquals(5D, Utility.subtractWithoutOverflow(10D, 5D), 0D); - assertTrue(Double.isNaN(Utility.subtractWithoutOverflow(5D, Double.NaN))); - assertTrue(Double.isNaN(Utility.subtractWithoutOverflow(Double.POSITIVE_INFINITY, Double.POSITIVE_INFINITY))); - - try { - Utility.subtractWithoutOverflow(Double.MAX_VALUE, -Double.MAX_VALUE); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - try { - Utility.subtractWithoutOverflow(-Double.MAX_VALUE, Double.MAX_VALUE); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - } - - public void testMultiplyWithoutOverflowFloat() { - assertEquals(25F, Utility.multiplyWithoutOverflow(5F, 5F), 0F); - assertTrue(Float.isNaN(Utility.multiplyWithoutOverflow(5F, Float.NaN))); - assertEquals(Float.POSITIVE_INFINITY, Utility.multiplyWithoutOverflow(5F, Float.POSITIVE_INFINITY), 0F); - - try { - Utility.multiplyWithoutOverflow(Float.MAX_VALUE, Float.MAX_VALUE); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - } - - public void testMultiplyWithoutOverflowDouble() { - assertEquals(25D, Utility.multiplyWithoutOverflow(5D, 5D), 0D); - assertTrue(Double.isNaN(Utility.multiplyWithoutOverflow(5D, Double.NaN))); - assertEquals(Double.POSITIVE_INFINITY, Utility.multiplyWithoutOverflow(5D, Double.POSITIVE_INFINITY), 0D); - - try { - Utility.multiplyWithoutOverflow(Double.MAX_VALUE, Double.MAX_VALUE); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - } - - public void testDivideWithoutOverflowFloat() { - assertEquals(5F, Utility.divideWithoutOverflow(25F, 5F), 0F); - assertTrue(Float.isNaN(Utility.divideWithoutOverflow(5F, Float.NaN))); - assertEquals(Float.POSITIVE_INFINITY, Utility.divideWithoutOverflow(Float.POSITIVE_INFINITY, 5F), 0F); - - try { - Utility.divideWithoutOverflow(Float.MAX_VALUE, Float.MIN_VALUE); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - try { - Utility.divideWithoutOverflow(0F, 0F); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - try { - Utility.divideWithoutOverflow(5F, 0F); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - } - - public void testDivideWithoutOverflowDouble() { - assertEquals(5D, Utility.divideWithoutOverflow(25D, 5D), 0D); - assertTrue(Double.isNaN(Utility.divideWithoutOverflow(5D, Double.NaN))); - assertEquals(Double.POSITIVE_INFINITY, Utility.divideWithoutOverflow(Double.POSITIVE_INFINITY, 5D), 0D); - - try { - Utility.divideWithoutOverflow(Double.MAX_VALUE, Double.MIN_VALUE); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - try { - Utility.divideWithoutOverflow(0D, 0D); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - - try { - Utility.divideWithoutOverflow(5D, 0D); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - } - - public void testRemainderWithoutOverflowFloat() { - assertEquals(1F, Utility.remainderWithoutOverflow(25F, 4F), 0F); - - try { - Utility.remainderWithoutOverflow(5F, 0F); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - } - - public void testRemainderWithoutOverflowDouble() { - assertEquals(1D, Utility.remainderWithoutOverflow(25D, 4D), 0D); - - try { - Utility.remainderWithoutOverflow(5D, 0D); - fail("did not get expected exception"); - } catch (ArithmeticException expected) {} - } -}