VNX-194: Unexpected Sign Extension
Reports C/C++ <ctype.h> calls (isspace, isdigit, tolower, ...) given a plain char, *p or p[i] of a char pointer without an (unsigned char) cast, and Java code that combines byte[] elements by shifting or by * 256 without & 0xff.
| Field | Value |
|---|---|
| Rule ID | VNX-194 |
| Severity | Medium |
| SARIF level | warning |
| Kind | sast |
| Languages | C, C++, Java |
| CWE | CWE-194 |
| CAPEC | CAPEC-128 |
| 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 | sign-extension integer ctype cwe-194 |
| Source | internal/sast/rules/vnx-194.rego |
Overview
char is signed on most platforms, and Java’s byte always is. Bytes 0x80-0xFF therefore widen to negative int values. Passed to isspace() or tolower(), a negative value other than EOF is undefined behaviour and indexes the classification table out of bounds. Combined into a wider integer in Java, the sign bit smears across every upper bit, so (b[0] << 8) | b[1] returns a wrong (often negative) length. This maps to CWE-194: Unexpected Sign Extension.
What Gets Flagged
const char *skip_ws(const char *p)
{
while (isspace(*p)) /* flagged */
p++;
return p;
}
public static int readLength(byte[] header) {
return (header[0] << 8) | header[1]; // flagged
}
The declaration nearest the call decides the type, so a char c in another function does not affect an int c here. Not flagged: arguments cast to (unsigned char), variables declared unsigned char or int (a getc() result), masked bytes (b[i] & 0xff, Byte.toUnsignedInt), an unmasked byte shifted by 24 into the top of an int, arrays of other types, and comments.
Remediation
while (isspace((unsigned char)*p))
p++;
int lower = tolower((unsigned char)c);
return ((header[0] & 0xff) << 8) | (header[1] & 0xff);
References
- CWE-194
- SEI CERT STR37-C: Arguments to character-handling functions must be representable as an unsigned char
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-194
// nosec vnx-194
Or record an ignore rule: vulnetix ignore add --rule vnx-194 --reason "...". See Suppressing findings.