Skip to content

VNX-825: Expired Pointer Dereference

Reports C and C++ pointers, references and iterators kept past the lifetime of their target: a local's address stored through an out-parameter, in a global or in a field of a pointer parameter, a pointer to a block-scoped local used after the block, and C++ iterators or references used after the container may have reallocated.

Updated 02 Nov 2026Checked against cli@de9b52a
Field Value
Rule ID VNX-825
Severity Medium
SARIF level warning
Kind sast
Languages C, C++
CWE CWE-825
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 dangling-pointer iterator-invalidation cwe-825 c cpp memory-safety
Source internal/sast/rules/vnx-825.rego

Overview

VNX-825 maps to CWE-825: Expired Pointer Dereference. It reports five shapes in C and C++:

  1. The address of a non-static local (&x, or a local array) stored through a pointer-to-pointer parameter (*out = &value;, *result = buf;). Also a field of a pointer parameter (c->label = buf;) not overwritten later in the function.
  2. The same address stored in a file-scope pointer (active = &cfg;) that the function does not reset before it returns.
  3. A pointer assigned the address of a local declared inside an inner block and used after that block closes.
  4. In C++, an iterator, reference or pointer taken from a std::vector, std::string or std::deque (begin(), front(), data(), c_str(), &v[i]) used after a call that can reallocate the container (push_back, insert, resize, erase, +=, …), and a range-for whose body grows or shrinks the container it iterates.

Not reported: static and heap storage, a global restored later in the function, uses inside the block that owns the local, iterators refreshed after the modification (it = v.erase(it)), node containers such as std::list and std::map, comments and string literals. Returning a local’s address is VNX-562; use after free() is VNX-C-004.

Why This Matters

The pointer outlives the object: the stack frame is reused by the next call, or the vector moved its elements to a new allocation. Every later access reads or writes memory that now belongs to something else.

What Gets Flagged

int value = atoi(s);
*out = &value;               /* FLAGGED: caller gets a dead stack address */
auto it = items.begin();
items.push_back(extra);
*it = 0;                     /* FLAGGED: push_back may have reallocated */

Remediation

  1. Return values by copy, or store heap or caller-owned storage in out-parameters and globals.
  2. Re-acquire iterators, references and c_str()/data() pointers after any call that can reallocate the container.
  3. Do not modify a container inside a range-for over it; collect changes and apply them after the loop.

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

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

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