The printf
and scanf
family of functions are easy places to make mistakes which show up either as bugs or portability problems. For example, consider the following code:
foo() { double f; scanf("%f", &f); }
This code will not crash, but the value read into the variable f
will be incorrect because its data type (double
) doesn’t match the float
format specified in the call to scanf
. As a result, incorrect data will be transferred to the program.
Similarly, the following code in the badform2.c
example corrupts memory, since too much data will be written over the supplied variable. This error can be very difficult to detect.
foo() { float f; scanf("%1f", &f); }
A more subtle issue arises when data types used in I/O statements “accidentally” match. The following code functions correctly on machines where types {{int}} and {{long}} have the same number of bits, but fails otherwise.
foo() { long l = 123; printf("l = %d\n", l); }
Insure++ detects this error, but classifies it differently from the previous cases. You can choose to ignore this type of problem while still seeing the previous bugs.
In addition to checking printf and scanf arguments, Insure++ also detects errors in other I/O statements. The following code works as long as the input supplied by the user is shorter than 80 characters, but fails on longer input:
foo(line) { char line[80]; gets(line); }
Insure++ checks for this case and reports an error if necessary.
Insure++ can only check for an overflow after the data has been read. In extreme cases, the act of reading the data will crash the program before Insure++ gets the chance to report it.