VNX-806: Buffer Access Using Size of Source Buffer
A C/C++ copy into a destination buffer is bounded by the size of the SOURCE instead of the destination, so a long source overruns the destination: memcpy, memmove, strncpy, strncat, strlcpy, strlcat, wcsncpy, wcsncat, wmemcpy or wmemmove whose count is strlen(src), wcslen(src) or sizeof(src) of the same expression passed as the source (optionally + 1), a variable assigned from one of those in the ten lines above, or, for a C++ string, s.size()/s.length() with s.c_str()/s.data() as the source. Calls broken across up to three lines are read whole. Not reported: a destination allocated in the twelve lines above (malloc/calloc/realloc/alloca/strdup/new[]/kmalloc, sized from the source), a destination that is itself a container's buffer (v.data(), &s[0]), a length compared with something (a <, >, <= or >= on strlen(src), the length variable or sizeof(dst)) in the twelve lines above or on the call line, a count wrapped in MIN/min, a string-literal or address-of (&x) source, calls spelled inside string literals, and comments. Reading from a source pointer, an unknown destination capacity and cross-function flows are out of scope.
| Field | Value |
|---|---|
| Rule ID | VNX-806 |
| Severity | Medium |
| SARIF level | warning |
| Kind | sast |
| Languages | C, C++ |
| CWE | CWE-806 |
| 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-access-source-size cwe-806 memory-safety |
| Source | internal/sast/rules/vnx-806.rego |
Overview
VNX-806 maps to CWE-806: Buffer Access Using Size of Source Buffer. It reports bounded copies whose bound is the length of what is being copied rather than the room in the destination, which makes the bound meaningless.
What Gets Flagged
char dst[32];
memcpy(dst, src, strlen(src)); /* FLAGGED */
strncpy(buf, input, strlen(input)); /* FLAGGED */
char out[16]; char big[256];
memcpy(out, big, sizeof(big)); /* FLAGGED: size of the source array */
size_t n = strlen(arg);
memcpy(local, arg, n); /* FLAGGED: two-line form */
Not flagged: memcpy(dst, src, sizeof(dst)), a copy into malloc(strlen(s) + 1), a copy preceded by if (strlen(src) >= sizeof(dst)) return -1;, memcpy(&x, raw, sizeof(x)), copies between arrays of the same declared size.
// FLAGGED: C++ string copied by its own size into a fixed field
std::memcpy(r.user, user.c_str(), user.size() + 1);
Not flagged: std::vector<char> out(s.size()); std::memcpy(out.data(), s.data(), s.size());, where the destination is sized from the source.
Remediation
- Bound the copy by the destination’s capacity, not the source’s length.
- Check the source length against the destination size first, and fail or truncate explicitly.
- When the destination must hold the whole source, allocate it from the source length.
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-806
// nosec vnx-806
Or record an ignore rule: vulnetix ignore add --rule vnx-806 --reason "...". See Suppressing findings.