Skip to content

Commit 072ebe7

Browse files
authored
Fix a bug with null value passed to annotated parameter on attribute (#2894)
This also makes small tweaks to help with linker->AOT sync.
1 parent e2b3a92 commit 072ebe7

6 files changed

Lines changed: 83 additions & 11 deletions

File tree

src/linker/Linker.Dataflow/AttributeDataFlow.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,14 +50,17 @@ public void ProcessAttributeDataflow (FieldDefinition field, CustomAttributeArgu
5050
MultiValue GetValueForCustomAttributeArgument (CustomAttributeArgument argument)
5151
{
5252
if (argument.Type.Name == "Type") {
53+
if (argument.Value is null)
54+
return NullValue.Instance;
55+
5356
TypeDefinition? referencedType = ((TypeReference) argument.Value).ResolveToTypeDefinition (_context);
5457
return referencedType == null
5558
? UnknownValue.Instance
5659
: new SystemTypeValue (referencedType);
5760
}
5861

5962
if (argument.Type.MetadataType == MetadataType.String)
60-
return new KnownStringValue ((string) argument.Value);
63+
return argument.Value is null ? NullValue.Instance : new KnownStringValue ((string) argument.Value);
6164

6265
// We shouldn't have gotten a non-null annotation for this from GetParameterAnnotation
6366
throw new InvalidOperationException ();

src/linker/Linker.Dataflow/CompilerGeneratedCallGraph.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,15 @@ namespace Mono.Linker.Dataflow
99
{
1010
sealed class CompilerGeneratedCallGraph
1111
{
12-
readonly Dictionary<IMemberDefinition, HashSet<IMemberDefinition>> callGraph;
12+
readonly Dictionary<IMemberDefinition, HashSet<IMemberDefinition>> _callGraph;
1313

14-
public CompilerGeneratedCallGraph () => callGraph = new Dictionary<IMemberDefinition, HashSet<IMemberDefinition>> ();
14+
public CompilerGeneratedCallGraph () => _callGraph = new Dictionary<IMemberDefinition, HashSet<IMemberDefinition>> ();
1515

1616
void TrackCallInternal (IMemberDefinition fromMember, IMemberDefinition toMember)
1717
{
18-
if (!callGraph.TryGetValue (fromMember, out HashSet<IMemberDefinition>? toMembers)) {
18+
if (!_callGraph.TryGetValue (fromMember, out HashSet<IMemberDefinition>? toMembers)) {
1919
toMembers = new HashSet<IMemberDefinition> ();
20-
callGraph.Add (fromMember, toMembers);
20+
_callGraph.Add (fromMember, toMembers);
2121
}
2222
toMembers.Add (toMember);
2323
}
@@ -48,7 +48,7 @@ public IEnumerable<IMemberDefinition> GetReachableMembers (MethodDefinition star
4848
visited.Add (start);
4949
queue.Enqueue (start);
5050
while (queue.TryDequeue (out IMemberDefinition? method)) {
51-
if (!callGraph.TryGetValue (method, out HashSet<IMemberDefinition>? callees))
51+
if (!_callGraph.TryGetValue (method, out HashSet<IMemberDefinition>? callees))
5252
continue;
5353

5454
foreach (var callee in callees) {

src/linker/Linker.Dataflow/CompilerGeneratedState.cs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ public static bool TryGetStateMachineType (MethodDefinition method, [NotNullWhen
102102
/// up and find the nearest containing user type. Returns the nearest user type,
103103
/// or null if none was found.
104104
/// </summary>
105-
TypeDefinition? PopulateCacheForType (TypeDefinition type)
105+
TypeDefinition? GetCompilerGeneratedStateForType (TypeDefinition type)
106106
{
107107
// Look in the declaring type if this is a compiler-generated type (state machine or display class).
108108
// State machines can be emitted into display classes, so we may also need to go one more level up.
@@ -183,7 +183,7 @@ lambdaOrLocalFunction.DeclaringType is var generatedType &&
183183
}
184184
// Already warned above if multiple methods map to the same type
185185
// Fill in null for argument providers now, the real providers will be filled in later
186-
_ = _generatedTypeToTypeArgumentInfo.TryAdd (stateMachineType, new TypeArgumentInfo (method, null));
186+
_generatedTypeToTypeArgumentInfo[stateMachineType] = new TypeArgumentInfo (method, null);
187187
}
188188
}
189189

@@ -292,6 +292,7 @@ void MapGeneratedTypeTypeParameters (TypeDefinition generatedType)
292292
if (typeRef is null) {
293293
return;
294294
}
295+
295296
for (int i = 0; i < typeRef.GenericArguments.Count; i++) {
296297
var typeArg = typeRef.GenericArguments[i];
297298
// Start with the existing parameters, in case we can't find the mapped one
@@ -321,6 +322,7 @@ void MapGeneratedTypeTypeParameters (TypeDefinition generatedType)
321322

322323
typeArgs[i] = userAttrs;
323324
}
325+
324326
_generatedTypeToTypeArgumentInfo[generatedType] = typeInfo with { OriginalAttributes = typeArgs };
325327
}
326328
}
@@ -356,7 +358,7 @@ public bool TryGetCompilerGeneratedCalleesForUserMethod (MethodDefinition method
356358
if (IsNestedFunctionOrStateMachineMember (method))
357359
return false;
358360

359-
var typeToCache = PopulateCacheForType (method.DeclaringType);
361+
var typeToCache = GetCompilerGeneratedStateForType (method.DeclaringType);
360362
if (typeToCache is null)
361363
return false;
362364

@@ -371,7 +373,7 @@ public bool TryGetCompilerGeneratedCalleesForUserMethod (MethodDefinition method
371373
{
372374
Debug.Assert (CompilerGeneratedNames.IsGeneratedType (generatedType.Name));
373375

374-
var typeToCache = PopulateCacheForType (generatedType);
376+
var typeToCache = GetCompilerGeneratedStateForType (generatedType);
375377
if (typeToCache is null)
376378
return null;
377379

@@ -407,7 +409,7 @@ public bool TryGetOwningMethodForCompilerGeneratedMember (IMemberDefinition sour
407409
// sourceType is a state machine type, or the type containing a lambda or local function.
408410
// Search all methods to find the one which points to the type as its
409411
// state machine implementation.
410-
var typeToCache = PopulateCacheForType (sourceType);
412+
var typeToCache = GetCompilerGeneratedStateForType (sourceType);
411413
if (typeToCache is null)
412414
return false;
413415

test/Mono.Linker.Tests.Cases/DataFlow/AttributeConstructorDataflow.cs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,11 @@ class AttributeConstructorDataflow
1616
{
1717
[KeptAttributeAttribute (typeof (KeepsPublicConstructorAttribute))]
1818
[KeptAttributeAttribute (typeof (KeepsPublicMethodsAttribute))]
19+
[KeptAttributeAttribute (typeof (KeepsPublicFieldsAttribute))]
1920
[KeptAttributeAttribute (typeof (TypeArrayAttribute))]
2021
[KeepsPublicConstructor (typeof (ClassWithKeptPublicConstructor))]
2122
[KeepsPublicMethods ("Mono.Linker.Tests.Cases.DataFlow.AttributeConstructorDataflow+ClassWithKeptPublicMethods")]
23+
[KeepsPublicFields (null, null)]
2224
[TypeArray (new Type[] { typeof (AttributeConstructorDataflow) })]
2325
// Trimmer only for now - https://github.com/dotnet/linker/issues/2273
2426
[ExpectedWarning ("IL2026", "--ClassWithKeptPublicMethods--", ProducedBy = ProducedBy.Trimmer)]
@@ -55,6 +57,23 @@ public KeepsPublicMethodsAttribute (
5557
}
5658
}
5759

60+
// Used to test null parameter values
61+
[Kept]
62+
[KeptBaseType (typeof (Attribute))]
63+
class KeepsPublicFieldsAttribute : Attribute
64+
{
65+
[Kept]
66+
public KeepsPublicFieldsAttribute (
67+
[KeptAttributeAttribute(typeof(DynamicallyAccessedMembersAttribute))]
68+
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields)]
69+
Type type,
70+
[KeptAttributeAttribute(typeof(DynamicallyAccessedMembersAttribute))]
71+
[DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicFields)]
72+
string typeName)
73+
{
74+
}
75+
}
76+
5877
[Kept]
5978
class ClassWithKeptPublicConstructor
6079
{

test/Mono.Linker.Tests.Cases/DataFlow/AttributeFieldDataflow.cs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,11 @@ class AttributeFieldDataflow
1616
{
1717
[KeptAttributeAttribute (typeof (KeepsPublicConstructorsAttribute))]
1818
[KeptAttributeAttribute (typeof (KeepsPublicMethodsAttribute))]
19+
[KeptAttributeAttribute (typeof (KeepsPublicFieldsAttribute))]
1920
[KeptAttributeAttribute (typeof (TypeArrayAttribute))]
2021
[KeepsPublicConstructors (Type = typeof (ClassWithKeptPublicConstructor))]
2122
[KeepsPublicMethods (Type = "Mono.Linker.Tests.Cases.DataFlow.AttributeFieldDataflow+ClassWithKeptPublicMethods")]
23+
[KeepsPublicFields (Type = null, TypeName = null)]
2224
[TypeArray (Types = new Type[] { typeof (AttributeFieldDataflow) })]
2325
// Trimmer only for now - https://github.com/dotnet/linker/issues/2273
2426
[ExpectedWarning ("IL2026", "--ClassWithKeptPublicMethods--", ProducedBy = ProducedBy.Trimmer)]
@@ -58,6 +60,27 @@ public KeepsPublicMethodsAttribute ()
5860
public string Type;
5961
}
6062

63+
// Use to test null values
64+
[Kept]
65+
[KeptBaseType (typeof (Attribute))]
66+
class KeepsPublicFieldsAttribute : Attribute
67+
{
68+
[Kept]
69+
public KeepsPublicFieldsAttribute ()
70+
{
71+
}
72+
73+
[Kept]
74+
[KeptAttributeAttribute (typeof (DynamicallyAccessedMembersAttribute))]
75+
[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)]
76+
public Type Type;
77+
78+
[Kept]
79+
[KeptAttributeAttribute (typeof (DynamicallyAccessedMembersAttribute))]
80+
[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)]
81+
public string TypeName;
82+
}
83+
6184
[Kept]
6285
class ClassWithKeptPublicConstructor
6386
{

test/Mono.Linker.Tests.Cases/DataFlow/AttributePropertyDataflow.cs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,11 @@ class AttributePropertyDataflow
1616
{
1717
[KeptAttributeAttribute (typeof (KeepsPublicConstructorsAttribute))]
1818
[KeptAttributeAttribute (typeof (KeepsPublicMethodsAttribute))]
19+
[KeptAttributeAttribute (typeof (KeepsPublicFieldsAttribute))]
1920
[KeptAttributeAttribute (typeof (TypeArrayAttribute))]
2021
[KeepsPublicConstructors (Type = typeof (ClassWithKeptPublicConstructor))]
2122
[KeepsPublicMethods (Type = "Mono.Linker.Tests.Cases.DataFlow.AttributePropertyDataflow+ClassWithKeptPublicMethods")]
23+
[KeepsPublicFields (Type = null, TypeName = null)]
2224
[TypeArray (Types = new Type[] { typeof (AttributePropertyDataflow) })]
2325
// Trimmer only for now - https://github.com/dotnet/linker/issues/2273
2426
[ExpectedWarning ("IL2026", "--ClassWithKeptPublicMethods--", ProducedBy = ProducedBy.Trimmer)]
@@ -60,6 +62,29 @@ public KeepsPublicMethodsAttribute ()
6062
public string Type { get; [Kept] set; }
6163
}
6264

65+
// Used to test null values
66+
[Kept]
67+
[KeptBaseType (typeof (Attribute))]
68+
class KeepsPublicFieldsAttribute : Attribute
69+
{
70+
[Kept]
71+
public KeepsPublicFieldsAttribute ()
72+
{
73+
}
74+
75+
[field: Kept]
76+
[Kept]
77+
[KeptAttributeAttribute (typeof (DynamicallyAccessedMembersAttribute))]
78+
[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)]
79+
public Type Type { get; [Kept] set; }
80+
81+
[field: Kept]
82+
[Kept]
83+
[KeptAttributeAttribute (typeof (DynamicallyAccessedMembersAttribute))]
84+
[DynamicallyAccessedMembers (DynamicallyAccessedMemberTypes.PublicFields)]
85+
public string TypeName { get; [Kept] set; }
86+
}
87+
6388
[Kept]
6489
class ClassWithKeptPublicConstructor
6590
{

0 commit comments

Comments
 (0)