In this section:

Overview

This error is generated when there is a mismatch in format specification, such as 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 mismatches which have different levels of severity as follows:

CodeDescriptionEnabledReportedPlatform
BAD_DECLIncompatible global declarations(error)

Compilation

Runtime

Windows/Unix
(sign)Types differ only by sign, e.g., int vs. unsigned int(error)CompilationWindows/Unix
(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.(error)CompilationWindows/Unix
(incompatible)Fundamental types are different, e.g., int vs. double(tick)RuntimeWindows/Unix
(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(tick)CompilationWindows/Unix


Error messages are classified according to this scheme and can be selectively enabled or disabled

Problem 1

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.

/*
 * File: badform1.c
 */
main()
{
	double f = 1.23;
	int i = 99;

	printf("%d %f\n”, f, i);
}

This type of mismatch is detected during compilation. Another problem includes badform4.c. A diagnosis similar to the one that follows applies.

Diagnosis During Compilation

[badform1.c:9] **BAD_FORMAT(incompatible)**
		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);
  • Line 1: Source line at which the problem was detected.
  • Line 2: Description of the problem and the arguments that are incorrect.

Problem 2

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.

/*
 * File: badform2.c
 */
main()
{
	int a;
	float f;

	scanf("%lf, %f);
}

This problem, as well as the WRITE_OVERFLOW (not shown), is diagnosed at compile time.

Diagnosis During Compilation

[badform2.c:9] **BAD_FORMAT(incompatible)**
		Wrong type passed to scanf (argument 2).
		Expected double *, found float *.
>> 				scanf("%lf\n", &f);


  • Line 1: Source line at which the problem was detected.
  • Line 2: Description of the problem and the arguments that are incorrect.

Problem 3

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 of the calling routine, however, the arguments are reversed.

/*
 * File: badform3.c
 */
char *file;
int line;


error(format)
	char *format;
{
	printf(format,file,line);
}


main()
{
	file = "foo.c";
	line = 3;

	error("Line %d, file %s\n");
}

Diagnosis at Runtime

[badform3.c:10] **BAD_FORMAT(incompatible)**
>> 			printf(format,file,line);
	Format string is inconsistent:
			Wrong type passed to printf (argument 3).
	Expected pointer, found int.
	Format string: "Line %d, file %s\n"
	Stack trace where the error occurred:
			error() badform3.c, 10
			main() badform3.c, 18
  • Line 2: Source line at which the problem was detected.
  • Line 3: Description of the problem and the argument that is in error.
  • Line 6: Explanation of the error and the format string that caused it.
  • Line 7: 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. 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 because a pointer and an integer are both the same size in memory. Because compatible BAD_FORMAT errors are suppressed by default, you will not see it. These errors are suppressed because they tend to 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.

Repair

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.

You can correct Problem 1, for example, 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 suppress BAD_FORMAT in the Suppressions Control Panel.

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 following syntax where the arguments are one or more of the identifiers for the various categories of errors described in Overview:

BAD_FORMAT(class1, class2, …)

Similarly, you can enable suppressed types by unsuppressing them in the Suppressions Control Panel. The problem with the pointer and integer that was not shown in the current example could be displayed by unsuppressing BAD_FORMAT(compatible) in the Suppressions Control Panel. For an example of this option, as well as the remaining subcategories of BAD_FORMAT, see the example badform4.c.

  • No labels