-
Notifications
You must be signed in to change notification settings - Fork 63
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Integer overflow panics in debug mode but is allowed by the verifier #45
Comments
Given:
the points seem in favor that Verus should probably check for no overflow. |
I agree that developers will (and should) expect verified code not to panic. I also like the notion that we can use the verification of non-overflow to optimize the code. We should try to find more such cases as we develop Verus (e.g., Rust already does a good job of eliminating array bounds checks, but verification should require us to eliminate any need for them at all). |
+1 to the above comments. Additionally, I would like to note that there already exists constructs in Rust for intentionally-wrapping and intentionally-checked behavior, and that For intentionally-wrapping arithmetic with the exact same ergonomics as Relevant docs from there (emphasis mine):
|
Currently, this passes: fn test(a: u64) {
let mut j = a;
j = j + 2;
assert(j == a + 2);
} and this fails fn test(a: u64) {
let mut j = a;
j = j + 2;
j = j + 2;
assert(j == a + 4);
} because of how subexpression substitution works. We should be careful about that when we address this issue. |
My current idea for this is that by default we generate verification conditions to ensure arithmetic doesn't overflow (and so we could also potentially use In addition, we can have a flag that disables the overflow check VCs (that is, returns to the current behaviour): this would be intended to be used in conjunction with disabling Finally, one should be able to use |
I know this is an old PR, but to elaborate on this a bit: I don't know that any of the instructions are directly faster with the no-wrap flags (at least on normal chips -- if you have a 1s-complement machine things might be weirder). The difference, from what I've seen, is entirely in the optimizations that are only legal because of the lack of overflow. As a trivial example, |
Integer overflow is defined to behave as follows by the currently adopted RFC 560 https://github.com/rust-lang/rfcs/blob/master/text/0560-integer-overflow.md
In modern rust,
debug_assertions
(which includes overflow checking) is enabled when compiling with thedebug
default configurations. In therelease
(optimized) default config,debug_assertions
is disabled, and the overflowing operations will wrap.Because of this, integer overflow is never undefined behavior[^1]. Note that this is different from the
unchecked_*
operations on integers, which are undefined behavior if they overflow, e.g. for u64::unchecked_add.Verus currently admits overflowing operations which will panic when compiled with
debug_assertions
. This can be regarded as a soundness issue (verified code should not panic).How to address this is still up for debate, but it may be worth noting that if we were to introduce verification conditions for integer operations that ensure there's no overflow, we could also replace the native operations with their
unchecked_math
counterparts, which (apparently) can use LLVM intrinsics that can be faster because they assume no overflow can occur./cc @Chris-Hawblitzel
The text was updated successfully, but these errors were encountered: