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);
}
在经修正的代码中,每一种格式字符串规范和参数都兼容。