Skip to content

Commit 5cccabe

Browse files
authored
Improve error message for unparseable numeric settings (#115609) (#115718)
When a numeric setting is too large or too small such that it can't be parsed at all, the error message is the same as for garbage values. This commit improves the error message in these cases to be the same as for normal bounds checks. closes #115080
1 parent 5bfc1f1 commit 5cccabe

File tree

2 files changed

+84
-8
lines changed

2 files changed

+84
-8
lines changed

server/src/main/java/org/elasticsearch/common/settings/Setting.java

Lines changed: 50 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import org.elasticsearch.xcontent.XContentType;
3535

3636
import java.io.IOException;
37+
import java.math.BigInteger;
3738
import java.time.Instant;
3839
import java.util.Arrays;
3940
import java.util.Collections;
@@ -1507,27 +1508,68 @@ public static int parseInt(String s, int minValue, int maxValue, String key) {
15071508
}
15081509

15091510
public static int parseInt(String s, int minValue, int maxValue, String key, boolean isFiltered) {
1510-
int value = Integer.parseInt(s);
1511+
int value;
1512+
try {
1513+
value = Integer.parseInt(s);
1514+
} catch (NumberFormatException e) {
1515+
// check if value is a number or garbage
1516+
try {
1517+
var bi = new BigInteger(s);
1518+
// it's a number, so check which bound it is outside
1519+
if (bi.compareTo(BigInteger.valueOf(minValue)) < 0) {
1520+
throw newNumericBoundsException(s, key, isFiltered, ">=", minValue);
1521+
} else {
1522+
throw newNumericBoundsException(s, key, isFiltered, "<=", maxValue);
1523+
}
1524+
} catch (NumberFormatException e2) {
1525+
throw e; // it's garbage, use the original exception
1526+
}
1527+
}
15111528
if (value < minValue) {
1512-
String err = "Failed to parse value" + (isFiltered ? "" : " [" + s + "]") + " for setting [" + key + "] must be >= " + minValue;
1513-
throw new IllegalArgumentException(err);
1529+
throw newNumericBoundsException(s, key, isFiltered, ">=", minValue);
15141530
}
15151531
if (value > maxValue) {
1516-
String err = "Failed to parse value" + (isFiltered ? "" : " [" + s + "]") + " for setting [" + key + "] must be <= " + maxValue;
1517-
throw new IllegalArgumentException(err);
1532+
throw newNumericBoundsException(s, key, isFiltered, "<=", maxValue);
15181533
}
15191534
return value;
15201535
}
15211536

15221537
static long parseLong(String s, long minValue, String key, boolean isFiltered) {
1523-
long value = Long.parseLong(s);
1538+
long value;
1539+
try {
1540+
value = Long.parseLong(s);
1541+
} catch (NumberFormatException e) {
1542+
// check if value is a number or garbage
1543+
try {
1544+
var bi = new BigInteger(s);
1545+
// it's a number, so check which bound it is outside
1546+
if (bi.compareTo(BigInteger.valueOf(minValue)) < 0) {
1547+
throw newNumericBoundsException(s, key, isFiltered, ">=", minValue);
1548+
} else {
1549+
throw newNumericBoundsException(s, key, isFiltered, "<=", Long.MAX_VALUE);
1550+
}
1551+
} catch (NumberFormatException e2) {
1552+
throw e; // it's garbage, use the original exception
1553+
}
1554+
}
15241555
if (value < minValue) {
1525-
String err = "Failed to parse value" + (isFiltered ? "" : " [" + s + "]") + " for setting [" + key + "] must be >= " + minValue;
1526-
throw new IllegalArgumentException(err);
1556+
throw newNumericBoundsException(s, key, isFiltered, ">=", minValue);
15271557
}
15281558
return value;
15291559
}
15301560

1561+
private static IllegalArgumentException newNumericBoundsException(String s, String key, boolean isFiltered, String type, long bound) {
1562+
String err = "Failed to parse value"
1563+
+ (isFiltered ? "" : " [" + s + "]")
1564+
+ " for setting ["
1565+
+ key
1566+
+ "] must be "
1567+
+ type
1568+
+ " "
1569+
+ bound;
1570+
throw new IllegalArgumentException(err);
1571+
}
1572+
15311573
public static Setting<Integer> intSetting(String key, int defaultValue, Property... properties) {
15321574
return intSetting(key, defaultValue, Integer.MIN_VALUE, properties);
15331575
}

server/src/test/java/org/elasticsearch/common/settings/SettingTests.java

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1522,4 +1522,38 @@ public void testDeprecationPropertyValidation() {
15221522
() -> Setting.boolSetting("a.bool.setting", true, Property.DeprecatedWarning, Property.IndexSettingDeprecatedInV7AndRemovedInV8)
15231523
);
15241524
}
1525+
1526+
public void testIntSettingBounds() {
1527+
Setting<Integer> setting = Setting.intSetting("int.setting", 0, Integer.MIN_VALUE, Integer.MAX_VALUE);
1528+
var e = expectThrows(
1529+
IllegalArgumentException.class,
1530+
() -> setting.get(Settings.builder().put("int.setting", "2147483648").build())
1531+
);
1532+
assertThat(e.getMessage(), equalTo("Failed to parse value [2147483648] for setting [int.setting] must be <= 2147483647"));
1533+
var e2 = expectThrows(
1534+
IllegalArgumentException.class,
1535+
() -> setting.get(Settings.builder().put("int.setting", "-2147483649").build())
1536+
);
1537+
assertThat(e2.getMessage(), equalTo("Failed to parse value [-2147483649] for setting [int.setting] must be >= -2147483648"));
1538+
}
1539+
1540+
public void testLongSettingBounds() {
1541+
Setting<Long> setting = Setting.longSetting("long.setting", 0, Long.MIN_VALUE);
1542+
var e = expectThrows(
1543+
IllegalArgumentException.class,
1544+
() -> setting.get(Settings.builder().put("long.setting", "9223372036854775808").build())
1545+
);
1546+
assertThat(
1547+
e.getMessage(),
1548+
equalTo("Failed to parse value [9223372036854775808] for setting [long.setting] must be <= 9223372036854775807")
1549+
);
1550+
var e2 = expectThrows(
1551+
IllegalArgumentException.class,
1552+
() -> setting.get(Settings.builder().put("long.setting", "-9223372036854775809").build())
1553+
);
1554+
assertThat(
1555+
e2.getMessage(),
1556+
equalTo("Failed to parse value [-9223372036854775809] for setting [long.setting] must be >= -9223372036854775808")
1557+
);
1558+
}
15251559
}

0 commit comments

Comments
 (0)