[C++][Gandiva] Out-of-bounds read in round(int, precision) for the most negative precision
- Dominant language
- C++
- Stars
- 17.1k
- Forks
- 4.3k
- Avg merge
- 3d 13h
- Merged PRs (30d)
- 88
Description
Describe the bug, including details regarding any error messages, version, and platform.
`round_int32_int32` and `round_int64_int32` in `cpp/src/gandiva/precompiled/extended_math_ops.cc` negate the caller-supplied precision into `abs_precision` and only then apply the range check (`abs_precision > 9` and `abs_precision > 18` respectively).
For `precision == INT32_MIN` the negation leaves the value unchanged and still negative, so both range checks evaluate false. The negative value is then passed to `get_power_of_10`, which indexes a 19-element static table guarded only by `DCHECK_GE`/`DCHECK_LE`. Those compile out in release builds, so the read lands far outside the table.
Reachable from SQL as `round(int_col, -2147483648)`; both overloads are registered in `function_registry_arithmetic.cc`.
In a debug build the DCHECK fires:
```
extended_math_ops.cc:372: Check failed: (exp) >= (0)
```
In a release build there is no check and the indexed load faults or yields arbitrary memory as the rounding multiplier.
`truncate_int64_int32` in the same file already compares the signed scale directly (`out_scale < -38`) and is not affected.
Component(s)
C++ - Gandiva
Contributor guide
Assessment
This issue has not been assessed yet.