SV.FMT_STR.PRINT_FORMAT_MISMATCH.BAD

规范和参数不匹配

打印函数参数会占用堆栈内存块(这些块包含的计算机字的数量为整数)。如果打印函数参数占用的堆栈内存的数量不同于对应的格式字符串规范预期的数量,则可能产生漏洞。SV.FMT_STR.PRINT_FORMAT_MISMATCH.BAD 检查器会标记出那些其中的打印参数的内存块大小与对应的格式字符串规范不匹配的代码。

漏洞与风险

不匹配的参数和格式字符串规范会造成内存访问冲突,从而可能导致意外的程序执行结果。有可能会出现未定义的行为和异常的程序终止。

漏洞代码示例

复制
   # 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 标记了第 4 行,因为 %d 规范与 double 类型的参数不匹配。类型 int 所需的内存量(%d 规范预期的数量)与类型 double(实际提供的数量)不同。在大多数 32 位系统中,类型 int 需要一个计算机字,而类型 double 需要两个。当从堆栈中读取一个计算机字(而非读取参数实际占用的两个计算机字)时,则可能发生内存访问冲突。

标记了第 5 行,因为此处没有调用 std::string::c_str() 方法。%s 规范预期以空值终止的字符串,但是实际上提供的是一个对象。当尝试读取对象占用的内存字节及直至遇到空字符为止的任何后续字节时,则可能导致内存访问冲突。

修正代码示例

复制
   # 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());            
   }

在经修正的代码的第 4 行中,使用了正确的格式说明符 %f 来打印浮点值。第 5 行中添加了对 std::string::c_str() 方法的调用(此方法经常被错误地遗漏)。