VNX-681: Incorrect Conversion between Numeric Types
Detects lengths, sizes and file offsets narrowed to a type too small to hold them: C/C++ 8- and 16-bit variables or casts from strlen, read or ftell, int from ftell/lseek, and Java int/short casts of long sizes and times.
| Field | Value |
|---|---|
| Rule ID | VNX-681 |
| Severity | Medium |
| SARIF level | warning |
| Kind | sast |
| Languages | C, C++, Java |
| CWE | CWE-681 |
| CAPEC | CAPEC-66 |
| ATT&CK | T1190 |
| CWSS vector | CWSS:1.0/TI:M/AP:RU/AL:S/IC:N/FC:LT/RP:RU/RL:S/AV:L/AS:N/IN:A/SC:A/BI:M/DI:H/EX:M/EC:N/P:C |
| Tags | numeric-truncation cwe-681 |
| Source | internal/sast/rules/vnx-681.rego |
Overview
VNX-681 maps to CWE-681: Incorrect Conversion between Numeric Types. A length stored in a uint16_t, or a file size cast to int, silently wraps once the value is large enough. The truncated number then sizes a copy, an allocation or a seek, and the code works on test data and fails on the large input an attacker supplies.
What Gets Flagged
uint16_t name_len = strlen(name); // FLAGGED: 8/16-bit from a length
out[2] = (uint8_t)strlen(name); // FLAGGED: narrowing cast
int size = ftell(fp); // FLAGGED: file offset into int
pos = (int)ftello(fp); // FLAGGED
char c;
while ((c = fgetc(fp)) != EOF) { ... } // FLAGGED: EOF test after narrowing to char
byte[] buf = new byte[(int) uploadFile.length()]; // FLAGGED
int size = (int) Files.size(p); // FLAGGED
int len = (int) conn.getContentLengthLong(); // FLAGGED
short id = (short) System.currentTimeMillis(); // FLAGGED
C and C++: variables declared as char, short, uint8_t, uint16_t, BYTE, WORD, USHORT and similar, initialised from or cast from strlen, wcslen, strnlen, ftell, ftello, lseek, read, recv, recvfrom, fread or C++ .size()/.length(); and int/unsigned int from ftell/ftello/lseek. Java: casts to int, short, byte or char of Files.size(), getContentLengthLong(), getSize(), getCompressedSize(), length() on a file, size()/position() on a channel, System.currentTimeMillis() and System.nanoTime().
What Is Not Flagged
int len = strlen(s)and the(int)strlen(s)idiom for a printf precision.- Conversions to
size_t,long,off_t,uint32_tand wider. Math.toIntExact(...), and casts ofint-valuedsize()/length()calls on collections and strings.- Comments and string literals.
Remediation
Keep sizes in size_t/off_t (C) or long (Java). Where a narrower type is required by a format or protocol, check the range first and fail on overflow: if (n > UINT16_MAX) return -1; or Math.toIntExact(file.length()).
References
- CWE-681: Incorrect Conversion between Numeric Types
- SEI CERT INT31-C: Ensure that integer conversions do not result in lost or misinterpreted data
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-681
// nosec vnx-681
Or record an ignore rule: vulnetix ignore add --rule vnx-681 --reason "...". See Suppressing findings.