-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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 #560
Integer overflow #560
Conversation
mandate checking in debug mode.
|
||
pub struct Wrapping<T>(pub T); | ||
|
||
impl<T: WrappingOps> Add<Wrapping<T>, Wrapping<T>> for Wrapping<T> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: this is the old definition of Add
If it's ever going to use hardware overflow instructions and cause an error only on-demand, then it can't panic or report precise errors. Having it use |
Slowing down unoptimized Rust even further is certainly relevant. Optimized builds take a long time to compile and there is absolutely no support for debugging optimized code with LLVM. It's inappropriate to claim that the performance hit from this isn't relevant. |
This is an improvement of the current state (not sure if it's the best overall since solutions that don't fail might be better, but much better that silently overflowing). I think the "wrapping"/modular types should be separate types (which could be called "m8", "m16", etc.), just like signed and unsigned integers are separate types. This makes sense since they are mathematically different objects, with s32/u32 representing subsets of the infinite ring of integers ("Z"), while the "wrapping" types represent the finite rings of integers modulo 2^k ("Z/2^kZ"). In practice, this means that things like ordered comparisons or integer-like division make no sense on modular types (if needed, the programmer would have to cast to either the corresponding unsigned or signed type, which of course will in general yield different results) [I'd also be tempted to remove the arithmetic operations from the current non-modular types since they aren't closed under them, but I guess that might be too extreme (the user would be forced to choose between manually calling "checked_add", cast to the modular types and back, or cast to bigint depending on what they want).] |
@bill-myers Thanks for explaining this more thoroughly. What would the difference be between (Of course I'm +1 on the RFC as it is.) @thestinger I agree that performance and not foreclosing on imprecise exceptions are important. But it's not clear to me that the present RFC would create any constraints in this area. I see this text:
I interpret this to mean "whenever |
By the way, wraparound operations are also useful for "odometer comparison" (which is (a - b) as iKK < 0) |
m32 would be the same as current u32 except it would not support the <, >, <=, >=, /, % and >> operators (and any other where casting to s32 or u32 and back yields a different result). It might also be printed differently, for instance the value 42 as "42 mod 2^32". |
@glaebhoerl: So does |
@thestinger it does report an error. No it "must" not do so. If you'd read the RFC, you'd know that overflow produces an unspecified value. In builds where a |
I've read the RFC and I'm responding to it.
So it strictly reports an error on overflow by default which is the only case that really matters. Even Rust's own nightly releases aren't build with |
The current build system defaults shouldn't influence language design; in any case, the defaults should be changed, and somewhat coincidentally there was actually some discussion along these lines in #rust-internals in the past few days (it's no-one's problem if they missed that discussion, just some extra commentary :) ).
I wonder if we could tweak this part of the detailed design
slightly, to more explicitly allow e.g. coalescing multiple checks so that each possibly-overflowing operation may not be checked immediately, while still guaranteeing that any overflow will detected at some point (in any case, this doesn't seem to be disallowed AFAICT). Also, I'll note that, as written, the RFC does not require the use of |
The ridiculously poor performance of Rust's debug builds is a major problem, and this is an enormous step in the wrong direction. The RFC _is_ heavily influenced by the current compiler implementation because it's based on the assumption that debug builds are already slow. However, it's going to severely aggravate that problem and the inability to mix debugging with optimizations is a fixable LLVM issue which is not there for other compilers like GCC. It's the norm to use an optimized debug build with GCC ( You can't claim that language design shouldn't be influenced by the build system defaults while supporting an RFC that's explicitly designed around a concept of debug and release builds. |
It's absurd to draw a line between language and implementation in order to ignore the fact that out-of-the-box performance will be severely impacted. The practical implications of an RFC are very relevant and cannot be ignored by refusing to talk about anything but pure programming language design. Rust's optimization process takes a very long time so the performance of unoptimized builds is not unimportant considering the productivity loss from optimizing. I can't see it as a step in the right direct unless it's an explicitly an opt-in feature in all cases. It would be fine to tie it to |
How many real overflow bugs were found while converting the compiler? That's a 200k+ line code so if it has any value at all there should be dozens of bug fixes to point at. Each case of intentional overflow is a case where this feature had a negative impact. The ratio between those is what determines the value of the feature vs. the cost of the feature. An acceptable ratio is a subjective issue, but the ratio itself is simply an important number to discuss here. You may be willing to accept hundreds or thousands of cases of "friction" in order to catch one bug, but it will drive away people would find the language too abrasive. |
I'm afraid I don't understand why this current failing of LLVM is important. Could you expand on why integer overflow detection would be influenced by LLVM being able to build optimised debuggable code?
I was specifically talking about Rust's makefiles currently defaulting to passing Phrasing it the latter terms: Rust current defaults to a sort-of debug build, we could/should make it default to a release build. This seems mostly independent of detecting integer overflow in debug builds, to me?
I'm not doing that, I personally haven't said anything about performance or otherwise, just correcting/clarifying/commenting on some subpoints made earlier in this discussion, trying to keep everything as true (given what I personally understand) as possible. Whether this leads us to doing overflow detection or not is another matter.
Are you saying that you would be OK with the RFC if it was adjusted to explicitly require using the |
I'm not the one tying it to debug vs. release builds.
I'm not talking about Rust's build system. I'm talking about
You claimed that the defaults used by
I'm saying that I would be fine with it if it was made clear that this isn't going to be enabled when you use |
You said above:
I was refuting the relevance of this.
I specifically claimed that:
We should evaluate this feature on its own merits, not on what we happen to do in some Makefiles right this minute. Once the feature is accepted, we then chose the defaults for |
I don't see how. It was an example of why the
I was never talking about build system defaults, so I don't know why you keep coming back to this.
The merits of the feature certainly depend on the interaction with the rest of the language and tooling. There is no indication that the compiler's default for If you don't want to talk about the issue of a significant out-of-the-box performance hit then the RFC should make it clear that the feature is going to be opt-in with the reference implementation. Otherwise, the fact that it's significantly hurting performance by default is very relevant. |
This RFC is a continuation of a long-running discussion about overflow: The topic has been covered in considerable depth in those earlier threads as well as on this RFC comment thread itself. While the discussion has been contentious at points, a fairly clear picture of the tradeoffs in each direction has emerged. There were concerns about the performance hit even if checking is restricted to debugging builds. Some details about the hit and possible mitigations are in this comment. Other mitigation strategies include scoped disabling of checking, as was proposed in the initial RFC. There were concerns about the clarity of the RFC text. This was partly intentional as the precise details of checking and panicking semantics will likely need some implementation work to fully sort out. But @mkaufmann's comment also helped clarify the text. There were questions about whether over/underflow detection as proposed would actually catch many bugs. The clearest response is probably @nikomatsakis's comment, which discusses some published research on the topic as well as the need of using fuzzing and other tools in conjunction with the checking proposed here. A key point that emerged is that, at heart, this RFC is about distinguishing intentional and unintentional over/underflow. There are many ways to make the distinction, but the most promising is by differentiating types, since mixtures of desired and undesired over/underflow for the same value are expected to be rare. In the end, the core team has decided to move forward with this RFC. If we ever hope to distinguish between intentional wrapping and unintentional wrapping, this is the time. The specifics of interaction with optimization, defaults and opt-outs can be tweaked over time. |
Rebase and follow-through on work done by @cmr and @Aatch. Implements most of rust-lang/rfcs#560. Errors encountered from the checks during building were fixed. The checks for division, remainder and bit-shifting have not been implemented yet. See also PR #20795 cc @Aatch ; cc @nikomatsakis
I am accumulating a list of actual bugs uncovered via the arithmetic overflow checks here: I welcome others to tell me about any bugs they found via these checks. (Note that I am only interested in actual bugs; not in benign overflows; see the document for more discussion.) Update: The above document was originally in an etherpad (you can find out which one via its commit history). But now it is in a github repo, so that others can submit pull requests with new stories of bugs arithmetic-overflow found in their code. |
I wouldn't expect you to find a lot of integer overflow bugs until you do some intensive fuzz testing. |
@rocallahan agreed (as we said earlier), but it's still good for historical record to know what bugs were encountered even without fuzz testing (and there certainly have been some). |
The RFC has this text:
I have written an internals post regarding the fine details of what this sentence is saying (or should instead be saying); the post is here: http://internals.rust-lang.org/t/on-casts-and-checked-overflow/1710 If you had an interest in the discussion here or want to provide input on the future semantics of (I note in particular both @mahkoh and @quantheory were discussing the details of cast-semantics in the discussion above, and therefore may want to chime in on the internals thread.) |
@glaebhoerl wrote:
As a very very last minute change (that should still manage to land in the beta release, if all goes well), based on discussion here: "A tale of two’s complement" and here: "Forbid -(unsigned integer)", the team decided in the most recent weekly meeting to feature-gate the unary-negation operator on unsigned integer values. This is largely based on following the philosophy presented here on RFC #560: the arithmetic operators should be use in a manner that does not cause overflow; if one wants bitwise operations, then one can e.g. rewrite The PR that puts in the feature-gates is: rust-lang/rust#23945 |
A simplified version of Gabhor's "Scoped Attributes for Integer Overflow" RFC.
Merged
text/
Rendered.
tracking issue: rust-lang/rust#22020