CWE-1335 is the bug of shifting an integer by a negative amount, or by an amount greater than or equal to the number of bits in the value. It appears in C, C++, C#, Java and JavaScript.
How it happens
A negative shift count is undefined in several languages, and architectures handle it differently. An over-shift, where the count is at least the bit width, gives a result that varies by architecture and compiler. Compilers and interpreters generally do not insert a check, so the problem passes silently until someone supplies a bad count.
/* Vulnerable: shift count comes from untrusted input */
uint32_t mask_for(int bits) {
return (1u << bits) - 1; /* undefined if bits < 0 or bits >= 32 */
}
/* Safer: validate the count first */
uint32_t mask_for(int bits) {
if (bits < 0 || bits >= 32) {
return 0; /* or report an error */
}
return (1u << bits) - 1;
}
The record gives several real cases:
- CVE-2023-4720: a multimedia product performs a left shift with a negative value, leading to a crash.
- CVE-2009-4307 and CVE-2012-2100: an unexpected large value in the ext4 filesystem causes an overshift that leads to a divide by zero. The second is a fix of the first.
- CVE-2020-8835: an overshift in a kernel allowed out of bounds reads and writes, resulting in a root takeover.
What an attacker gains
The record lists integrity impact and denial of service through crash, exit or restart. The kernel case above shows the worst outcome reaches much further than a crash.
How to find it
Static analysis (SAST) can find some instances by modeling data flow, for example a shift count that originates from input without a range check. Compiler warnings and runtime sanitizers that report undefined behavior are also useful in test builds.
How to fix it
Add explicit or implicit checks for negative and over-shift values before the shift happens. Treat any count that comes from a file header, network field or user input as untrusted.
Quick check
What shift counts are unsafe for a 32-bit value?
Negative counts, and counts of 32 or more.