You are viewing a plain text version of this content. The canonical link for it is here.
Posted to github@arrow.apache.org by "choksi2212 (via GitHub)" <gi...@apache.org> on 2026/10/15 22:20:14 UTC

[PR] fix(arrow-array): return overflow error instead of panicking when negating `i32::MIN` months [arrow-rs]

choksi2212 opened a new pull request, #11611:
URL: https://github.com/apache/arrow-rs/pull/11611

   # Which issue does this PR close?
   
   - Closes #11600
   
   # Rationale for this change
   
   `Date32Type`/`Date64Type`::`subtract_year_months_opt` and `subtract_month_day_nano_opt` negate the interval months with a unary minus before handing them to `add_months_date`. When the months are `i32::MIN` the negation itself overflows, so in debug builds the `_opt` helpers panic instead of returning `None`:
   
   ```
   thread panicked at arrow-array/src/types.rs:1143:55:
   attempt to negate with overflow
   ```
   
   Every other out-of-range date arithmetic returns `None` from the `_opt` helpers, which `date_op` surfaces as `Date arithmetic overflow`. The timestamp kernels already handle `i32::MIN` months (`sub_months_datetime` subtracts through `unsigned_abs`), so only these four date helpers were affected.
   
   # What changes are included in this PR?
   
   The four negations now use `checked_neg()`, so the negation overflow returns `None` and the kernels report the same `Date arithmetic overflow` error as any other interval that moves the date out of range:
   
   - `Date32Type::subtract_year_months_opt`
   - `Date32Type::subtract_month_day_nano_opt`
   - `Date64Type::subtract_year_months_opt`
   - `Date64Type::subtract_month_day_nano_opt`
   
   `add_months_date` is untouched — it already handles months of any magnitude via `unsigned_abs`.
   
   # Are there any user-facing changes?
   
   No API changes. Subtracting an `i32::MIN`-months interval from a `Date32`/`Date64` array no longer panics in debug builds; it returns the existing `Date arithmetic overflow` error, matching the already-correct behavior of every other out-of-range interval.
   
   One note on release builds (overflow checks off): the wrapped `-i32::MIN` still lands in `add_months_date`'s `unsigned_abs` branch, which returns `None` for a ~179-million-year shift, so release builds were already reporting the overflow error. That part is reasoned from the code; everything below is from actual runs.
   
   # Testing
   
   - New kernel-level test `test_date_sub_interval_min_months` covers the repro from the issue for all four type/interval combinations and asserts the `Date arithmetic overflow` error. On unpatched `main` it panics with `attempt to negate with overflow` at `arrow-array/src/types.rs:1143:55`; with this patch it passes.
   - `test_year_month_ops!` and `test_month_day_nano_ops!` gain `i32::MIN` cases for both `Date32Type` and `Date64Type`: subtract must return `None`, and the corresponding `add` with `i32::MIN` months is pinned as the out-of-range control.
   - `cargo test -p arrow-arith`: 256 passed, 0 failed. `cargo test -p arrow-array`: 946 passed, 0 failed. `cargo fmt --all -- --check` and `cargo clippy -p arrow-arith -p arrow-array --all-targets` clean (rustc 1.99.0, Linux).
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] fix(arrow-array): return overflow error instead of panicking when negating `i32::MIN` months [arrow-rs]

Posted by "choksi2212 (via GitHub)" <gi...@apache.org>.
choksi2212 commented on PR #11611:
URL: https://github.com/apache/arrow-rs/pull/11611#issuecomment-6405318195

   One CI logistics note: `CI (fork)` on this PR is still waiting on an Approve-and-run click from someone with permissions (first PR from my fork to arrow-rs). Happy to rebase or adjust anything once it actually runs.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] fix(arrow-array): return overflow error instead of panicking when negating `i32::MIN` months [arrow-rs]

Posted by "choksi2212 (via GitHub)" <gi...@apache.org>.
choksi2212 commented on PR #11611:
URL: https://github.com/apache/arrow-rs/pull/11611#issuecomment-6440938259

   Thanks for the review and the merge!


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] fix(arrow-array): return overflow error instead of panicking when negating `i32::MIN` months [arrow-rs]

Posted by "choksi2212 (via GitHub)" <gi...@apache.org>.
choksi2212 commented on code in PR #11611:
URL: https://github.com/apache/arrow-rs/pull/11611#discussion_r4305219977


