SV.FMT_STR.PRINT_FORMAT_MISMATCH.BAD

Mismatched specification and parameter

Print function parameters can occupy stack memory blocks that consist of whole numbers of machine words. If a print function parameter occupies an amount of stack memory different from that expected from the corresponding format-string specification, a vulnerability can result. The SV.FMT_STR.PRINT_FORMAT_MISMATCH.BAD checker flags code in which the size of the memory block for the print parameter and the corresponding format-string specification don't match.

Vulnerability and risk

A mismatched parameter and format-string specification can cause memory access violation and may lead to undesired program execution results. Undefined behavior and abnormal program termination are possible.

Vulnerable code example

Copy
   # include <string>
   # include <stdio.h>
   void print_string(double weight, std::string str) {
     printf("String of weight %d:", weight);   // defect
     printf(" %s\n", str);                     // defect
   }

Klocwork flags line 4 because the %d specification doesn't match the parameter of type double. Different amounts of memory are required for type int, which is expected for the %d specification, and type double, which is actually provided. On most 32-bit systems, type int needs one machine word and type double needs two. A memory access violation may occur when one machine word is read from the stack instead of the two words actually occupied by the parameter.

Line 5 is flagged because there is no call to the std::string::c_str() method. A null-terminated string is expected for the %s specification, but an object is actually provided instead. A memory access violation can be caused when an attempt is made to read the memory bytes occupied by the object and any successive bytes until a null character is met.

Fixed code example

Copy
   # include <string>
   # include <stdio.h>
   void print_string(double weight, std::string str) {
     printf("String of weight %f:", weight);   
     printf(" %s\n", str.c_str());            
   }

In line 4 of the fixed code, the correct format specifier, %f, is used for printing a floating point value. In line 5, the call to std::string::c_str() method is added (it is often omitted by mistake).