Skip to content

System.Reflection.Emit.ParameterBuilder.SetCustomAttribute() throws undocumented ArgumentOutOfRangeException #12747

@mcpiroman

Description

@mcpiroman

Steps to Reproduce

Compile and run following program:

using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Reflection;
using System.Reflection.Emit;

class Program
{
    [DllImport("SomeLib")]
    private static extern void SomeMethod([MarshalAs(UnmanagedType.LPWStr)] string param);

    static void Main(string[] args)
    {
        var aName = new AssemblyName("TestAssembly");
        var assembly = AppDomain.CurrentDomain.DefineDynamicAssembly(aName, AssemblyBuilderAccess.RunAndSave);
        var module = assembly.DefineDynamicModule(aName.Name, aName.Name + ".dll");

        var someMethod = typeof(Program).GetMethod(nameof(SomeMethod), BindingFlags.Static | BindingFlags.NonPublic);

        var typeBuilder = module.DefineType("NewType" + module.ToString(), TypeAttributes.Class | TypeAttributes.Public);
        var methodBuilder = typeBuilder.DefineMethod("NewMethod", MethodAttributes.Public | MethodAttributes.HideBySig, typeof(void), new[] { typeof(string) });
        var il = methodBuilder.GetILGenerator();
        il.Emit(OpCodes.Ret);

        var param = someMethod.GetParameters()[0];
        var paramBuilder = methodBuilder.DefineParameter(1, param.Attributes, null);
        var attr = param.GetCustomAttribute<MarshalAsAttribute>();
        var attrCtor = typeof(MarshalAsAttribute).GetConstructor(new[] { typeof(UnmanagedType) });
        object[] attrCtorArgs = { attr.Value };
        var fieldArguments = new List<FieldInfo>();
        var fieldArgumentValues = new List<object>();
        foreach (var field in typeof(MarshalAsAttribute).GetFields(BindingFlags.Public | BindingFlags.Instance))
        {
            fieldArguments.Add(field);
            fieldArgumentValues.Add(field.GetValue(attr));
        }

        var attrBuilder = new CustomAttributeBuilder(attrCtor, attrCtorArgs, Array.Empty<PropertyInfo>(), Array.Empty<object>(),
            fieldArguments.ToArray(), fieldArgumentValues.ToArray());
        paramBuilder.SetCustomAttribute(attrBuilder);

        var finalType = typeBuilder.CreateType();
        Console.WriteLine("DONE");
        Console.ReadKey(false);
    }
}

Current Behavior

System.ArgumentOutOfRangeException is thrown at line paramBuilder.SetCustomAttribute(attrBuilder);

Expected Behavior

Of course no exceptions (or at least documented ones).
Running the same program (even the same exe file) with .net framework executes everything without exception.

On which platforms did you notice this

[ ] macOS
[ ] Linux
[x] Windows

Version Used:

Mono JIT compiler version 5.18.0 (Visual Studio built mono)
Copyright (C) 2002-2014 Novell, Inc, Xamarin Inc and Contributors. www.mono-project.com
        TLS:           __thread
        SIGSEGV:       normal
        Notification:  Thread + polling
        Architecture:  amd64
        Disabled:      none
        Misc:          softdebug
        Interpreter:   yes
        LLVM:          supported, not enabled.
        Suspend:       preemptive
        GC:            sgen (concurrent by default)

Stacktrace

Unhandled Exception:
System.ArgumentOutOfRangeException: Index and count must refer to a location within the buffer.
Parameter name: bytes
  at System.Text.UTF8Encoding.GetString (System.Byte[] bytes, System.Int32 index, System.Int32 count) [0x0003e] in <08dddd7e1b69412492b591625ff22e77>:0
  at System.Reflection.Emit.CustomAttributeBuilder.string_from_bytes (System.Byte[] data, System.Int32 pos, System.Int32 len) [0x00005] in <08dddd7e1b69412492b591625ff22e77>:0
  at System.Reflection.Emit.CustomAttributeBuilder.get_umarshal (System.Reflection.Emit.CustomAttributeBuilder customBuilder, System.Boolean is_field) [0x0036c] in <08dddd7e1b69412492b591625ff22e77>:0
  at System.Reflection.Emit.ParameterBuilder.SetCustomAttribute (System.Reflection.Emit.CustomAttributeBuilder customBuilder) [0x00085] in <08dddd7e1b69412492b591625ff22e77>:0
  at Program.Main (System.String[] args) [0x00188] in <43c4d55f3f5246aea25d946fc95e4cc1>:0
[ERROR] FATAL UNHANDLED EXCEPTION: System.ArgumentOutOfRangeException: Index and count must refer to a location within the buffer.
Parameter name: bytes
  at System.Text.UTF8Encoding.GetString (System.Byte[] bytes, System.Int32 index, System.Int32 count) [0x0003e] in <08dddd7e1b69412492b591625ff22e77>:0
  at System.Reflection.Emit.CustomAttributeBuilder.string_from_bytes (System.Byte[] data, System.Int32 pos, System.Int32 len) [0x00005] in <08dddd7e1b69412492b591625ff22e77>:0
  at System.Reflection.Emit.CustomAttributeBuilder.get_umarshal (System.Reflection.Emit.CustomAttributeBuilder customBuilder, System.Boolean is_field) [0x0036c] in <08dddd7e1b69412492b591625ff22e77>:0
  at System.Reflection.Emit.ParameterBuilder.SetCustomAttribute (System.Reflection.Emit.CustomAttributeBuilder customBuilder) [0x00085] in <08dddd7e1b69412492b591625ff22e77>:0
  at Program.Main (System.String[] args) [0x00188] in <43c4d55f3f5246aea25d946fc95e4cc1>:0

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions