Skip to content

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.

Updated 02 Nov 2026Checked against cli@de9b52a
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 sizeof value (values + sizeof(values), hdr + sizeof(struct header)), which pointer arithmetic multiplies by the element size a second time;
  • a for loop whose condition is i <= sizeof(arr), i <= ARRAY_SIZE(arr), _countof, std::size, or i <= 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

  1. Index the last element with sizeof(buf) - 1 or the element count minus one, never with the size or the count itself.
  2. Offset typed pointers by element counts (words + n), or cast to a byte pointer first ((uint8_t *)hdr + sizeof(*hdr)).
  3. Use < for loops bounded by an array’s size.

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-823
// nosec vnx-823

Or record an ignore rule: vulnetix ignore add --rule vnx-823 --reason "...". See Suppressing findings.

Edit this pageSources: cli/internal/sast/rules/vnx-823.rego, cli/internal/sast/docs/vnx-823.md
esc
↑ ↓ move↵ openSearches in your browser. A key like autonomy.max or a code like threshold_required jumps straight to it.