Skip to content

Commit 3636ebe

Browse files
committed
a fix that allows for only one particular edge case scenario
1 parent 6d325c4 commit 3636ebe

File tree

2 files changed

+24
-4
lines changed

2 files changed

+24
-4
lines changed

src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/MemberTypeInfo.cs

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -91,9 +91,7 @@ internal static MemberTypeInfo Decode(BinaryReader reader, int count, PayloadOpt
9191
const AllowedRecordTypes SystemClass = Classes | AllowedRecordTypes.SystemClassWithMembersAndTypes
9292
// All primitive types can be stored by using one of the interfaces they implement.
9393
// Example: `new IEnumerable[1] { "hello" }` or `new IComparable[1] { int.MaxValue }`.
94-
| AllowedRecordTypes.BinaryObjectString | AllowedRecordTypes.MemberPrimitiveTyped
95-
// System.Nullable<UserStruct> is a special case of SystemClassWithMembersAndTypes
96-
| AllowedRecordTypes.ClassWithMembersAndTypes;
94+
| AllowedRecordTypes.BinaryObjectString | AllowedRecordTypes.MemberPrimitiveTyped;
9795
const AllowedRecordTypes NonSystemClass = Classes | AllowedRecordTypes.ClassWithMembersAndTypes;
9896

9997
return binaryType switch
@@ -104,10 +102,29 @@ internal static MemberTypeInfo Decode(BinaryReader reader, int count, PayloadOpt
104102
BinaryType.StringArray => (StringArray, default),
105103
BinaryType.PrimitiveArray => (PrimitiveArray, default),
106104
BinaryType.Class => (NonSystemClass, default),
105+
BinaryType.SystemClass when IsNullableUserTypeRepresentedAsSystemType((TypeName)additionalInfo!) => (SystemClass | AllowedRecordTypes.ClassWithMembersAndTypes, default),
107106
BinaryType.SystemClass => (SystemClass, default),
108107
BinaryType.ObjectArray => (ObjectArray, default),
109108
_ => throw new InvalidOperationException()
110109
};
110+
111+
static bool IsNullableUserTypeRepresentedAsSystemType(TypeName typeName)
112+
{
113+
if (!typeName.IsConstructedGenericType || typeName.Name != typeof(Nullable<>).Name)
114+
{
115+
return false;
116+
}
117+
118+
var genericArgs = typeName.GetGenericArguments();
119+
if (genericArgs.Length != 1)
120+
{
121+
return false;
122+
}
123+
124+
// If the generic argument is not from CoreLib, then it is a user type.
125+
var assemblyName = genericArgs[0].AssemblyName;
126+
return assemblyName is not null && !assemblyName.FullName.Equals(TypeNameHelpers.CoreLibAssemblyName.FullName, StringComparison.Ordinal);
127+
}
111128
}
112129

113130
internal TypeName GetArrayTypeName(ArrayInfo arrayInfo)

src/libraries/System.Formats.Nrbf/src/System/Formats/Nrbf/Utils/TypeNameHelpers.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,9 @@ internal static class TypeNameHelpers
2121
private static readonly TypeName?[] s_primitiveSZArrayTypeNames = new TypeName?[(int)UIntPtrPrimitiveType + 1];
2222
private static AssemblyNameInfo? s_coreLibAssemblyName;
2323

24+
internal static AssemblyNameInfo CoreLibAssemblyName
25+
=> s_coreLibAssemblyName ??= AssemblyNameInfo.Parse("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089".AsSpan());
26+
2427
internal static TypeName GetPrimitiveTypeName(PrimitiveType primitiveType)
2528
{
2629
TypeName? typeName = s_primitiveTypeNames[(int)primitiveType];
@@ -155,7 +158,7 @@ internal static TypeName ParseSystemRecordTypeName(this string rawName, PayloadO
155158
.WithCoreLibAssemblyName(); // We know it's a System Record, so we set the LibraryName to CoreLib
156159

157160
internal static TypeName WithCoreLibAssemblyName(this TypeName systemType)
158-
=> systemType.With(s_coreLibAssemblyName ??= AssemblyNameInfo.Parse("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089".AsSpan()));
161+
=> systemType.With(CoreLibAssemblyName);
159162

160163
private static TypeName With(this TypeName typeName, AssemblyNameInfo assemblyName)
161164
{

0 commit comments

Comments
 (0)