Insure++ Reference - BAD_FORMAT
This error is generated when a call to one of the
printf or scanf routines
contains a mismatch between a parameter type and the corresponding
format specifier or the format string is nonsensical.
Insure++ distinguishes several types of mismatch which have
different levels of severity as follows:
sign
|
Types differ only by sign, e.g., int vs.
unsigned int .
|
compatible
|
Fundamental types are different but they happen to have
the same representation on the particular hardware in use,
e.g., int vs. long on
machines where both are 32-bits,
or int * vs. long where
both are 32-bits.
|
incompatible
|
Fundamental types are different, e.g. int vs.
double .
|
other
|
A problem other than an argument type mismatch is detected,
such as passing the wrong number of arguments.
|
Error messages are classified according to this scheme and can be
selectively enabled or disabled as described in the
"Repair"
section.
An example of format type mismatch occurs when the format specifiers
passed to one of the printf routines do not
correspond to the data, as shown below.
1: /*
2: * File: badform1.c
3: */
4: main()
5: {
6: double f = 1.23;
7: int i = 99;
8:
9: printf("%d %f\n\", f, i);
10: }
This type of mismatch is detected during compilation.
1. [badform1.c:9] **BAD_FORMAT(incompatible)**
2. Wrong type passed to printf (argument 2).
Expected int, found double.
>> printf("%d %f\n", f, i);
[badform1.c:9] **BAD_FORMAT(incompatible)**
Wrong type passed to printf (argument 3).
Expected double, found int.
>> printf("%d %f\n", f, i);
- Source lines at which problems were detected.
- Description of the problem and the arguments that are incorrect.
A more dangerous problem occurs when the types passed as arguments to one
of the scanf functions are incorrect. In the following code, for
example, the call to scanf tries to read a double
precision value, indicated by the "%lf "
format, into a single precision value. This will overwrite memory.
1: /*
2: * File: badform2.c
3: */
4: main()
5: {
6: int a;
7: float f;
8:
9: scanf("%lf\', &f);
10: }
This problem is again diagnosed at compile time along with the
WRITE_OVERFLOW , which is not shown below).
1. [badform2.c:8] **BAD_FORMAT(incompatible)**
2. Wrong type passed to scanf (argument 2).
Expected double *, found float *.
>> scanf("%lf\n", &f);
- Source lines at which problems were detected.
- Description of the problem and the arguments that are incorrect.
A third type of problem is caused when the format string being used
is a variable rather than an explicit string. The following code contains
an error handler that attempts to print out a message containing a filename
and line number. In line 18
1: /*
2: * File: badform3.c
3: */
4: char *file;
5: int line;
6:
7: error(format)
8: char *format;
9: {
10: printf(format, file, line);
11: }
12:
13: main()
14: {
15: file = "foo.c";
16: line = 3;
17:
18: error("Line %d, file %s\n");
19: }
of the calling routine, however, the arguments are reversed.
[badform3.c:10] **BAD_FORMAT(incompatible)**
1. >> printf(format, file, line);
2. Format string is inconsistent:
Wrong type passed to printf (argument 3).
Expected pointer, found int.
3. Format string: "Line %d, file %s\n"
Stack trace where the error occurred:
4. error() badform3.c, 10
main() badform3.c, 18
- Source line at which the problem was detected.
- Description of the problem and the argument that is in error.
- Explanation of the error and the format string that caused it.
- Stack trace showing the function call sequence leading to the
error.
The error diagnosed in this message is in the
"incompatible " category, because any attempt
to print a string by passing an integer variable will result in garbage.
Note that with some compilers, this program may cause a core dump because
of this error, while others will merely produce incorrect output.
There is, however, a second potential error in this code in the same
line.
Because the arguments are in the wrong order in line 7, an attempt will
be made to print a pointer variable as an integer. This error is in the
"compatible" class, since a pointer and an
integer are both the same size in memory. Since
"compatible" BAD_FORMAT errors are suppressed
by default, you will not see it. (These errors are suppressed because they
will cause unexpected rather than incorrect behavior.)
If you enabled these errors, you would see a second problem report from
this code.
If you run Insure++ on an architecture where pointers and
integers are not the same length, then this second error would also be
in the "incompatible " class and would be
displayed by default.
Most of these problems are simple to correct based on the information
given. Normally, the correction is one or more of the following
- Change the format specifier used in the format string.
- Change the type of the variable involved.
- Add a suitable typecast.
For example, problem #1 can be corrected by simply changing the
incorrect line of code as follows
badform1.c, line 9:printf("%d %f\n", i, f);
The other problems can be similarly corrected.
If your application generates error messages that you wish to ignore,
you can add the option
insure++.suppress BAD_FORMAT
to the .psrc file.
This directive suppresses all BAD_FORMAT messages.
If you wish to be more selective and suppress only a certain type of
error, you can use the syntax
insure++.suppress BAD_FORMAT(class1, class2, ...)
where the arguments are one or more of the identifiers for the various
categories of error described in
BAD_FORMAT.
Similarly, you can enable suppressed types with an unsuppress
command. The problem with the pointer and integer that was not shown in the
current example could be displayed by adding the option
insure++.unsuppress BAD_FORMAT(compatible)
to your .psrc file.
BAD_DECL
BAD_INTERFACE
|