The following (simplified code) code gives a (false positive) SQ bug:
C#
byte result = LargeNumber >> 8;
// In case the example makes no sense to you: In the real code, masks are used to select the right bits.
The explanation given bij SQ is wrong:
Since an int is a 32-bit variable, shifting by more than +/-31 is confusing at best and an error at worst. Shifting an int by 32 is the same as shifting it by 0, and shifting it by 33 is the same as shifting it by 1.
If you shift an int 32 times, the result is zero. It is NOT the same as shifting it 0 times (which will leave the value intact). Furthermore, shifting 33 is not the same as shifting it one time. Shifting it by 33 will give the same result as shifting it 32 times; the variable will be 0.
Summary
- Right shifting an int32 8 times and storing it in a byte should not yield a SQ S2183 bug.
- The explanation for the SQ S2183 bug is not correct.
EDIT
Mhhh… If found something unexpected in C#:
UInt16 test = 0xFFFF;
UInt16 test1 = (UInt16)(test >> 1);
UInt16 test2 = (UInt16)(test >> 16);
UInt16 test3 = (UInt16)(test >> 17);
Console.WriteLine($“Test: {test}”);
Console.WriteLine($“Test1: {test1}”);
Console.WriteLine($“Test2: {test2}”);
Console.WriteLine($“Test3: {test3}”);
UInt32 foe = 0xFFFFFFFF;
UInt32 foe1 = foe >> 1;
UInt32 foe2 = foe >> 32;
UInt32 foe3 = foe >> 33;
Console.WriteLine($"Foe: {foe}");
Console.WriteLine($"Foe1: {foe1}");
Console.WriteLine($"Foe2: {foe2}");
Console.WriteLine($"Foe3: {foe3}");
Console output:
Test: 65535
Test1: 32767
Test2: 0
Test3: 0
Foe: 4294967295
Foe1: 2147483647
Foe2: 4294967295
Foe3: 2147483647
So for UInt32, the SQ explanation is correct. For UInt16, it is not…