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++
Describe the bug, including details regarding any error messages, version, and platform.
DecimalRescale(cpp/src/arrow/util/basic_decimal.cc) computesabs_delta_scale = |new_scale - original_scale|and looks it up withDecimalClass::GetScaleMultiplier(abs_delta_scale), which indexeskDecimalNNNPowersOfTen[scale]. That table only haskMaxScale + 1entries and is guarded solely byDCHECK, which is compiled out underNDEBUG.Decimal::FromStringbounds 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 reachesRescalewith a scale far abovekMaxScale.Example: a CSV cell
1E-100for adecimal128(38, 0)column parses to precision 1, scale 100, then callsRescale(100, 0), readingkDecimal128PowersOfTen[100]past the 39-entry table. UBSan reportsindex 100 out of bounds for type 'const BasicDecimal128[39]'atGetScaleMultiplier. Reachable from untrusted input throughcsv::DecimalValueDecoder::Decodeand the publicDecimal32/64/128/256::FromString+RescaleAPIs.Component(s)
C++