Skip to content

Commit f8b5e9c

Browse files
Add (commented) test case that crashes LibraryImportGenerator (#117447)
* Add test case that crashes LibraryImportGenerator When a collection marshaller does not conform to the correct shape and an element marshaller is specified, we crash the generator with a NullRef. Co-authored-by: Aaron Robinson <arobins@microsoft.com>
1 parent 780d05e commit f8b5e9c

File tree

2 files changed

+91
-0
lines changed

2 files changed

+91
-0
lines changed

src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/CodeSnippets.cs

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1438,5 +1438,93 @@ public Native(S s)
14381438

14391439
public static string TypeUsage(string attr) => MarshalUsingParametersAndModifiers("S", "Marshaller", attr);
14401440
}
1441+
1442+
public const string ImproperCollectionWithMarshalUsingOnElements = """
1443+
using System;
1444+
using System.Collections.Generic;
1445+
using System.Runtime.InteropServices;
1446+
using System.Runtime.InteropServices.Marshalling;
1447+
1448+
class MyList<T>
1449+
{
1450+
}
1451+
1452+
class NotMyList {}
1453+
1454+
class Example
1455+
{
1456+
public int Value;
1457+
}
1458+
1459+
internal static partial class PInvoke
1460+
{
1461+
[LibraryImport("NativeLibrary", EntryPoint = "ProcessExample")]
1462+
public static partial int ProcessExample([MarshalUsing(typeof(ListMarshaller<,>), CountElementName = nameof(exampleCount)), MarshalUsing(typeof(ExampleMarshaller), ElementIndirectionDepth = 1)] MyList<Example> examples, ref int exampleCount);
1463+
}
1464+
1465+
[ContiguousCollectionMarshaller]
1466+
[CustomMarshaller(typeof(MyList<>), MarshalMode.Default, typeof(ListMarshaller<,>.Marshaller))]
1467+
public unsafe static class ListMarshaller<T, TUnmanagedElement> where TUnmanagedElement : unmanaged
1468+
{
1469+
public static class Marshaller
1470+
{
1471+
public static byte* AllocateContainerForUnmanagedElements(NotMyList managed, out int numElements)
1472+
{
1473+
numElements = default;
1474+
return default;
1475+
}
1476+
1477+
public static ReadOnlySpan<T> GetManagedValuesSource(NotMyList managed)
1478+
=> default;
1479+
1480+
public static Span<TUnmanagedElement> GetUnmanagedValuesDestination(byte* unmanaged, int numElements)
1481+
=> new Span<TUnmanagedElement>((TUnmanagedElement*)unmanaged, numElements);
1482+
1483+
public static List<T> AllocateContainerForManagedElements(byte* unmanaged, int length)
1484+
=> new List<T>(length);
1485+
1486+
public static Span<T> GetManagedValuesDestination(NotMyList managed)
1487+
=> default;
1488+
1489+
public static ReadOnlySpan<TUnmanagedElement> GetUnmanagedValuesSource(byte* nativeValue, int numElements)
1490+
=> new ReadOnlySpan<TUnmanagedElement>((TUnmanagedElement*)nativeValue, numElements);
1491+
1492+
public static void Free(byte* unmanaged)
1493+
=> NativeMemory.Free(unmanaged);
1494+
}
1495+
}
1496+
1497+
[CustomMarshaller(typeof(Example), MarshalMode.ManagedToUnmanagedIn, typeof(ManagedToNative))]
1498+
[CustomMarshaller(typeof(Example), MarshalMode.ManagedToUnmanagedOut, typeof(ManagedToNativeOutFinally))]
1499+
static class ExampleMarshaller
1500+
{
1501+
public static class ManagedToNativeOutFinally
1502+
{
1503+
public static Example ConvertToManagedFinally(int managed)
1504+
{
1505+
return default;
1506+
}
1507+
1508+
public static void Free(int unmanaged)
1509+
{
1510+
}
1511+
}
1512+
1513+
public struct ManagedToNative
1514+
{
1515+
Example managed;
1516+
1517+
public static int BufferSize => sizeof(int);
1518+
1519+
public void FromManaged(Example managed, Span<int> buffer) => this.managed = managed;
1520+
1521+
public int ToUnmanaged() => managed.Value;
1522+
1523+
public void OnInvoked() { }
1524+
1525+
public void Free() { }
1526+
}
1527+
}
1528+
""";
14411529
}
14421530
}

src/libraries/System.Runtime.InteropServices/tests/LibraryImportGenerator.UnitTests/CompileFails.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,9 @@ public static IEnumerable<object[]> CodeSnippetsToCompile()
5757
// Not LibraryImportAttribute
5858
yield return new object[] { ID(), CodeSnippets.UserDefinedPrefixedAttributes, Array.Empty<DiagnosticResult>() };
5959

60+
// Bug: https://github.com/dotnet/runtime/issues/117448
61+
// yield return new[] { ID(), CodeSnippets.ImproperCollectionWithMarshalUsingOnElements };
62+
6063
// No explicit marshalling for char or string
6164
yield return new object[] { ID(), CodeSnippets.BasicParametersAndModifiers<char>(), new[]
6265
{

0 commit comments

Comments
 (0)