Skip to content

Fix silent numeric overflow in argument and input binding - #2783

Open
RoMiRoSSaN wants to merge 2 commits into
smallrye:mainfrom
RoMiRoSSaN:number_fix
Open

RoMiRoSSaN wants to merge 2 commits into
smallrye:mainfrom
RoMiRoSSaN:number_fix

Conversation

@RoMiRoSSaN

Copy link
Copy Markdown
Contributor

Fixes #2781

Changes

  • IntegerScalar: the range check is exact and includes both bounds. Int.MIN_VALUE is accepted.
  • Integer targets (byte, short, int, long, atomic and Optional* wrappers): the conversion is exact. intValue() and casts are replaced with *ValueExact, so overflow and fractions return a GraphQL error.
  • Floating-point targets (float, double, OptionalDouble): NaN, Infinity and finite overflow return a GraphQL error. Normal IEEE rounding is kept.
  • Input objects (records, POJOs, nested objects, lists): numeric fields are checked before JSON binding. Each field's number type is resolved once, when the schema is built.
  • Missing OptionalInt / OptionalLong / OptionalDouble arguments: passed as Optional*.empty() instead of null.
  • Unchanged: BigInteger, BigDecimal and the schema.
// before
return bigInteger.intValue();
return (byte) input.intValue();

// after
return bigInteger.intValueExact();
return input instanceof Byte ? input : byteValueExact(input);

Before / after

Java parameter Input Before After
int 2147483648 method receives -2147483648 error
int -2147483648 error method receives -2147483648
int variable 1.5 method receives 1 error
byte 128 method receives -128 error
long variable 9223372036854775808 method receives -9223372036854775808 error
float 1e39 method receives Infinity error
record with int field -99999999999999999999999999999 method receives 1610612737, or an unrelated Unknown Scalar Type error error naming the field

Example error after the fix:

Validation error (WrongType@[primitiveInt]) : argument 'input' with value 'IntValue{value=2147483648}'
is not a valid 'Int' - SRGQL000014: Expected value to be in the Int range but it was 'IntValue{value=2147483648}'

@jmartisk

Copy link
Copy Markdown
Member

Thanks! Can you have a look at the failing tests please?

Reject out-of-range numbers instead of silently wrapping them, and accept
Int.MIN_VALUE. Narrowing to Java numeric types is exact, including fields
of input objects; overflow, fractions and non-finite floats are errors.

Preserve converted numeric default values in SDL and introspection.
Distinguish fractional Int literals from values outside the Int range.

Cover numeric bindings, literal conversion, default values and diagnostics
with regression tests.
phillip-kruger
phillip-kruger previously approved these changes Nov 13, 2026

@phillip-kruger phillip-kruger left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CI is green on the current head, and server/implementation passes locally (1622 tests).

One thing for the description, so it ends up in the release notes: this also changes output, not just input binding. NumberCoercing.serialize now rejects NaN/Infinity on Float fields, and fractions or out-of-range values on Int fields. A resolver that used to return Double.NaN will now get a field error. That's correct per the spec, but users will notice it, so please mention it in the PR description.

server/implementation/src/main/java/io/smallrye/graphql/scalar/number/NumberCoercing.java line 592:

serialize now goes through the same exact and finite checks, so a resolver that returns NaN, Infinity or an out-of-range value now gets an error. That's spec-correct, but it changes behaviour on the output side, so please call it out in the PR description.

Skip the numeric component shortcut when a field has a transformation so
that NumberFormat still formats each array element as a string.

Cover primitive and boxed arrays, arrays inside lists, and null elements.
Characterize Optional argument, POJO field, and record component binding
without changing the existing Optional contract.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Numeric arguments silently overflow when converted to Java types

3 participants