VNX-908: Use of Uninitialized Resource
A C or C++ local scalar, pointer or struct is read before it is assigned (or assigned only under an if with no else), or a stack char array or malloc/new[] buffer is used as a string before anything writes it.
| Field | Value |
|---|---|
| Rule ID | VNX-908 |
| Severity | Low |
| SARIF level | note |
| Kind | sast |
| Languages | C, C++ |
| CWE | CWE-908 |
| CAPEC | CAPEC-66 |
| ATT&CK | T1190 |
| CWSS vector | CWSS:1.0/TI:L/AP:RU/AL:S/IC:N/FC:LT/RP:RU/RL:S/AV:L/AS:N/IN:A/SC:A/BI:L/DI:H/EX:L/EC:N/P:L |
| Tags | use-uninitialized-resource cwe-908 uninitialized-variable |
| Source | internal/sast/rules/vnx-908.rego |
Overview
VNX-908 maps to CWE-908: Use of Uninitialized Resource. It reports three shapes in C and C++ function bodies:
- Read before assignment. A local scalar, pointer or C struct declared without an initializer (
int total;,const char *name;,struct node *n;, and each name inint rc, n;orchar *a, *b;; one finding per declaration line) whose first use within 30 lines reads it:total += v[i],n->value = v,printf("%s", name). - Assigned on one path only. Such a local assigned only inside an
ifwith noelse(or on a single-lineif) and then read at the declaration’s own level. - String operations on an unwritten buffer. A stack
chararray without an initializer, or memory frommalloc/realloc/new char[], whose first use after any NULL check reads it as a string:strcat/strncatinto it,strlen,strcmp,puts,printf%s, or copying from it.
Not reported: a first use that assigns the variable (including for (i = 0, j = 0; ...), (ch = getchar()), chained a = b = v and ip = strchr(s, c); if (!ip) ... on one line), a statement-level ALL-CAPS macro call between the declaration and the read, takes its address (&x out-parameters, stat(path, &st)), reads into it with >>, uses it only in sizeof, or passes it to a C++ function (which may take it by reference) or a macro (ALL-CAPS, or defined with #define in the project); branches with else/default/switch, early returns or gotos between the assignment and the read; calloc, = {0}, memset, snprintf, fgets or strcpy into a buffer; statics, globals and struct/class fields; comments and strings. Flow through loops, other functions and pointers is not followed.
Why This Matters
An uninitialized local holds whatever the stack or a register last held. Reading it gives undefined behaviour: a wrong sum, a pointer write to an arbitrary address, or a strcat that walks past the buffer looking for a terminator that was never written. Stale stack contents can also leak earlier data (keys, pointers that defeat ASLR) into output.
What Gets Flagged
int sum(const int *v, int len)
{
int total;
for (int i = 0; i < len; i++)
total += v[i]; // FLAGGED
}
int open_log(const char *path)
{
int fd;
if (path != NULL) {
fd = open(path, O_WRONLY | O_APPEND);
}
return fd; // FLAGGED
}
char *out = malloc(strlen(a) + strlen(b) + 1);
if (out == NULL)
return NULL;
strcat(out, a); // FLAGGED
Not flagged: if (stat(p, &st) == 0) return st.st_size;, int r; if (a > b) { r = a; } else { r = b; } return r;, char buf[64]; snprintf(buf, sizeof buf, ...), char *q = calloc(1, 64); strcat(q, who);.
Remediation
- Initialize locals at their declaration (
int total = 0;,char *name = NULL;,struct stat st = {0};). - Assign a value on every path, including the
elseyou did not write. - Terminate a fresh buffer before string operations (
buf[0] = '\0'), or allocate it withcalloc. - Compile with
-Wall -Wuninitialized -Wmaybe-uninitializedand run tests under MemorySanitizer or Valgrind.
References
- CWE-908: Use of Uninitialized Resource
- CWE-457: Use of Uninitialized Variable
- SEI CERT EXP33-C: Do not read uninitialized memory
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-908
// nosec vnx-908
Or record an ignore rule: vulnetix ignore add --rule vnx-908 --reason "...". See Suppressing findings.