SV.FMT_STR.SCAN_FORMAT_MISMATCH.UNDESIRED

非预期的规范和参数匹配

SV.FMT_STR.SCAN_FORMAT_MISMATCH.UNDESIRED 检查器会标记那些扫描函数参数与对应的格式字符串规范不匹配的代码。如果参数指向的项目的类型大小不小于对应的格式字符串规范所预期的大小,则该检查器会报告漏洞。

漏洞与风险

因为参数指向的类型的大小大于或等于规范预期的大小,所以不会出现内存损坏的情况,但是可能导致将非预期的值写入所指向的项目。将代码移植到不同平台时也可能遇到问题。

漏洞代码示例

复制
  char* pc;
  int i;
  char c;
  long l;
  long long ll;
 
  void scan_all(FILE* f) {
    fscanf(f, "%s", pc);
    fscanf(f, "%d", &pc);  // fscanf format mismatch
   fscanf(f, "%d", &i);
   fscanf(f, "%hx", &i);  // fscanf format mismatch
   fscanf(f, "%c", &l);   // fscanf format mismatch
   fscanf(f, "%p", &ll);  // fscanf format mismatch
 }

Klocwork 在第 9 行、第 11 行、第 12 行和第 13 行标记出错误,表明格式字符串规范和参数之间不匹配。格式规范显示第 9 行中预期指向 int 类型的指针,第 11 行中预期指向 short int 类型的指针,第 12 行中预期指向 char 类型的指针,第 13 行中预期指向指针的指针,但是这几行中提供的参数都与预期的不符。但是,因为在这几行中,参数占用的内存项目都不小于规范的预期,所以该错误被视为 UNDESIRED 而不是 BAD。相比之下,第 8 行和第 10 行显示的是规范与参数相匹配的示例。

修正代码示例

复制
  char* pc;
  int i;
  char c;
  long l;
  long long ll;
  short s;
 
  void scan_all(FILE* f) {
    fscanf(f, "%s", pc);
   fscanf(f, "%p", &pc);
   fscanf(f, "%d", &i);
   fscanf(f, "%hx", &s);
   fscanf(f, "%ld", &l);
   fscanf(f, "%lld", &ll);
 }

在经修正的示例中,每一种格式规范和参数都相互对应。