CWE-194, Unexpected Sign Extension, occurs when an operation causes a number to be sign extended as it is converted to a larger data type. If the original number is negative, the result can be an unexpected value that leads to further weaknesses. MITRE lists C and C++ as the affected languages.
How it happens
Sign extension copies the sign bit into the new high bits to keep a negative number negative. That is correct for a signed number, and surprising when the code thought it was handling raw bytes or an unsigned quantity.
// Vulnerable: plain char may be signed
char c = (char)0xFF; // value is -1 on platforms where char is signed
unsigned long n = c; // sign extended to 0xFFFFFFFFFFFFFFFF
// Fixed: use an unsigned type for byte data
unsigned char c = 0xFF;
unsigned long n = c; // 255
The record offers four cases. In CVE-2018-10887, unexpected sign extension led to an integer overflow and an out of bounds read. CVE-1999-0234 produced a value of negative one that was treated as a command separator, enabling OS command injection. CVE-2003-0161 used the char type for an input character, and when char is signed, the ASCII value 0xFF extended to negative one, which the program treated as a separator. CVE-2007-4988 involved a signed short width value in an image processor that was sign extended during conversion to an unsigned int, leading to integer overflow and a heap based buffer overflow.
What an attacker gains
When the value is a size or memory index, MITRE says the program may read or write outside the intended buffer. Listed impacts are integrity, confidentiality and availability, through reading and modifying memory.
How to find it
MITRE says automated static analysis (SAST) can find some instances by modelling data flow. Enable compiler warnings for sign conversion, and review any place a plain char, short or int feeds a wider type, especially for lengths and indexes.
How to fix it
The record lists no mitigations, so these are general steps.
- Use unsigned types for bytes, sizes and indexes.
- Cast to the unsigned type of the same width before widening.
- Validate that lengths from untrusted data are in range before use.
Quick check
Why does 0xFF become negative one?
On platforms where plain char is signed, 0xFF in a char is the value negative one, and widening keeps it negative.