[Mono-bugs] [Bug 542959] New: Incorrect IL generated when creating a delegate

bugzilla_noreply at novell.com bugzilla_noreply at novell.com
Tue Sep 29 15:34:40 EDT 2009


http://bugzilla.novell.com/show_bug.cgi?id=542959


           Summary: Incorrect IL generated when creating a delegate
    Classification: Mono
           Product: Mono: Compilers
           Version: SVN
          Platform: x86-64
        OS/Version: All
            Status: NEW
          Severity: Normal
          Priority: P5 - None
         Component: C#
        AssignedTo: mono-bugs at lists.ximian.com
        ReportedBy: jpryor at novell.com
         QAContact: mono-bugs at lists.ximian.com
          Found By: ---


User-Agent:       Mozilla/5.0 (X11; U; Linux i686 (x86_64); en-US)
AppleWebKit/532.0 (KHTML, like Gecko) Chrome/4.0.202.2 Safari/532.0

Summary is likely wrong; not sure how best to summarize this.

Consider the following code:

  using System;
  using System.Collections;
  using System.Collections.Generic;

  namespace MyAddressBook {

    public struct ABMultiValueEntry<T>
    {
      ABMultiValue<T> self;
      int index;

      internal ABMultiValueEntry (ABMultiValue<T> self, int index)
      {
        this.self   = self;
        this.index  = index;
      }

      public T Value {
        get {
          var v = IntPtr.Zero;
          Console.Error.WriteLine("# ABMultiValueEntry.Value; v={0}", v);
          return self.toManaged (v);
        }
      }
    }

    public class ABMultiValue<T>
    {
      protected List<KeyValuePair<T, string>> items = new List<KeyValuePair<T,
string>>();
      internal Converter<IntPtr, T> toManaged;

      internal ABMultiValue (Converter<IntPtr, T> toManaged)
      {
        if (toManaged == null)
          throw new ArgumentNullException ("toManaged");

        this.toManaged = toManaged;
      }

      public ABMultiValueEntry<T> this [int index] {
        get {
          if (index < 0 || index >= items.Count)
            throw new IndexOutOfRangeException ();
          return new ABMultiValueEntry<T> (this, index);
        }
      }

      public void Add (T value, string label)
      {
        items.Add(new KeyValuePair<T, string>(value, label));
      }
    }

    public class ABPerson {

      internal static string ToString (IntPtr value)
      {
        Console.Error.WriteLine("# ABPerson.ToString(IntPtr): value={0}",
value);
        if (value == IntPtr.Zero)
          return null;
        return value.ToString ();
      }

      public ABMultiValue<string> GetPhones ()
      {
        var p = new ABMultiValue<string> (ToString);
        p.Add ("value1", "label1");
        return p;
      }
    }

    class Demo {

      static void Main (string [] args)
      {
        var phoneNumbers = new ABPerson().GetPhones();
        var entry = phoneNumbers[0];
        Console.Error.WriteLine("# entry.Value={0}", entry.Value);
      }        
    }
  }

It's simple: ABPerson.GetPhones() returns an ABMultiValueEntry<string>,
providing the ABMultiValueEntry<string> a Converter<IntPtr, string> delegate
which refers to the static ABPerson.ToString(IntPtr) method.

We then call phoneNumbers[0].Value, which invokes the Converter<IntPtr, string>
delegate to obtain an actual value.

The problem: the IntPtr value is CORRUPTED during the invocation!

Program output:

# ABMultiValueEntry.Value; v=0
# ABPerson.ToString(IntPtr): value=140373527179248
# entry.Value=140373527179248

Expected output: value should always be 0, not some random garbage value.

Here's why I think it's an "incorrect" IL issue.  Take the IL of the above app:

  monodis tostring.exe > tostring.il

Then modify ABPerson.GetPhones() so that it uses ldnull instead of ldarg.0,
i.e. change line 206 from:

  IL_0000:  ldarg.0

to:

  IL_0000:  ldnull

Recompile:

  ilasm /exe /out:tostring.new.exe tostring.il

Run:

$ mono tostring.new.exe 
# ABMultiValueEntry.Value; v=0
# ABPerson.ToString(IntPtr): value=0
# entry.Value=

The SAME effect can be had by renaming ABPerson.ToString(IntPtr) to
ABPerson._ToString(IntPtr).  So apparently the problem is using the name
"ToString".

Reproducible: Always

Steps to Reproduce:
1.
2.
3.

-- 
Configure bugmail: http://bugzilla.novell.com/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are the QA contact for the bug.
You are the assignee for the bug.


More information about the mono-bugs mailing list