V5006. OWASP. More than N bits are required to store the value, but the expression evaluates to the T type which can only hold K bits.
The analyzer has detected a potential error in an expression that uses shift operations. They cause an overflow and loss of the most significant bit values.
Let's start with a simple example:
std::cout << (77u << 26);
The value of the 77u << 26
expression equals 5167382528 (0x134000000), and this expression is of the unsigned int
type. This means that the most significant bits will be truncated, and the 872415232 (0x34000000)
value will be printed.
Overflows caused by shift operations usually indicate a logic error or a typo in the code. For example, a programmer intended to define 77u
as an octal number, , then the correct code should look like this:
std::cout << (077u << 26);
No overflow occurs now; the value of the 077u << 26
expression is 4227858432 (0xFC000000)
.
If you need the the 5167382528 number to be printed , define 77 the 64-bit type. For example:
std::cout << (77ui64 << 26);
Now, to the cases one may encounter in real life. The two samples below are taken from real applications.
Example 1.
typedef __UINT64 Ipp64u;
#define MAX_SAD 0x07FFFFFF
....
Ipp64u uSmallestSAD;
uSmallestSAD = ((Ipp64u)(MAX_SAD<<8));
A programmer wants the 0x7FFFFFF00
value to be written into the uSmallestSAD
64-bit variable. However, the variable stores the 0xFFFFFF00
value instead, and the most significant bits will be truncated because the MAX_SAD<<8
expression is of the int
type. The programmer knew that and decided to use explicit type casting but made a mistake when placing parentheses. Theexample shows that even ordinary mistakes can easily cause such bugs. Here is the fixed code:
uSmallestSAD = ((Ipp64u)(MAX_SAD))<<8;
Example 2.
#define MAKE_HRESULT(sev,fac,code) \
((HRESULT) \
(((unsigned long)(sev)<<31) | \
((unsigned long)(fac)<<16) | \
((unsigned long)(code))) )
*hrCode = MAKE_HRESULT(3, FACILITY_ITF, messageID);
The function must generate an error message in a variable of the HRESULT
type. To do this, the developer used the MAKE_HRESULT
macro—but incorrectly, assuming that the first parameter, severity
, could range from 0 to 3. Most likely they confused it with the format used to generate error codes when working with the GetLastError()
/ SetLastError()
functions.
The MAKE_HRESULT
macro can take either 0 (success) or 1 (failure) as the first argument. For more details on this topic, see thread on the forum of the CodeGuru website: Warning! MAKE_HRESULT macro doesn't work.
Since 3 is passed as the first actual argument, an overflow occurs, and 3 "turns into" 1. Because of this unexpected event, the error does not affect the program execution. However, this example shows that code often works by sheer luck, and not because it was written correctly.
The fixed code:
*hrCode = MAKE_HRESULT(SEVERITY_ERROR, FACILITY_ITF, messageID);
This diagnostic is classified as:
|