SV.FMT_STR.SCAN_IMPROP_LENGTH

Incompatible scan length modifier

In certain types of format specifications, length modifiers for parameters, such as h, l, or L, can be used in the format string. The SV.FMT_STR.SCAN_IMPROP_LENGTH checker produces a warning if a length modifier can't be used with the given format specifier-for example, in the specification %hf, the h length modifier doesn't make any sense when used with the %f format specifier.

Vulnerability and risk

A compiler normally ignores the incompatible use of length modifiers. However, such use cases may show that a developer intended to use a different format specification and made a mistake, so the Klocwork warning allows the designer to consider the change to the correct specification.

Mitigation and prevention

The compatibility of parameters and length modifiers depends on the particular compiler you're using, so it's best to check compiler-specific help or documentation, such as the appropriate fscanf Linux man page or the MSDN web site. A general resource document is the CERT site's article, FIO00-C: Take care when creating format strings.

Vulnerable code example

Copy
 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 flags errors at lines 2, 6, and 7 to indicate mismatches between the format-string specification and the parameter. The format specification shows that in line 2, a character string is expected, in line 6, a character is expected, and in line 7, a hexadecimal is expected, and none of the modifiers in these lines makes sense with the specifications. In contrast, lines 3, 4, and 5 show examples of specification and modifier that are compatible.

Fixed code example

Copy
 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);    
 }

In the fixed code, each format-string specification and the parameter are compatible.