Bug 312838 (MONO48679) - Unboxed bool is neither true nor false
Summary: Unboxed bool is neither true nor false
Status: RESOLVED FIXED
Alias: MONO48679
Product: Mono: Compilers
Classification: Mono
Component: C# (show other bugs)
Version: unspecified
Hardware: Other All
: P3 - Medium : Major
Target Milestone: ---
Assignee: Mono Bugs
QA Contact: Mono Bugs
URL:
Whiteboard:
Keywords: patch
Depends on:
Blocks:
 
Reported: 2003-09-22 05:01 UTC by Ben Maurer
Modified: 2007-09-15 21:24 UTC (History)
0 users

See Also:
Found By: ---
Services Priority:
Business Priority:
Blocker: ---
Marketing QA Status: ---
IT Deployment: ---


Attachments
potential patch + test case (1.79 KB, patch)
2003-09-23 12:59 UTC, Thomas Wiest
Details | Diff
second patch, should apply cleanly (2.00 KB, patch)
2003-09-24 06:37 UTC, Thomas Wiest
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Thomas Wiest 2007-09-15 18:15:39 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)