Repository navigation
Conversation
|
|
| // SliceOptions uses INT64_MIN/MAX for open-ended bounds. Clamp stop before | ||
| // arithmetic so equivalent out-of-range indices cannot overflow the size estimate. | ||
| const int64_t stop = std::clamp(opt.stop, -input_bytes, input_bytes); | ||
| int64_t max_slice_bytes = (stop - opt.start + opt.step - 1) / opt.step; |
There was a problem hiding this comment.
This fixes the default stop case, but the calculation can still overflow with valid values.
Check start=INT64_MIN, stop=-1, and step=1 overflows at INT64_MAX + 1.
| // before arithmetic so equivalent out-of-range indices cannot overflow the size estimate. | ||
| const int64_t start = std::clamp(opt.start, -input_bytes, input_bytes); | ||
| const int64_t stop = std::clamp(opt.stop, -input_bytes, input_bytes); | ||
| int64_t max_slice_bytes = (stop - start + opt.step - 1) / opt.step; |
There was a problem hiding this comment.
Check: input "abc", start=1, the default stop, and step=INT64_MAX
The code around here is short, but the arithmetic is fragile. See if you can separate out boundary checks although this might as well be "one last boundary to enforce"...
…p and bounds Co-Authored-By: Claude Opus 5.5 <[email protected]>
61c9a9c to
6c0d83f
Compare
|
Thanks for the reviews. Updated and rebased onto main:
Tested with ASan + UBSan. I also ran a local, uncommitted comparison against Python slice semantics over ~20k start/stop/step combinations. AI disclosure: I used Claude to find the remaining overflow paths and to draft the change and tests. I've reviewed all of it.
|
dmitry-chirkov-dremio
left a comment
There was a problem hiding this comment.
Lgtm. My earlier feedback is addressed. @pitrou's too it seems?
Rationale for this change
binary_sliceusesINT64_MAXas its default stop, and several internal calculations usedstart,stopandstepdirectly. With large values they overflowed. That causedArrowInvalid: Negative buffer resizefor valid calls likebinary_slice(values, 1), wrong output, and crashes in release builds (e.g.step=INT64_MIN).Closes #51222.
What changes are included in this PR?
MaxSliceBytesclamps start/stop to[-len - 1, len], andNumSelectedBytescomputesceil(span / |step|)without overflow.SliceBackwardRangeclamps before adding 1.FixedOutputSizeusesNumSelectedBytes.The slicing rules and public API are unchanged.
Are these changes tested?
Yes. Cases with
INT64_MIN/INT64_MAXstart, stop and step are added to the existing binary and fixed-size-binary slice tests.arrow-compute-scalar-type-testpasses under ASan + UBSan.Are there any user-facing changes?
binary_slicewith extremestart/stop/stepreturns the correct slice instead of raising, returning wrong bytes, or crashing.This PR contains a "Critical Fix".
binary_slicecould return incorrect data or crash for validSliceOptionswith extremestart/stop/step.utf8_slice_codeunitshas a similar overflow, tracked separately in #55509.Was AI used for this PR?
In accordance to the AI generation guidelines, please disclose below whether and how AI was used in this PR.
Yes. OpenAI Codex helped with the initial fix. Claude helped find the remaining overflow paths and write the follow-up change and tests. I reviewed all of it and take responsibility for the contribution.
PR code and description written by:
Reviewed before submission by:
stopraises "Negative buffer resize" #51222