fix: const eval of *_with_overflow intrinsics for signed integers - #22869
Open
MintSoup wants to merge 1 commit into
Open
fix: const eval of *_with_overflow intrinsics for signed integers#22869MintSoup wants to merge 1 commit into
*_with_overflow intrinsics for signed integers#22869MintSoup wants to merge 1 commit into
Conversation
ChayimFriedman2
requested changes
Jul 20, 2026
| // Below 16 bytes the `i128` arithmetic itself cannot overflow, but the | ||
| // result may not fit the operand type: check with a sign-extension | ||
| // round-trip. | ||
| let out_of_range = op_size < 16 && { |
Contributor
There was a problem hiding this comment.
The existing check is good enough (and simpler). You don't need to duplicate it, and certainly not change it. The if should only return (ans, u128overflow, if is_signed { 0xFF } then { 0 }) and then you change the check for 0 in out_of_range to check for 0 or 0xFF.
Author
There was a problem hiding this comment.
Did you mean something like this?
let is_signed = matches!(lhs.ty.kind(), TyKind::Int(_));
let op_size = self.size_of_sized(lhs.ty, locals, "operand of add_with_overflow")?;
let lhs = u128::from_le_bytes(pad16(lhs.get(self)?, is_signed));
let rhs = u128::from_le_bytes(pad16(rhs.get(self)?, is_signed));
let (ans, is_overflow) = match name {
"add_with_overflow" => lhs.overflowing_add(rhs),
"sub_with_overflow" => lhs.overflowing_sub(rhs),
"mul_with_overflow" => lhs.overflowing_mul(rhs),
_ => unreachable!(),
};
let extra = if is_signed { 0xFF } else { 0 };
let out_of_range =
ans.to_le_bytes()[op_size..].iter().any(|&it| it != 0 && it != extra);
let is_overflow = vec![u8::from(is_overflow || out_of_range)];I'm afraid this won't work for sub_with_overflow(0i8, 1)
Contributor
There was a problem hiding this comment.
No, rather:
let (ans, is_overflow) = if is_signed {
let (lhs, rhs) = (lhs as i128, rhs as i128);
let ans = match name {
"add_with_overflow" => lhs.overflowing_add(rhs),
"sub_with_overflow" => lhs.overflowing_sub(rhs),
"mul_with_overflow" => lhs.overflowing_mul(rhs),
_ => unreachable!(),
} as u128;
(ans, 0xFF)
} else {
let ans = match name {
"add_with_overflow" => lhs.overflowing_add(rhs),
"sub_with_overflow" => lhs.overflowing_sub(rhs),
"mul_with_overflow" => lhs.overflowing_mul(rhs),
_ => unreachable!(),
};
(ans, 0)
};
Author
There was a problem hiding this comment.
That doesn't compile, I believe you meant this?
let (ans, is_overflow, bg) = if is_signed {
let (lhs, rhs) = (lhs as i128, rhs as i128);
let (ans, overflow) = match name {
"add_with_overflow" => lhs.overflowing_add(rhs),
"sub_with_overflow" => lhs.overflowing_sub(rhs),
"mul_with_overflow" => lhs.overflowing_mul(rhs),
_ => unreachable!(),
};
(ans as u128, overflow, 0xFF)
} else {
let (ans, overflow) = match name {
"add_with_overflow" => lhs.overflowing_add(rhs),
"sub_with_overflow" => lhs.overflowing_sub(rhs),
"mul_with_overflow" => lhs.overflowing_mul(rhs),
_ => unreachable!(),
};
(ans, overflow, 0)
};
let out_of_range =
ans.to_le_bytes()[op_size..].iter().any(|&it| it != bg && it != 0);Still fails, for e.g. -128 - 1, reports as no overflow. I believe the background byte needs to depend on the actual value, not just the signedness.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The consteval overflow flag calculation for the signed
with_overflowfunctions is not correct.Example:
Hover over
FLAGshows true whereas it should clearly be false.The blast radius of this bug is much larger than this contrived example, as this also breaks struct layout calculation for signed
NonZerotypes. This in turn breaks layout calculation for structs from many popular crates in the ecosystem (notablychrononaive types) and their transitive dependents.Fixes #22871.
AI disclosure: AI has been used to help troubleshoot the issue and write the fix.