Skip to content

Jackson 3: numeric functions/operators throw on out-of-range values ($fromMillis, $sum, unary minus, range, array index) #433

Description

@wnm3

Summary

After the Jackson 3 migration (#430, PR #431), several numeric functions and operators call asInt()/asLong() on values that are outside int/long range. Jackson 3 makes these coercions fail‑fast — they throw tools.jackson.databind.node.JsonNodeException for out‑of‑range DoubleNode/BigIntegerNode values. Jackson 2 silently narrowed (a plain cast), so these paths previously produced a (possibly wrong but non‑throwing) value or a controlled JSONata error. The lines were not changed by the migration, so behavior flipped from "return/handle" to "crash".

Not caught by the test suite — no test exercises out‑of‑range magnitudes at these sites.

Where & reproductions

Site Code Repro Jackson 2 Jackson 3
ExpressionsVisitor.java:381 isWholeNumber n.asInt() == n.asDouble() [1..1e19] (range bound) returns false → controlled "must be an integer" error throws raw JsonNodeException
ExpressionsVisitor.java:994 (array index) indexInContext.asInt() ["a","b"][3000000000] narrows → harmless out‑of‑bounds throws
ExpressionsVisitor.java:2919/2925 (unary minus) operand.asLong() on BigIntegerNode -99999999999999999999999999 narrowed long throws
FromMillisFunction.java:90 argNumber.asLong() (guarded only by isNumber()) $fromMillis(1e30) narrowed → wrong date throws
FromMillisZonedFunction.java:90 argNumber.asLong() $fromMillisTz(1e30, '[Y]') narrowed throws
SumFunction.java:95 and :107 a.asLong() / argArray.asLong() on out‑of‑range BigIntegerNode $sum([99999999999999999999999999]) narrowed throws

Verified empirically against jackson‑databind 3.2.0

DoubleNode(1.0E46).asInt()   -> THROWS JsonNodeException
DoubleNode(1.0E46).asLong()  -> THROWS JsonNodeException
BigIntegerNode(99999999999999999999).asLong() -> THROWS JsonNodeException
LongNode(3000000000).asInt() -> THROWS JsonNodeException

Suggested fix

Before calling asInt()/asLong() at these sites, pre‑check magnitude (canConvertToInt() / canConvertToLong()) or operate on doubleValue()/bigIntegerValue() and range‑check, restoring the Jackson‑2 narrowing (or converting to the appropriate controlled JSONata error) rather than allowing a raw JsonNodeException to escape. This mirrors the guard already applied to AgnosticTestSuite's (long) d fix in this migration.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions