Skip to content

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

Description

@Arawoof06

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++

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions