-
Notifications
You must be signed in to change notification settings - Fork 13k
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
Check for Integer Overflow by Default #47739
Comments
What about to create another compiler flag (if it is not yet created) for that. I am not sure that rust's embedded dev community will be happy with this idea. |
I am not completely opposed to this idea. ;) However, I think using unchecked_ operations with an Overflowing type (just like for checked_ and Wrapping) is sufficiently pleasant. Having a compiler flag is dangerous because people will copy a list of "optimizations" from stackoverflow, disabling the checks again without knowing what they are doing. This may seem silly but as a security engineer I can only assure you that it is a real problem and I would like to avoid it. I also don't see why embedded engineers would be less likely to care about overflow errors in their programs and want to blanket disable such checks. Sure, speed might be more important but probably not to the point of not caring about correctness anymore. |
We already have the flag I'm leaning in favor of changing the default but this is probably contentious enough that we'd want an RFC that lays out the motivation and downsides (and ideally, hard benchmark data). |
@rkruppe Yes, it should default to on and ideally be removed in favor of a more selective way of disabling it. The latter is probably more work and more controversial but imho the right thing to do™. |
Before introducing overflow checks on default I suggest to introduce a refined compiler pass like this one from Swift: |
@leonardo-m That is a great idea but I still think we should enable it first and then do that. The selling point of rust is that it is safer than C, so we should emphasize and prioritize that. |
Greater safety while also offering competitive performance and control is a selling point, too. Regressing the performance of the default configuration is sure to rustle some feathers, and making sure to quantify and reduce the slowdown will be very useful both for building goodwill and for convincing people to actually accept the new default. Aside: You're using "safety" in a different sense here than most Rust material. I don't want to quibble about terminology, but I do want to be clear that lack of overflow checks does not jeopardize the guarantees that Rust offers (lack of use-after-free, type safety, data race freedom, etc.). |
tl;dr: nevermind, ignore this post & don't read this - because it's also not in the proper place! Reading this from OP:
made me believe that you (also?) meant that, in the following example(playground), Rust should have inferred the type of 'i64'(instead of 'i32') for 'b': #![feature(core_intrinsics)] //must be crate-wide ie. #![]
fn print_type_of<T>(_: &T) { //src: https://stackoverflow.com/questions/21747136/how-do-i-print-the-type-of-a-variable-in-rust/29168659#29168659
println!("{}", unsafe { std::intrinsics::type_name::<T>() });
}
fn main() {
let a=1.0;// defaulting to f64
print_type_of(&a);// f64
println!("{}",a);// 1
let b=-4000000000;// defaulting to i32 despite the 'literal out of range for i32'
print_type_of(&b);// i32
println!("{}",b);// 294967296
} Btw is there an issue for this ^ ? I only stumbled upon PR #20189 so far. EDIT: I guess I found one #8337 (comment) |
Just anecdotally, lots of permission check bypasses in the linux kernel have been from integer overflows. |
Before I start writing I just want to point out that I'm completly new to Rust (2 days in) and I may be wrong about everything that I'm going to write here. I noticed some inconsistencies on the default state of overflow checks:
With that said, in my opinion overflow checks should be enabled by default, a new type |
This >3 year old comment from Niko rust-lang/rfcs#560 (comment) seems particularly relevant to this discussion. In particular this sentence:
|
Even if we don't turn on checking by default, I think it's still a good idea to add some math optimizations like in Swift language for debug builds. |
FWIW, Ada has a concept of modular and non-modular types, where by default signed types have checked overflow resulting in an exception, and unsigned types have modular semantics. I'm not advocating for any particular approach, or even weighing in on previous discussion or existing options in rust. I'm just calling attention to a similar situation in another language. |
We have |
Apologies if this is completely not applicable here, but Capnproto author Kenton Varda claims to do static out of integer overflow checking. I don't entirely understand how that's possible, but if it is, I reckon rust should probably have it. |
@najamelan At least based on a quick reading, that particular kind of overflow checking is done by embedding the maximum possible logical value for an integral type into the type and tracking that maximum value across operations. It would work fairly well if you use a relatively small portion of an integer type's possible range, but isn't really a general solution. I think const generics and const fns would be needed for a straight translation of the C++ code to Rust. I'm not sure whether what has landed so far would be enough, but in principle it's possible. |
Without unwinding we get something like 1.status flag clear, 2.operation, 3.status flag read,4.mask flag, 5.status flag mask, 6.compare to nullregister, 7.njump. That should be still 2x-3x the cost of multiplication/addition per check. It would be nice, if the issue could be updated to reflect the status quo or closed after the overflow RFC |
Hi, Is there a compiler option to add overflow checks by default when casting an integer with Personally, I would really prefer to have checks by default every time an integer can overflow, even for « simple » casts (those that everyone will use most of the time), and then have some conversion function that can overflow / truncate without panicking if you need it, but with an explicit name like Even if this compiler check never becomes the default (as I understand there are backwards compatibility requirements here), at least having a compiler option to turn it on automatics checks for that as well ? As for the general discussion of whether to have systematic overflow checks on by default or not, I am in favor of it as well. I think this way (all overflow checks activated by default, explicitly opt-out if you don’t want it) is much more logical, because if you want performance for number operations and / or want to rely on the overflowing behavior, you will immediately notice the problem (because it always panics), and you can fix it immediately. But the other way around can create bugs that are much more complicated to find and fix. |
Can you ask on reddit or another forum, why |
It would be good to always check integers for overflow and thereby providing users with an integer type that actually behaves like an integer or at least fails completely instead of giving "wrong" results.
This was discussed on IRC last week and three distinct cases were identified:
My proposal is to make (1.) the default.
For (2.) there is already Wrapping but (3.) should also be annotated requiring people to assert that they have done their homework and
a) are sure that overflows cannot cause problems
b) the compiler cannot infer that the situation is safe and remove the checks
c) actually need the speed-up of omitting the checks.
I am aware that there are checked operations and compiler flags to keep overflow checks in release builds but the defaults are important and the defaults are wrong!
This issue is also discussed in the following two posts:
https://mail.mozilla.org/pipermail/rust-dev/2014-June/010363.html
https://huonw.github.io/blog/2016/04/myths-and-legends-about-integer-overflow-in-rust/
The text was updated successfully, but these errors were encountered: