Building on the answers about using numbers as a ring mod 2^32, some hashing and checksum algorithms are built to be performed modulo a word size. For example, for a CRC code, common implementations choose a polynomial so that they can be computed very quickly using an unsigned 16-bit integer (Bluetooth, USB), 32-bit integer (Ethernet, GZIP, MPEG-2, Adler-32), 64-bit integer, etc. In these cases, the math operates on a polynomial over the finite field with 2 elements, which isn't important for this answer aside from just saying it maps directly to a binary integer and overflow is completely intended. Also, MD5 and SHA-1 are designed to use unsigned 32-bit ints with wrapping.
In my opinion, it's much safer to explicitly say when you want this overflow behavior. But getting the compiler to not warn about all the false positives without manually annotating every math operation is difficult. Linus Torvalds ranted last year against a proposal for the Linux kernel for C operator overloading by handling overflows with handlers:
I'm still entirely unconvinced.
The thing is, wrap-around is not only well-defined, it's common, and
EXPECTED.
Example:
static inline u32 __hash_32_generic(u32 val) {
return val * GOLDEN_RATIO_32; }
and dammit, I absolutely DO NOT THINK we should annotate this as some
kind of "special multiply".
I have no idea how many of these exist. But I am 100% convinced that
making humans annotate this and making the source code worse is
absolutely the wrong approach.
Basically, unsigned arithmetic is well-defined as wrapping around, and
it is so for a good reason.
So I'm going to have a HARD REQUIREMENT that any compiler complaints
need to be really really sane. They need to detect when people do
things like this on purpose, and they need to SHUT THE ^&% UP about
the fact that wrap-around happens.
Any tool that is so stupid as to complain about wrap-around in the
above is a BROKEN TOOL THAT NEEDS TO BE IGNORED.
Really. This is non-negotiable.
This is similar to the whole
unsigned int a, b;
if (a+b < a) ..
kind of pattern: a tool that complains about wrap-around in the above
is absolutely broken sh*t and needs to be ignored.
So I think you need to limit your wrap-around complaints, and really
think about how to limit them. If you go "wrap-around is wrong" as
some kind of general; rule, I'm going to ignore you, and I'm going to
tell people to ignore you, and refuse any idiotic patches that are the
result of such idiotic rules.
Put another way the absolute first and fundamental thing you should
look at is to make sure tools don't complain about sane behavior.
Until you have done that, and taken this seriously, this discussion is
not going to ever result in anything productive.
Any kind of mindless "this can wrap around" is inexcusable.
And later:
It needs to be smarter than that. And yes, that means exactly taking
into account how the result of the possible wrap-around is actually
used.
If it's used as a size or as an array index, it might be a problem.
But if it's used for masking and then a masked version is used for
an index, it clearly is NOT a problem.
IOW, exactly the same as "a+b < a". Yes, "a+b" might wrap around, but
if the use is to then compare it with one of the addends, then clearly
such a wrap-around is fine.
A tool that doesn't look at how the result is used, and just blindly
says "wrap-around error" is a tool that I think is actively
detrimental.
And no, the answer is ABSOLUTELY NOT to add cognitive load on kernel
developers by adding yet more random helper types and/or functions.
We already expect a lot of kernel developers. We should not add on to
that burden because of your pet project.
Put another way: I'm putting the onus on YOU to make sure your pet
project is the "Yogi Bear" of pet projects - smarter than the average
bear.
As long as you are approaching this from a "this puts the onus on
others", YOU are the problem.
Be the solution, not the problem.
Linus
if (a + b < a)) too. Overflow on multiplication is hard for both signed and unsigned types.MAX_INT+1 == -0, while on a two's complement it would beINT_MIN