Skip to content

Commit 5ad714b

Browse files
Fix numeric overflow in JSON integral coercion and add tests
1 parent adc1f7e commit 5ad714b

3 files changed

Lines changed: 25 additions & 3 deletions

File tree

java/src/org/openqa/selenium/json/JsonInput.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,7 @@ public Number nextNumber() {
263263
return Long.valueOf(builder.toString());
264264
}
265265

266-
return new BigDecimal(builder.toString());
266+
return new BigDecimal(builder.toString()).doubleValue();
267267
} catch (NumberFormatException e) {
268268
throw new JsonException("Unable to parse to a number: " + builder + ". " + input, e);
269269
}

java/src/org/openqa/selenium/json/NumberCoercer.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,9 @@ public BiFunction<JsonInput, PropertySetting, T> apply(Type ignored) {
8888
}
8989

9090
private static void validateIntegralRange(Number number, Class<?> stereotype) {
91-
// Only for integral targets
91+
// Prevent silent overflow when JSON numbers are coerced to integral types.
92+
// Java's Number.intValue()/longValue() silently wraps values outside the
93+
// valid range, which previously produced incorrect results instead of errors.
9294
if (!(stereotype == Byte.class
9395
|| stereotype == Short.class
9496
|| stereotype == Integer.class
@@ -98,7 +100,7 @@ private static void validateIntegralRange(Number number, Class<?> stereotype) {
98100

99101
final BigInteger value;
100102
try {
101-
// Parses "2147483648", "1e3", "1.0" safely; rejects "1.2"
103+
// Use BigDecimal so we can reject fractional values and validate range before coercion.
102104
BigDecimal bd =
103105
(number instanceof BigDecimal) ? (BigDecimal) number : new BigDecimal(number.toString());
104106
value = bd.toBigIntegerExact();

java/test/org/openqa/selenium/json/JsonTest.java

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,26 @@ void canReadANumber() {
7272
assertThat((Double) new Json().toType("4.2e-1", Double.class)).isEqualTo(0.42);
7373
}
7474

75+
@Test
76+
void shouldRejectIntegerOverflow() {
77+
Json json = new Json();
78+
79+
assertThatExceptionOfType(JsonException.class)
80+
.isThrownBy(() -> json.toType("2147483648", Integer.class))
81+
.withMessageContaining("out of range")
82+
.withMessageContaining("Integer");
83+
}
84+
85+
@Test
86+
void shouldRejectFractionalValueForInteger() {
87+
Json json = new Json();
88+
89+
assertThatExceptionOfType(JsonException.class)
90+
.isThrownBy(() -> json.toType("1.2", Integer.class))
91+
.withMessageContaining("Expected an integer value")
92+
.withMessageContaining("Integer");
93+
}
94+
7595
@Test
7696
void canRoundTripNumbers() {
7797
Map<String, Object> original = Map.of("options", Map.of("args", List.of(1L, "hello")));

0 commit comments

Comments
 (0)