VNX-823: Use of Out-of-range Pointer Offset
Reports C and C++ pointer offsets and indexes that are out of range by construction: an array indexed at its own size or element count, a non-byte pointer offset by a sizeof value (scaled twice), and a <= loop bound at an array's size that indexes the same array.
| Field | Value |
|---|---|
| Rule ID | VNX-823 |
| Severity | Medium |
| SARIF level | warning |
| Kind | sast |
| Languages | C, C++ |
| CWE | CWE-823 |
| 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 | oor-pointer-offset cwe-823 c cpp memory-safety |
| Source | internal/sast/rules/vnx-823.rego |
Overview
VNX-823 maps to CWE-823: Use of Out-of-range Pointer Offset. It reports three shapes in C and C++ where the offset is wrong by construction, so no runtime value can make it right:
- an array indexed at its own size or element count (
buf[sizeof(buf)],names[ARRAY_SIZE(names)],slots[sizeof(slots) / sizeof(slots[0])]), one element past the end; - a pointer or array of a non-byte type offset by a
sizeofvalue (values + sizeof(values),hdr + sizeof(struct header)), which pointer arithmetic multiplies by the element size a second time; - a
forloop whose condition isi <= sizeof(arr),i <= ARRAY_SIZE(arr),_countof,std::size, ori <= v.size()and whose body indexes that same array with the loop variable.
Not reported: the one-past-the-end address &buf[sizeof(buf)], byte pointers (char, uint8_t, void) plus sizeof, a pointer cast to a byte pointer before the addition, pointer offsets by element counts (a + sizeof(a) / sizeof(a[0])), sizeof(x) - 1 bounds, a <= loop that indexes a different array, offsets computed from runtime lengths, comments and string literals.
Why This Matters
An offset past the end of an object reads or writes memory that belongs to something else: a neighbouring variable, a saved return address or heap metadata. These are the off-by-one and double-scaling errors that turn into memory disclosure or memory corruption.
What Gets Flagged
char name[32];
name[sizeof(name)] = '\0'; /* FLAGGED: one past the end */
uint32_t *words = table;
uint32_t *end = words + sizeof(table); /* FLAGGED: scaled twice */
for (i = 0; i <= ARRAY_SIZE(slots); i++)
slots[i] = 0; /* FLAGGED: last iteration is out of range */
Remediation
- Index the last element with
sizeof(buf) - 1or the element count minus one, never with the size or the count itself. - Offset typed pointers by element counts (
words + n), or cast to a byte pointer first ((uint8_t *)hdr + sizeof(*hdr)). - Use
<for loops bounded by an array’s size.
References
- CWE-823: Use of Out-of-range Pointer Offset
- SEI CERT ARR39-C: Do not add or subtract a scaled integer to a pointer
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-823
// nosec vnx-823
Or record an ignore rule: vulnetix ignore add --rule vnx-823 --reason "...". See Suppressing findings.