VNX-686: Function Call With Incorrect Argument Type
Detects C and C++ printf- and scanf-family calls whose argument type visibly mismatches its conversion: size_t to %d, non-strings to %s, std::string without .c_str(), and scanf targets passed by value.
| Field | Value |
|---|---|
| Rule ID | VNX-686 |
| Severity | Low |
| SARIF level | note |
| Kind | sast |
| Languages | C, C++ |
| CWE | CWE-686 |
| CAPEC | CAPEC-66 |
| ATT&CK | T1190 |
| CWSS vector | CWSS:1.0/TI:L/AP:RU/AL:S/IC:N/FC:LT/RP:RU/RL:S/AV:L/AS:N/IN:A/SC:A/BI:L/DI:H/EX:L/EC:N/P:L |
| Tags | format-argument-type cwe-686 |
| Source | internal/sast/rules/vnx-686.rego |
Overview
VNX-686 maps to CWE-686: Function Call With Incorrect Argument Type. A variadic call reads each argument as the type its conversion names. Passing a 64-bit size_t to %d, an integer to %s or a std::string object to %s is undefined behaviour: the call reads the wrong bytes, or dereferences an integer as a pointer.
What Gets Flagged
printf("name is %d bytes\n", strlen(name)); // FLAGGED: size_t to %d
printf("status %s\n", 404); // FLAGGED: integer to %s
sprintf(buf, "%d items", "ten"); // FLAGGED: string to %d
printf("%f\n", 1); // FLAGGED: int to %f
scanf("%d", count); // FLAGGED: int count; needs &count
size_t len = strlen(s);
double ratio = 0.5;
printf("len=%d\n", len); // FLAGGED: declared size_t
printf("ratio=%d\n", ratio); // FLAGGED: declared double
printf("name=%s id=%d\n", name, id); // FLAGGED: name is a std::string
std::printf("user %s\n", std::to_string(id)); // FLAGGED
What Is Not Flagged
%zu/%zdand%lu, explicit casts, and.c_str().- Pointers and arrays passed to scanf.
- Calls whose argument count differs from the format (VNX-685 reports those), calls split over several lines, and macro-built formats.
- Comments and string literals.
Remediation
Use the conversion that matches the type (%zu for size_t), pass .c_str() for C++ strings and &var to scanf, and compile with -Wall -Wformat=2.
References
Suppressing this rule
Put a nosec comment on the line, or on line 1 to cover the whole file. Use the comment marker of the file’s language (#, //, -- or ;):
# nosec vnx-686
// nosec vnx-686
Or record an ignore rule: vulnetix ignore add --rule vnx-686 --reason "...". See Suppressing findings.