VNX-786: Access of Memory Location Before Start of Buffer
C/C++ indexing with strlen()-1 or a read()/recv() result that is never checked, and literal negative indexes on declared arrays.
| Field | Value |
|---|---|
| Rule ID | VNX-786 |
| Severity | Medium |
| SARIF level | warning |
| Kind | sast |
| Languages | C, C++ |
| CWE | CWE-786 |
| 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 | buffer-oob cwe-786 |
| Source | internal/sast/rules/vnx-786.rego |
Overview
VNX-786 maps to CWE-786: Access of Memory Location Before Start of Buffer. It reports C and C++ indexing that reaches before the start of a buffer when a length is zero or a call failed:
X[strlen(Y) - 1]with no length or first-byte check in the three lines aboveX[n - 1]wherenwas assigned fromstrlen()and never checked before the indexX[n]orX[n - 1]wherencame fromread(),recv(),recvfrom(),readlink()orpread(), which return -1 on error, and was never checked- a literal negative index (
counts[-1]) on a name whose nearest declaration is an array
Negative indexes on pointers into the middle of a buffer (p[-1]) and lengths compared anywhere between the assignment and the index are not reported.
Why This Matters
line[strlen(line) - 1] = '\0' after fgets() writes line[-1] when the line is empty (an input starting with a NUL byte is enough). buf[n] = '\0' after a failed read() writes buf[-1]. Both corrupt the byte before the buffer, which is often a saved pointer or another variable.
What Gets Flagged
line[strlen(line) - 1] = '\0'; // FLAGGED: empty line writes line[-1]
ssize_t n = read(fd, buf, sizeof(buf) - 1);
buf[n] = '\0'; // FLAGGED: n is -1 on error
Not flagged:
size_t len = strlen(s);
if (len > 0 && s[len - 1] == '\n')
s[len - 1] = '\0';
Remediation
- Check the length is non-zero before subtracting one from it.
- Check
read()/recv()results for< 0(and== 0) before using them as an index.
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-786
// nosec vnx-786
Or record an ignore rule: vulnetix ignore add --rule vnx-786 --reason "...". See Suppressing findings.