apache / apache/arrow

[C++] Out-of-bounds read in DecimalRescale for a scale delta larger than kMaxScale

Open
#50,964 0 comments 0 reactions 1 assignee Claimed by @Arawoof06 View on GitHub
Component: C++
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.

`DecimalRescale` (cpp/src/arrow/util/basic_decimal.cc) computes `abs_delta_scale = |new_scale - original_scale|` and looks it up with `DecimalClass::GetScaleMultiplier(abs_delta_scale)`, which indexes `kDecimalNNNPowersOfTen[scale]`. That table only has `kMaxScale + 1` entries and is guarded solely by `DCHECK`, which is compiled out under `NDEBUG`.

`Decimal::FromString` bounds the negative scale (`-parsed_scale > kMaxScale`) but returns a positive scale unbounded. A decimal literal with a negative exponent and few significant digits parses to a tiny precision and a large scale, so it slips past the precision check and reaches `Rescale` with a scale far above `kMaxScale`.

Example: a CSV cell `1E-100` for a `decimal128(38, 0)` column parses to precision 1, scale 100, then calls `Rescale(100, 0)`, reading `kDecimal128PowersOfTen[100]` past the 39-entry table. UBSan reports `index 100 out of bounds for type 'const BasicDecimal128[39]'` at `GetScaleMultiplier`. Reachable from untrusted input through `csv::DecimalValueDecoder::Decode` and the public `Decimal32/64/128/256::FromString` + `Rescale` APIs.

### Component(s)

C++

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.