This bug is not a common case and you might not have a chance to engage into
it. But when you're going to make an plus or minus operation with signed
integer, and the result is overflowed, there is a chance to crash into this
bug.
Please try this in C#:
Int32 i = Int32.MaxValue;
i += 10;
if (i < 0)
{
i = -i;
}
Console.WriteLine(i.ToString());
We expect the output to be a positive number. However, we got a negative
ones. In fact, the statement "if (i < 0)" failed and the statement "i = -i;"
wasn't executed at all! So the i remain negative still.
But when you use "Console.WriteLIne(i)" instead of "i.ToString()", the
program will just work correctly. So what happen?
I found that in the original code, the JIT will translate il "bge.s" to
native code "jge". When you use "Console.Writeline(i)" instead of
"i.ToString()", the same il will be translated into "jns". Please see the two
snapshot if you got confused:
http://www.cnblogs.com/images/cnblogs_com/sumtec/TestJit_01.JPG
http://www.cnblogs.com/images/cnblogs_com/sumtec/TestJit_02.JPG
When overflowed, the instruction "jge" and "jns" will not perform the same
logic.
When you're adding two integer and get overflowed, and *immediately*
followed by a "< 0" comparison (attn, not comparing to an non-const
variable), you'll get a chance to see the bug. However, you will not get
burned, unless you use the reference of variable "i" in the same function,
eg: "i.ToString()" or "AnotherFunction(ref i)".
One of my friend said that, not only when you use the reference of variable
"i" will cause the failure, but also some other cases. I guess when this
function uses ils like "ldloca.s" will cause the problem.
There is another similar case:
int i = int.Minimum;
i -= 10;
if (i > 0) ...
There's no public KB in MS now. (At least, I can not find it) And here is my
suggestion to work around the bug:
1. Becareful about the side effects of unchecked mathematics operations in
C#. Especially, when a comparison between the result and a const zero is
needed. If you're sure the operation should not result in overflowed, please
write codes like this:
checked
{
i += 10;
}
if (i<0) ...
2. Or, if you need this side effects, for example, you're writing a hashing
algorithm, please use the following style instead:
i += 10;
int b = i;
if (b < 0) ...
Any questions, please send email to sumtec@gmail.com. (I usually don't use
news group)
And if you're fortunately enough -- you can read Chinese, here is the
original text, and replying anything here is welcome:
http://www.cnblogs.com/sumtec/archive/2005/03/06/113748.aspx