apache / apache/arrow

[C++][Gandiva] Out-of-bounds read in round(int, precision) for the most negative precision

Open
#50,544 0 comments 0 reactions 1 assignee Claimed by @Arawoof06 View on GitHub
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

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.