Bugzilla – Bug 312838
Unboxed bool is neither true nor false
Last modified: 2007-09-15 21:24:23 UTC
---- Reported by bmaurer@users.sf.net 2003-09-21 22:01:20 MST ---- Description of Problem: Somehow, it is possible to get a value that equals neither true nor false. Steps to reproduce the problem:using System; using System.Xml; using System.Xml.XPath; public class T { static void Main () { XPathNavigator navigator = new XmlDocument ().CreateNavigator (); object val = navigator.Evaluate ("0>=0"); bool b = (bool) val; Console.WriteLine (true == b); Console.WriteLine (false == b); Console.WriteLine (b); } } Actual Results: [benm@Ben test]$ mono t.exe False False True Expected Results: [benm@Ben test]$ mint t.exe True False True How often does this happen? Always ---- Additional Comments From mass@akuma.org 2003-09-22 21:05:35 MST ---- Appending this block of code after the last WriteLine: int c; unsafe { bool *b2 = &b; int *c2 = (int*) b2; c = *c2; } Console.WriteLine (c); 'c' prints as '1' in mini and the microsoft vm, and '222114047' on my instance of mono. ---- Additional Comments From mass@akuma.org 2003-09-22 21:19:41 MST ---- New, simpler reproduction recipe: using System; using System.Xml; using System.Xml.XPath; public class T { static void Main () { object val = compare(0, 0); bool b = (bool) val; Console.WriteLine (true == b); Console.WriteLine (false == b); } static object compare(int a, int b) { return a >= b; } } ---- Additional Comments From mass@akuma.org 2003-09-22 22:46:15 MST ---- assembly generated for T::compare: 0: 55 push %ebp 1: 8b ec mov %esp,%ebp 3: 83 ec 04 sub $0x4,%esp 6: 68 1c 8e 12 08 push $0x8128e1c b: e8 57 9e f9 37 call 37f99e67 <_T_compare+0x37f99e67> 10: 83 c4 04 add $0x4,%esp 13: 89 45 fc mov %eax,0xfffffffc(%ebp) 16: 8b 4d 0c mov 0xc(%ebp),%ecx 19: 39 4d 08 cmp %ecx,0x8(%ebp) 1c: 0f 9c c1 setl %cl 1f: 0f b6 c9 movzbl %cl,%ecx 22: 83 e9 01 sub $0x1,%ecx 25: 88 48 08 mov %cl,0x8(%eax) 28: 8b 45 fc mov 0xfffffffc(%ebp),%eax 2b: c9 leave 2c: c3 ret two problems: 22: 83 e9 01 sub $0x1,%ecx this does %ecx = %ecx - 1, not %ecx = 1 - %ecx . This is why the number returned with my unsafe cast above ends with 0xff 25: 88 48 08 mov %cl,0x8(%eax) this is the byte copy, not word copy. making the unsafe assumption that the value that eax + 0x8 points to is not preset to zero, this leaves garbage in the high bytes. ---- Additional Comments From lupus@ximian.com 2003-09-23 04:34:37 MST ---- mcs here generates incorrect code for the comparison: IL_0000: ldarg.0 IL_0001: ldarg.1 IL_0002: clt IL_0004: ldc.i4.1 IL_0005: sub IL_0006: box [mscorlib]System.Boolean IL_000b: ret clt returns either 1 or 0: mcs subtracts 1 from the result, but 0 -1 => -1 is not a valid boolean value. csc generates the correct code (comparison to 0 after the clt): IL_0000: ldarg.0 IL_0001: ldarg.1 IL_0002: clt IL_0004: ldc.i4.0 IL_0005: ceq IL_0007: box [mscorlib]System.Boolean The final one byte copy is correct, since a bool is 1-byte sized. ---- Additional Comments From mass@akuma.org 2003-09-23 05:59:07 MST ---- Created an attachment (id=164958) potential patch + test case ---- Additional Comments From bmaurer@users.sf.net 2003-09-23 09:10:37 MST ---- Can you please use -u on that patch? If you dont do that by tonight i will take care of it. ---- Additional Comments From mass@akuma.org 2003-09-23 23:37:42 MST ---- Created an attachment (id=164959) second patch, should apply cleanly ---- Additional Comments From mass@akuma.org 2003-10-01 02:05:07 MST ---- to clarify, this patch removes the subtraction operation and replaces it with a zero-push and compare-equal (to get a logical not). The generated IL now matches the <= case and the IL of a test program compiled with csc ---- Additional Comments From miguel@ximian.com 2003-10-07 20:02:19 MST ---- David, thanks a lot for the patch; Sorry it took so long to get into CVS specially with a bug fix in place. Imported an attachment (id=164958) Imported an attachment (id=164959)