This got nothing to do with the memory but to the fact how CPU works with the integers. This means that (low-level) programming language fundamentally cannot solve this problem but only alleviate it either by:
1. Changing the semantics of integer arithmetic (e.g. saturate on overflow)
2. Keeping the semantics but babysit the computation during runtime so that the overflow/underflow can never happen (expensive)
First, unsigned integer underflow and overflow is _not_ UB. It is very well defined operation (wrap-around arithmetic) and the bug in question is not the result of undefined behavior and rust or whatever other bs I keep hearing around would have not solved it. It's the fundamental artifact of how CPUs work.
Secondly, CPUs have been "alerting" through their carry and overflow bits in registers since forever so this isn't some exclusive feature that only rust compiler writers were smart enough to take advantage of. The same code can be and is written where it matters in C and C++ code too.
It's not only the question if such extra checks are expensive (which they are given that integer arithmetic is such a fundamental operation and your favorite language disables it in release builds for the sakes of, I guess, nothing?) but it is also a question of all known _semantics_ of unsigned
integer arithmetic. That's simply the way they work and I see no near future where the CPU hardware engineers would change that (they will not).
> First, unsigned integer underflow and overflow is _not_ UB. It is very well defined operation (wrap-around arithmetic) and the bug in question is not the result of undefined behavior
Shockingly true. Per the C Standard, "6.2.5 Types" paragraph 9:
A computation involving unsigned operands can never overflow, because a result that cannot be represented by the resulting unsigned integer type is reduced modulo the number that is one greater than the largest value that can be represented by the resulting type.
What you actually want is to enable some kind automatic trapping behavior when a section of code is entered so that you can say “this set of math operations shouldn’t overflow”. That’s cheaper than what overflow bits get you although entering/exiting such a mode may be equally or more expensive.
The existence of the overflow bits and that overflow continues to remain a common security flaw indicates that there’s a disconnect between the mental model users have when writing this kind of arithmetic (ie they don’t think about it generally and C integer promotion rules don’t do any favors) and how CPU designers imagine you write code.
> you can say “this set of math operations shouldn’t overflow”
This is the same as putting an "if" statement to check for sizes (before or after the operation); the thing that other languages automatically do for you at runtime (with its performance implications).
> The existence of the overflow bits and that overflow continues to remain a common security flaw
What do you propose for a new CPU architecture/instruction set/register types?
How would you implement it? Signed registers?
> how CPU designers imagine you write code.
Write a program in assembler. You'll be checking carry/overflow bits in no-time.
> CPUs have been "alerting" through their carry and overflow bits in registers since forever so this isn't some exclusive feature that only rust compiler writers were smart enough to take advantage of.
Another way of putting it: C/C++ have been handling overflow badly since forever despite hardware support, but now Rust and other more security aware systems languages are free to take advantage of it.
I hope Rust will take the opportunity sooner or later, as the semantics seem to allow it.
You could imagine a version of the arithmetic instructions that traps on overflow. Or maybe a prefix for the normal instruction. Then it can be basically free in the happy path.
1. Changing the semantics of integer arithmetic (e.g. saturate on overflow)
2. Keeping the semantics but babysit the computation during runtime so that the overflow/underflow can never happen (expensive)