SV.FMT_STR.SCAN_IMPROP_LENGTH

不兼容的扫描长度修饰符

在特定类型的格式规范中,可以在格式字符串中使用参数的长度修饰符(例如 h、l 或 L)。如果不能将长度修饰符与给定的格式说明符一起使用,则 SV.FMT_STR.SCAN_IMPROP_LENGTH 检查器会发出警告。例如,在规范 %hf 中,长度修饰符 h 与格式说明符 %f 一起使用时没有任何意义。

漏洞与风险

编译器通常会忽略不兼容的长度修饰符用法。但是,此类使用案例可能表示开发者打算使用不同的格式规范,并且在使用过程中出错,因此 Klocwork 警告允许设计者考虑改用正确的规范。

缓解与预防

参数和长度修饰符的兼容性取决于正在使用的特定编译器,因此最好是查看特定于编译器的帮助或文档,例如适当的 fscanf Linux 手册页或 MSDN 网站。常用的资源文档是 CERT 网站的文章 FIO00-C:小心创建格式字符串

漏洞代码示例

复制
 void foo(FILE* f, char* pc, int i, long l, struct SomeStruct ss, long double ld) {
     fscanf(f, "%2hs", pc);     // improper use of 'h' modifier
     fscanf(f, "%lc", &i);         
     fscanf(f, "%10ld", &l);
     fscanf(f, "%hx", &i);
     fscanf(f, "%hc", pc);      // 'h' modifier used with 'c' type character
     fscanf(f, "%Lx", &l);      // 'L' modifier used with 'x' type character
     fscanf(f, "%Lf", &ld);    
 }

Klocwork 在第 2 行、第 6 行和第 7 行标记出错误,表明格式字符串规范和参数之间不匹配。格式规范显示第 2 行中预期字符串,第 6 行中预期字符,第 7 行中预期十六进制数,但是这几行中提供的修饰符在与规范一起使用时都没有意义。相比之下,第 3 行、第 4 行和第 5 行显示的是规范与修饰符兼容的示例。

修正代码示例

复制
 void foo(FILE* f, char* pc, int i, long l, struct SomeStruct ss, long double ld) {
     fscanf(f, "%s", pc);
     fscanf(f, "%lc", &i);         
     fscanf(f, "%10ld", &l);
     fscanf(f, "%hx", &i);
     fscanf(f, "%c", pc);
     fscanf(f, "%x", &l);
     fscanf(f, "%Lf", &ld);    
 }

在经修正的代码中,每一种格式字符串规范和参数都兼容。