VNX-191: Integer Underflow (Wrap or Wraparound)
Reports C/C++ length subtractions (len - HDR, len -= consumed, strlen(s) - 1) that size or index a memory operation with no prior check that the length is large enough, where the length is a function parameter or decoded from a message.
| Field | Value |
|---|---|
| Rule ID | VNX-191 |
| Severity | High |
| SARIF level | error |
| Kind | sast |
| Languages | C, C++ |
| CWE | CWE-191 |
| CAPEC | CAPEC-92 |
| ATT&CK | T1190 |
| CWSS vector | CWSS:1.0/TI:H/AP:RU/AL:S/IC:N/FC:LT/RP:RU/RL:S/AV:L/AS:N/IN:A/SC:A/BI:H/DI:H/EX:H/EC:N/P:H |
| Tags | integer-underflow arithmetic buffer cwe-191 |
| Source | internal/sast/rules/vnx-191.rego |
Overview
VNX-191 maps to CWE-191: Integer Underflow (Wrap or Wraparound). Lengths in C are unsigned (size_t). Subtracting a header size from a length that is shorter than the header wraps to a value near SIZE_MAX, and the memcpy, read or malloc that uses it runs far past the buffer.
What Gets Flagged
- A size argument of
memcpy,memmove,memset,strncpy,strncat,malloc,calloc,realloc,read,recv,fread,fwrite,write,send(andstd::forms) written aslen - x, wherelenis a length-like name handed in as a parameter or decoded from a message (ntohs(...),hdr->len). - An unsigned declaration initialised as
a - b, orlen -= xon an unsigned variable, whose result reaches such a call within 8 lines. buf[strlen(buf) - 1], which indexes before the buffer when the string is empty.
int parse_packet(const uint8_t *pkt, size_t len, uint8_t *out)
{
memcpy(out, pkt + HDR_LEN, len - HDR_LEN); /* flagged */
}
void chomp(char *line)
{
line[strlen(line) - 1] = '\0'; /* flagged */
}
Not flagged: a subtraction preceded within 10 lines by a comparison of the length (if (len < HDR_LEN) return -1;), a ternary or min(), constant minuends (sizeof(buf) - 1), pointer differences, lengths a data structure maintains itself (node->size - pos), and comments. Go and Java are not covered: Go panics on an out-of-range slice and Java has no unsigned lengths.
Remediation
if (len < HDR_LEN)
return -1;
memcpy(out, pkt + HDR_LEN, len - HDR_LEN);
size_t n = strlen(line);
if (n > 0 && line[n - 1] == '\n')
line[n - 1] = '\0';
References
- CWE-191: Integer Underflow (Wrap or Wraparound)
- SEI CERT INT30-C: Ensure that unsigned integer operations do not wrap
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-191
// nosec vnx-191
Or record an ignore rule: vulnetix ignore add --rule vnx-191 --reason "...". See Suppressing findings.