VNX-1265: Unintended Reentrant Invocation of Non-reentrant Code Via Nested Calls
strtok() keeps its position in hidden static state, so it is not reentrant: starting a second tokenization while one is in progress silently replaces the first, and the outer loop's next strtok(NULL, ...) continues through the wrong string or stops early. Reported, in C: inside the body of a for/while loop that iterates a strtok() tokenization (the loop begins on, or within three lines after, a strtok() call with a non-NULL string, and its header or body calls strtok(NULL, ...)), a line that starts another strtok() on a non-NULL string, or that calls a function defined in the same file whose body starts a strtok() tokenization (the nested call re-enters strtok). Not reported: strtok_r()/strtok_s(), a second tokenization that begins after the first loop has ended, a helper that does not call strtok(), a function calling itself, calls into other files (not visible to a line-oriented rule), text in comments and string literals. Signal handlers that call non-reentrant functions are reported by VNX-479 and VNX-828.
| Field | Value |
|---|---|
| Rule ID | VNX-1265 |
| Severity | Medium |
| SARIF level | warning |
| Kind | sast |
| Languages | C |
| CWE | CWE-1265 |
| 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 | unintended-reentrant strtok c cwe-1265 |
| Source | internal/sast/rules/vnx-1265.rego |
Overview
VNX-1265 maps to CWE-1265: Unintended Reentrant Invocation of Non-reentrant Code Via Nested Calls.
Why This Matters
strtok() stores its position in hidden static state. When a loop that is tokenizing one string calls strtok() on another string, directly or through a helper, the inner call replaces that state. The outer loop’s next strtok(NULL, ...) then continues through the wrong buffer or stops early, so input is skipped or misparsed.
What Gets Flagged
char *item = strtok(line, ";");
while (item != NULL) {
parse_pair(item, &key, &value); /* parse_pair() calls strtok(pair, "=") */
item = strtok(NULL, ";");
}
for (row = strtok(text, "\n"); row; row = strtok(NULL, "\n")) {
cell = strtok(row, ","); /* nested tokenization */
}
Not flagged: strtok_r(), a second tokenization that starts after the first loop has ended, helpers that do not call strtok().
Remediation
- Use
strtok_r()(POSIX) orstrtok_s()with a separate save pointer for each tokenization. - Signal handlers that call non-reentrant functions are reported separately by VNX-479 and VNX-828.
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-1265
// nosec vnx-1265
Or record an ignore rule: vulnetix ignore add --rule vnx-1265 --reason "...". See Suppressing findings.