Conversation
|
|
|
|
| // The most negative precision must be rejected by the range check rather than | ||
| // negated into an out-of-range table index. | ||
| EXPECT_EQ(round_int32_int32(1234, std::numeric_limits<int32_t>::min()), 0); | ||
| EXPECT_EQ(round_int64_int32(345353425343, std::numeric_limits<int32_t>::min()), 0); |
There was a problem hiding this comment.
Would it make sense to also add tests for the -9/-10 boundary (and -18/-19 for the int64 overload)? They could help catch any future off-by-one regressions around the new range check.
There was a problem hiding this comment.
Good idea, added them. There's now a -9/-10 pair for the int32 overload and -18/-19 for the int64 one, so the last in-range precision still rounds and one past it returns 0. That pins the boundary against any future off-by-one.
f1bb2c2 to
8b7eb22
Compare
|
Rebased onto current main. The earlier macOS failures were the aws-sdk s3fs crash on the July base, unrelated to this change. On the rebased run gandiva-precompiled-test passes everywhere; the three macOS jobs still red are an arrow-s3fs-test timeout, an acero hash-join timeout and a MinIO download DNS error on the runners. |
Rationale for this change
round_int32_int32andround_int64_int32negate the caller-supplied precision intoabs_precisionbefore range-checking it, so the checkabs_precision > 9(and> 18for the int64 overload) never fires forprecision == INT32_MIN, where the negation leaves the value negative. That value reachesget_power_of_10, which indexes a 19-element static table behindDCHECK_GE/DCHECK_LEonly. The DCHECKs compile out in release builds, soround(int_col, -2147483648)reads far outside the table and either faults or returns arbitrary memory as the rounding multiplier. Both overloads are registered infunction_registry_arithmetic.cc, so the precision comes straight from user SQL.truncate_int64_int32in the same file already compares the signed scale directly (out_scale < -38) and is unaffected; the tworoundoverloads are the only sites that negate first.What changes are included in this PR?
Check the bound against the signed
precisionbefore negating, at both sites. Every precision that was in range before still takes the same path, and the negation now only runs on values known to be within 9 (or 18) of zero.Are these changes tested?
Yes. Added two cases to
TestExtendedMathOps.TestRoundcoveringstd::numeric_limits<int32_t>::min()for both overloads, matching the existingtruncate_int64_int32case in the same file. On the unpatched tree the debug build aborts withextended_math_ops.cc:372: Check failed: (exp) >= (0); with the fix the fullgandiva-precompiled-testsuite passes (134 tests).Are there any user-facing changes?
No.
This PR contains a "Critical Fix". It fixes an out-of-bounds read reachable from a user-supplied
roundprecision argument.