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
printf
s. 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 theputs
function, 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 becauseputs
adds 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
printf
in 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.