Skip to content

Fix integer overflow when composing nested affine views - #1245

Merged
cprudhom merged 3 commits into
chocoteam:developfrom
adityaanikam:fix-nested-affine-view-overflow-1244
Sep 7, 2026
Merged

cprudhom merged 3 commits into
chocoteam:developfrom
adityaanikam:fix-nested-affine-view-overflow-1244

Conversation

@adityaanikam

Copy link
Copy Markdown
Contributor

Fixes #1244.

IViewFactory#intView flattens a nested affine view by composing the coefficients in int arithmetic:

int av = (view.p ? 1 : -1) * view.a * a;
int bv = a * view.b + b;

Either product can leave the int range even when every value the expression can take is small. In the reported case, x ranges over [46341, 46342] and the composed expression is at most 46341, but flattening (x - 46341) * 46341 computes bv as 46341 * -46341 = -2147488281, which underflows and wraps to +2147479015. The view built from that is wrong in both directions: a valid solution is pruned and the model reported unsatisfiable, and an assignment that violates the posted constraint is returned as a solution.

Changes proposed in this PR:

  • Compose the coefficients in long and keep the nested view when either does not fit in an int, falling back to the new IntAffineView<>(var, a, b) construction the non-flattening branch already used. No new view type is needed and views stay enabled.
  • Add two regression tests to IntAffineViewTest, one per direction reported in the issue.
  • Add myself to the authors of both modified classes, as CONTRIBUTING asks.

On scope: the issue also suggests guarding the scaled bounds of the base variable, in addition to the coefficients. I left that out. It only changes behaviour when av and bv both fit but av * base does not, and in that situation this patch and the current code take the same branch, so I could not write a test that distinguishes them. I would rather not add a condition with no regression test behind it. Worth noting if you do want it covered: getLB() and getUB() compute (...) * a + b as a single int expression, so an overflowing intermediate cancels there and the bound is still correct; contains() is the one that would suffer, because it does value -= b and then divides, and the division does not undo the wrap. Happy to add it if you would like it handled.

I did not touch CHANGES.md, since there is no unreleased section to add to.

Verified with a negative control: reverting only IViewFactory.java and keeping the tests fails exactly the two new tests out of 150 in the class, with expected [true] but found [false] for the pruned solution and expected [46342] but found [46341] for the invalid one. Restoring the fix passes all 150.

@chocoteam/core-developer

cprudhom and others added 2 commits May 21, 2026 17:33
intView flattens a * (view.a * x + view.b) + b into a single affine view
by computing the composed coefficients in int arithmetic. Either product
can leave the int range even when every value the expression can take is
small. For x in [46341, 46342], flattening (x - 46341) * 46341 computes
b as 46341 * -46341, which does not fit and wraps to a positive number.
The corrupted view then prunes valid solutions and returns assignments
that violate the posted constraint.

Compute the composed coefficients in long, and keep the nested view when
either of them does not fit in an int. That falls back to the same
IntAffineView construction the non-flattening branch already used, so no
new view type is needed and views stay enabled.

@ArthurGodet ArthurGodet left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a small change to do (to keep simplified imbricated if/else-if), but otherwise, changes seem fine to me. Thanks for your contribution !

Comment thread solver/src/main/java/org/chocosolver/solver/variables/IViewFactory.java Outdated
@ArthurGodet
ArthurGodet changed the base branch from master to develop September 6, 2026 16:15
@mergify

mergify Bot commented Sep 6, 2026

Copy link
Copy Markdown
Contributor

Tick the box to add this pull request to the merge queue (same as @mergifyio queue).

  • Queue this pull request

@cprudhom
cprudhom merged commit b19813c into chocoteam:develop Sep 7, 2026
9 checks passed
@cprudhom cprudhom added this to the 6.0.2 milestone Sep 7, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[BUG] Integer overflow when composing nested affine views produces incorrect results

3 participants