##########
arrow-array/src/types.rs:
##########
@@ -1140,7 +1140,7 @@ impl Date32Type {
         delta: <IntervalYearMonthType as ArrowPrimitiveType>::Native,
     ) -> Option<<Date32Type as ArrowPrimitiveType>::Native> {
         let prior = Date32Type::to_naive_date_opt(date)?;
-        let months = IntervalYearMonthType::to_months(-delta);
+        let months = IntervalYearMonthType::to_months(delta.checked_neg()?);

Review Comment:
   Done in a19611c — added the comment at all four sites. Kept it to two lines each: `-i32::MIN` overflows `i32`, but a 2^31-month shift is outside `NaiveDate`'s range anyway, so `None` is the right answer regardless.
   
   Re-verified locally on the updated tree: `cargo test -p arrow-arith --lib` 256 passed / 0 failed (incl. the updated kernel test), the moved type-level test passes under `arrow-array`, `cargo fmt --all --check` and `cargo clippy` are clean.



##########
arrow-arith/src/numeric.rs:
##########
@@ -2862,4 +2894,42 @@ mod tests {
         test_month_day_nano_ops!(Date32Type, date_to_days);
         test_month_day_nano_ops!(Date64Type, date_to_millis);
     }
+
+    #[test]
+    fn test_date_sub_interval_min_months() {
+        // Subtracting i32::MIN months requires negating i32::MIN, which
+        // overflows i32: the date kernels must return the Date arithmetic
+        // overflow error instead of panicking in debug builds
+        // https://github.com/apache/arrow-rs/issues/11600
+        let dates = Date32Array::from(vec![0]);
+        let deltas = IntervalYearMonthArray::from(vec![i32::MIN]);
+        let err = sub(&dates, &deltas).unwrap_err();
+        assert!(
+            err.to_string().contains("Date arithmetic overflow"),
+            "unexpected error: {err}"
+        );
+
+        let dates = Date64Array::from(vec![0]);
+        let err = sub(&dates, &deltas).unwrap_err();
+        assert!(
+            err.to_string().contains("Date arithmetic overflow"),
+            "unexpected error: {err}"
+        );
+
+        let deltas =
+            IntervalMonthDayNanoArray::from(vec![IntervalMonthDayNano::new(i32::MIN, 0, 0)]);
+        let dates = Date32Array::from(vec![0]);
+        let err = sub(&dates, &deltas).unwrap_err();
+        assert!(
+            err.to_string().contains("Date arithmetic overflow"),
+            "unexpected error: {err}"
+        );
+
+        let dates = Date64Array::from(vec![0]);
+        let err = sub(&dates, &deltas).unwrap_err();
+        assert!(
+            err.to_string().contains("Date arithmetic overflow"),
+            "unexpected error: {err}"
+        );

Review Comment:
   Done in a19611c — the kernel test now asserts the full error message for both the `IntervalYearMonth` and `IntervalMonthDayNano` deltas, on both `Date32` and `Date64`, so a failure from a different operand or operation can no longer pass it.



##########
arrow-arith/src/numeric.rs:
##########
@@ -2625,6 +2625,18 @@ mod tests {
                 <$type>::add_year_months_opt($date_fn(MIN_VALID_DATE), -1).is_none(),
                 "add_year_months: overflow neg days"
             );
+
+            // Negating i32::MIN months overflows i32: subtract must return
+            // None (reported as a Date arithmetic overflow by the kernels)
+            // instead of panicking in debug builds
+            assert!(

Review Comment:
   Done in a19611c — moved those to `types.rs` as `date_subtract_i32_min_months_overflows`, next to the `*_opt` implementations they exercise.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] fix(arrow-array): return overflow error instead of panicking when negating `i32::MIN` months [arrow-rs]

Posted by "Jefffrey (via GitHub)" <gi...@apache.org>.
Jefffrey merged PR #11611:
URL: https://github.com/apache/arrow-rs/pull/11611


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] fix(arrow-array): return overflow error instead of panicking when negating `i32::MIN` months [arrow-rs]

Posted by "Jefffrey (via GitHub)" <gi...@apache.org>.
Jefffrey commented on code in PR #11611:
URL: https://github.com/apache/arrow-rs/pull/11611#discussion_r4301901040


##########
arrow-arith/src/numeric.rs:
##########
@@ -2625,6 +2625,18 @@ mod tests {
                 <$type>::add_year_months_opt($date_fn(MIN_VALID_DATE), -1).is_none(),
                 "add_year_months: overflow neg days"
             );
+
+            // Negating i32::MIN months overflows i32: subtract must return
+            // None (reported as a Date arithmetic overflow by the kernels)
+            // instead of panicking in debug builds
+            assert!(

Review Comment:
   these tests seem like theyd be more suited to be alongside types.rs, where the functions being tested are defined



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] fix(arrow-array): return overflow error instead of panicking when negating `i32::MIN` months [arrow-rs]

Posted by "mbutrovich (via GitHub)" <gi...@apache.org>.
mbutrovich commented on code in PR #11611:
URL: https://github.com/apache/arrow-rs/pull/11611#discussion_r4299039276


##########
arrow-arith/src/numeric.rs:
##########
@@ -2862,4 +2894,42 @@ mod tests {
         test_month_day_nano_ops!(Date32Type, date_to_days);
         test_month_day_nano_ops!(Date64Type, date_to_millis);
     }
+
+    #[test]
+    fn test_date_sub_interval_min_months() {
+        // Subtracting i32::MIN months requires negating i32::MIN, which
+        // overflows i32: the date kernels must return the Date arithmetic
+        // overflow error instead of panicking in debug builds
+        // https://github.com/apache/arrow-rs/issues/11600
+        let dates = Date32Array::from(vec![0]);
+        let deltas = IntervalYearMonthArray::from(vec![i32::MIN]);
+        let err = sub(&dates, &deltas).unwrap_err();
+        assert!(
+            err.to_string().contains("Date arithmetic overflow"),
+            "unexpected error: {err}"
+        );
+
+        let dates = Date64Array::from(vec![0]);
+        let err = sub(&dates, &deltas).unwrap_err();
+        assert!(
+            err.to_string().contains("Date arithmetic overflow"),
+            "unexpected error: {err}"
+        );
+
+        let deltas =
+            IntervalMonthDayNanoArray::from(vec![IntervalMonthDayNano::new(i32::MIN, 0, 0)]);
+        let dates = Date32Array::from(vec![0]);
+        let err = sub(&dates, &deltas).unwrap_err();
+        assert!(
+            err.to_string().contains("Date arithmetic overflow"),
+            "unexpected error: {err}"
+        );
+
+        let dates = Date64Array::from(vec![0]);
+        let err = sub(&dates, &deltas).unwrap_err();
+        assert!(
+            err.to_string().contains("Date arithmetic overflow"),
+            "unexpected error: {err}"
+        );

Review Comment:
   What do you think about asserting the full error message, like the other kernel overflow tests in this file do ([numeric.rs](https://github.com/apache/arrow-rs/blob/3ef09c668303f46da22a56373bd125a320fecf3b/arrow-arith/src/numeric.rs#L1387-L1395))? `contains("Date arithmetic overflow")` would also pass if the error came from a different operand or operation. The full message also checks that the error reports the operands the caller passed. Looping over the two date arrays keeps the test short.
   
   ```suggestion
           let dates: [ArrayRef; 2] = [
               Arc::new(Date32Array::from(vec![0])),
               Arc::new(Date64Array::from(vec![0])),
           ];
           let year_month = IntervalYearMonthArray::from(vec![i32::MIN]);
           let month_day_nano =
               IntervalMonthDayNanoArray::from(vec![IntervalMonthDayNano::new(i32::MIN, 0, 0)]);
           for dates in &dates {
               assert_eq!(
                   sub(dates, &year_month).unwrap_err().to_string(),
                   "Compute error: Date arithmetic overflow: 0 - -2147483648 months"
               );
               assert_eq!(
                   sub(dates, &month_day_nano).unwrap_err().to_string(),
                   "Compute error: Date arithmetic overflow: 0 - IntervalMonthDayNano { months: -2147483648, days: 0, nanoseconds: 0 }"
               );
           }
   ```



##########
arrow-array/src/types.rs:
##########
@@ -1140,7 +1140,7 @@ impl Date32Type {
         delta: <IntervalYearMonthType as ArrowPrimitiveType>::Native,
     ) -> Option<<Date32Type as ArrowPrimitiveType>::Native> {
         let prior = Date32Type::to_naive_date_opt(date)?;
-        let months = IntervalYearMonthType::to_months(-delta);
+        let months = IntervalYearMonthType::to_months(delta.checked_neg()?);

Review Comment:
   Should we add a short comment here and at the other three `checked_neg()?` sites (lines 1229, 1333, and 1371)? A reader could take `checked_neg()?` as rejecting a subtraction that should succeed. As I read it, `None` is the right answer because a shift of 2^31 months (about 179 million years) is far outside the range of `NaiveDate`, which runs from year -262143 to 262142 ([numeric.rs](https://github.com/apache/arrow-rs/blob/3ef09c668303f46da22a56373bd125a320fecf3b/arrow-arith/src/numeric.rs#L1183)). The subtraction would overflow even if the negation didn't.
   
   ```suggestion
           // -i32::MIN overflows i32, but a 2^31 month shift is outside NaiveDate's range anyway
           let months = IntervalYearMonthType::to_months(delta.checked_neg()?);
   ```



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org


Re: [PR] fix(arrow-array): return overflow error instead of panicking when negating `i32::MIN` months [arrow-rs]

Posted by "choksi2212 (via GitHub)" <gi...@apache.org>.
choksi2212 commented on PR #11611:
URL: https://github.com/apache/arrow-rs/pull/11611#issuecomment-6401086659

   Following up on this one — the review feedback from mbutrovich and Jefffrey is applied at a19611c and the CI suites came back green. A review pass when someone has a cycle would be appreciated.
   


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: github-unsubscribe@arrow.apache.org

For queries about this service, please contact Infrastructure at:
users@infra.apache.org