note : removed printf part, since it's explained in a different post.
I learned C from K&R 2nd edition a few yours ago. I have not used C in a while, so I decided to skim through a more modern book. “C How to Program, 8th Edition” by Deitel and Deitel (published by Pearson in 2015), which has C99 and C11.
He covers security, unlike K&R. One thing that surprised me, is integer overflow. He wrote:
Section 3.13 Secure C Programming • Adding integers can result in a value that’s too large to store in an int variable. This is known as arithmetic overflow and can cause unpredictable runtime behavior, possibly leaving a system open to attack.
In a different page he has:
It’s considered a good practice to ensure that before you perform arithmetic calculations like the one in line 18 of Fig. 2.5, they will not overflow. The code for doing this is shown on the CERT website https://www.securecoding.cert.org — just search for guideline “INT32-C.”
If you look up the code they recommend:
5.3.3.2 Compliant Solution This compliant solution ensures that the addition operation cannot overflow, regardless of representation:
#include <limits.h>
void f(signed int si_a, signed int si_b)
{
signed int sum;
if (((si_b > 0) && (si_a > (INT_MAX - si_b))) ||
((si_b < 0) && (si_a < (INT_MIN - si_b)))) {
/* Handle error */
}
else {
sum = si_a + si_b;
}
/* ... */
}
My understanding was, although unsigned int behavior is undefined, it's always a fixed size of bits. On my computer it's a 32 bit int. So on my laptop my INT_MAX = 2147483647 and if I add 1 to it i get -2147483648. If I keep adding one to it, it will eventually get to 0, then go back up to INT_MAX and keep going round and round. I don’t see how this can be attacked by someone using my code?
To add extra code, every time I add ints, seems very wasteful, unless there really is a variability I have to look out for, not just getting the wrong result.
edit: I'm adding the quote back, because of the discussion below:
Avoid Single-Argument
printfs. One such guideline is to avoid using printf with a single string argument. If you need to display a string that terminates with a newline, use theputsfunction, which displays its string argument followed by a newline character. For example, in Fig. 2.1, line 8
printf( "Welcome to C!\n" );should be written as:puts( "Welcome to C!" );We did not include \n in the preceding string becauseputsadds it automatically. If you need to display a string without a terminating newline character, use printf with two arguments — a "%s" format control string and the string to display. The %s conversion specifier is for displaying a string. For example, in Fig. 2.3, line 8
printf( "Welcome " );should be written as:
printf( "%s", "Welcome " );Although the
printfin this chapter as written are actually not insecure, these changes are responsible coding practices that will eliminate certain security vulnerabilities as we get deeper into C.
volatilewill affect the behaviour of integer arithmetic overflow? Can you provide any authoritative reference that explains your suggestion?volatiledoes — and it is not at all obvious to me why you think it would have any effect whatsoever on the behaviour of integer overflow. "All"volatiledoes is say that the compiler must make an appropriate reference to the volatile-qualified variable whenever the source code refers to it, so it cannot (for example) optimize reads away assuming that the value is still the same as the last time it was read — which has precisely nothing to do with how an integer expression is evaluated once the values are read, which is what's relevant to overflow.