11 ms·
I'm pretty sure that this is one of the unsafeties that rust borrows from c, even as it attempts to eliminate all the others. Checking every addition adds a mas
by bensecure 3y ago
I'm pretty sure that this is one of the unsafeties that rust borrows from c, even as it attempts to eliminate all the others. Checking every addition adds a massive slowdown, without giving much useful protection against vulns or corruption.
- Hirrolot 3y ago> I'm pretty sure that this is one of the unsafeties that rust borrows from c But integer arithmetic is safe in terms of Rust. > Checking every addition adds a massive slowdown It only does so for debug mode. In release mode, it uses modular arithmetic.
- xscott 3y agoLol, when C does it, it's "unsafe". When Rust does it, it's "modular"!
- deleted 3y ago[deleted]
- mathiaskindberg 3y agoFor anyone wondering about the term "modular": > In mathematics, modular arithmetic is a system of arithmetic for integers, where numbers "wrap around" when reaching a certain value, called the modulus. The modern approach to modular arithmetic was developed by Carl Friedrich Gauss in his book Disquisitiones Arithmeticae, published in 1801. https://en.wikipedia.org/wiki/Modular_arithmetic https://en.wikipedia.org/wiki/Modular_arithmetic
- nuancebydefault 3y agoModular/modulus (and also twos complement) is a natural feature of most CPUs. It comes natural by the way logic counters work in hardware. C enforces that by not touching that logic. Rust is the same in that respect. Python on the other hand treats integers as objects with a virtually unlimited amount of digits. That said, float/double precision and logic is still CPU dependent and is used as-is for most languages.
- marcosdumay 3y agoIt's astonishing the number of people defending the C "ideals" that demonstrate ignorance about what C actually does. (Is it artificial,in order to willingly miss the point?) Only some of the integral types in C are modular. If they all where, it wouldn't be a problem.
- xscott 3y agoNo, what's astonishing is that now that every CPU worth using has 2's complement for signed integers, the compiler writers are still embracing undefined behavior in the name of piddly optimizations. I was tempted to specify "unsigned" to ward off the obnoxious pedants, and I see that I should have. C really should be a portable assembly language by now. A very small non-breaking change to the standard, and C's arithmetic would be the same as Rust's.
- marcosdumay 3y ago> No, what's astonishing is that now that every CPU worth using has 2's complement for signed integers, the compiler writers are still embracing undefined behavior in the name of piddly optimizations. Yeah, that's also astonishing. Anyway, I've stopped blaming the C developers by now. I just assume they have the goal of killing the language and moving people into a more ergonomic alternative. I don't know their true intentions, but this has been a very predictive assumption. (I guess any definition of any UB would be non-breaking, so yeah, they could fix all of the language.)
- xscott 3y ago> I just assume they have the goal of killing the language Sadly, that's my conclusion too. I really wish there was a good "portable assembly language", and maybe that'll be something that targets WASM.
- deleted 3y ago[deleted]
- cozzyd 3y agothen use -fwrapv if that's what you want...
- nicoburns 3y agoC and Rust do very different things in this case. C defines overflow of signed integers to be Undefined Behaviour. Whereas in Rust it either wraps (release mode) or panics (debug mode).
- jstimpfle 3y agoAny specific C compiler could do the same in complete agreement with the C standard. There isn't a guarantee that any given standards-conforming compiler will, but it seems that with Rust there isn't a guarantee what behaviour you get either (it depends on the compile settings). In either language, you can't write code that does signed overflow in a meaningful way (at least not if you use Debug).
- xscott 3y agoI agree with your point, but note that Rust does have an ugly way to do it: https://doc.rust-lang.org/std/primitive.i64.html#method.wrapping_add https://doc.rust-lang.org/std/primitive.i64.html#method.wrap... I'd rather just put `-fwrapv` on the command line that clutter my code with crap like that though.
- nicoburns 3y ago> I'd rather just put `-fwrapv` on the command line that clutter my code with crap like that though. The advantage of Rust's way is that it lets you customise addition on a per-operation basis. So you can mix and match wrapping addition with saturating addition, etc.
- xscott 3y agoYes, I can have functions/methods that do math differently from the default. I could just as easily say that's C's way and mix and match those: int64_t x = add_i64_with_abort_on_debug_and_wrap_on_release(y, z); uint8_t t = add_u8_with_saturation(u, v); I'd prefer the default for the math operators be what all the CPUs currently do, and neither C or Rust promises that.
- estebank 3y ago> But integer arithmetic is safe in terms of Rust. To expand on this: integer overflow is not UB, it is unspecified. It can result in clamping, wrapping or a panic, depending on configuration at compile time. > In release mode, it uses modular arithmetic. And I believe that to have been a mistake. Android enables overflow checks by default and there is no measurable performance impact.
- Chabsff 3y ago> It only does so for debug mode. In release mode, it uses modular arithmetic. So it's still treated as an error, just one that has a predictable fallback. I'm really not sure how that's much different from `-fsanitize=undefined`. Broken code is broken, even if it breaks in a predictable manner. Now if the modular arithmetic had been enshrined as the expected behavior without being treated like an error to be caught, it'd be another matter.
- marcosdumay 3y agoAn error does not rewrite your entire code on the assumption that it can not happen. Signed overflow is not an error in C.
- deleted 3y ago[deleted]
- jstimpfle 3y agoThat should just be a matter of a compiler knob, no? Such as -fsanitize=undefined (which is the sledge hammer, but there could be more fine grained ones).
- imtringued 3y agoIt's not. There is no sanitizer on embedded platforms and it turns out, I only use C on embedded platforms, which for me means the UB sanitizer doesn't exist.
- shrimp_emoji 3y agoAlso, that flag enables only unreliable detection of the issue. It won't catch it 100% of the time. :D It also interferes with other flags and checkers like Valgrind and adds bloat to the executable as a bonus.
- Chabsff 3y agoI meant error "in the code". A chunk of C that causes a signed overflow has an error in it. Seemingly, so does Rust code according to the behavior described in the post I was replying to. My point is that I question how big is the value gain from having a predictable fallback when we are already within the realm of "this code is considered wrong". This isn't unlike the various arguments against the value of compiler warnings. That being said, I agree that it's preferable in general, but the difference seems rather marginal to me. That is, within the context of what I'm replying to. I wouldn't be surprised if Rust had a few additional tricks up its sleeve to address this.
- bjourne 3y ago> But integer arithmetic is safe in terms of Rust. It's "defined safety": If a >= 0 and b >= 0 then a + b > = 0. True according to most schoolchildren but not true according to the Rust spec. It breaks the principle of least astonishment and has and will lead to security vulnerabilities.
- uecker 3y agoFor C, I tell my compiler to make it trap. Then it is also safe.