LuciferYang opened a new pull request, #878:
URL: https://github.com/apache/iceberg-cpp/pull/878
## What
`LiteralFromJson` accepted JSON integers beyond the signed 64-bit range and
produced a wrong literal instead of a parse error. nlohmann reports unsigned
integers as `is_number_integer()`, and `get<int64_t>()` converts values above
INT64_MAX silently rather than throwing, so the `kInt` branch ran its int32
range check on the already-wrapped value and the `kLong` branch had no range
check at all. `18446744073709551615` parsed as `Literal::Int(-1)`, and
`9223372036854775808` as `Literal::Long(INT64_MIN)`. The untyped overload had
the same hole.
The live consequence is on table metadata: `initial-default` /
`write-default` go through this parser, `ValidateDefault` has no integer range
check, and the value is later materialized into a returned column. A metadata
file that Java rejects reads back as `-1` in C++. The expression path is latent
for now, since no reader evaluates `ReaderOptions::filter` yet.
Fixes #877.
## How
Added `GetInt64Checked`, which rejects unsigned nodes above INT64_MAX before
the conversion, and called it from the `kInt` branch, the `kLong` branch, and
the untyped overload. This mirrors Java, where `SingleValueParser` and
`ExpressionParser` guard the same paths with `canConvertToInt()` /
`canConvertToLong()`.
The `is_number_unsigned()` half of the guard is load-bearing:
`get<uint64_t>()` on a negative node yields its two's-complement value, which
compares above INT64_MAX and would reject every negative literal. Both halves
now have accept-side tests.
Also in this PR, both on lines the fix touches: the int32 narrowing on the
`kInt` path gained the coverage it never had, and the two out-of-range messages
now use one wording instead of saying "int" in one place and "long" in the
other.
## Testing
`expression_test` 526 tests and the full `ctest` suite (18/18) pass. Each
new test was checked against a mutation of the code it guards:
- `>` changed to `>=` in the guard: only `LongMax` fails (the `ULL` suffix
there is load-bearing, a signed INT64_MAX node would skip the unsigned branch
entirely).
- `is_number_unsigned() &&` dropped: `LongMin`, `IntNegative` and
`AcceptsNegativeIntegerUntyped` fail.
- int32 range check deleted: `IntAboveInt32Max` and `IntBelowInt32Min` fail.
Verified fail-without / pass-with for the three overflow-rejection cases as
well.
## Out of scope
`GetTypedJsonValue` in `src/iceberg/util/json_util_internal.h` truncates
out-of-range integers the same way, so `FieldFromJson({"id": 2147483648, ...})`
yields `field_id = -2147483648` silently. That helper has on the order of 80
call sites and is left for a follow-up rather than widened into this PR.
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]