mirror of
https://github.com/github/codeql.git
synced 2026-04-25 08:45:14 +02:00
C#: Take nullability into account when creating symbol entities. Otherwise, an entity with the wrong (cached) nullability could be created.
This commit is contained in:
@@ -77,7 +77,7 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
}
|
||||
|
||||
public new static Accessor Create(Context cx, IMethodSymbol symbol) =>
|
||||
AccessorFactory.Instance.CreateEntity(cx, symbol);
|
||||
AccessorFactory.Instance.CreateEntityFromSymbol(cx, symbol);
|
||||
|
||||
class AccessorFactory : ICachedEntityFactory<IMethodSymbol, Accessor>
|
||||
{
|
||||
|
||||
@@ -104,7 +104,7 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
{
|
||||
case MethodKind.StaticConstructor:
|
||||
case MethodKind.Constructor:
|
||||
return ConstructorFactory.Instance.CreateEntity(cx, constructor);
|
||||
return ConstructorFactory.Instance.CreateEntityFromSymbol(cx, constructor);
|
||||
default:
|
||||
throw new InternalError(constructor, "Attempt to create a Constructor from a symbol that isn't a constructor");
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
: base(cx, init) { }
|
||||
|
||||
public new static Conversion Create(Context cx, IMethodSymbol symbol) =>
|
||||
ConversionFactory.Instance.CreateEntity(cx, symbol);
|
||||
ConversionFactory.Instance.CreateEntityFromSymbol(cx, symbol);
|
||||
|
||||
public override Microsoft.CodeAnalysis.Location ReportingLocation
|
||||
{
|
||||
|
||||
@@ -24,7 +24,7 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
}
|
||||
|
||||
public new static Destructor Create(Context cx, IMethodSymbol symbol) =>
|
||||
DestructorFactory.Instance.CreateEntity(cx, symbol);
|
||||
DestructorFactory.Instance.CreateEntityFromSymbol(cx, symbol);
|
||||
|
||||
class DestructorFactory : ICachedEntityFactory<IMethodSymbol, Destructor>
|
||||
{
|
||||
|
||||
@@ -60,7 +60,7 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
TypeMention.Create(Context, syntaxType, this, type);
|
||||
}
|
||||
|
||||
public static Event Create(Context cx, IEventSymbol symbol) => EventFactory.Instance.CreateEntity(cx, symbol);
|
||||
public static Event Create(Context cx, IEventSymbol symbol) => EventFactory.Instance.CreateEntityFromSymbol(cx, symbol);
|
||||
|
||||
class EventFactory : ICachedEntityFactory<IEventSymbol, Event>
|
||||
{
|
||||
|
||||
@@ -53,7 +53,7 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
}
|
||||
|
||||
public new static EventAccessor Create(Context cx, IMethodSymbol symbol) =>
|
||||
EventAccessorFactory.Instance.CreateEntity(cx, symbol);
|
||||
EventAccessorFactory.Instance.CreateEntityFromSymbol(cx, symbol);
|
||||
|
||||
class EventAccessorFactory : ICachedEntityFactory<IMethodSymbol, EventAccessor>
|
||||
{
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
type = new Lazy<AnnotatedType>(() => Entities.Type.Create(cx, symbol.GetAnnotatedType()));
|
||||
}
|
||||
|
||||
public static Field Create(Context cx, IFieldSymbol field) => FieldFactory.Instance.CreateEntity(cx, field);
|
||||
public static Field Create(Context cx, IFieldSymbol field) => FieldFactory.Instance.CreateEntityFromSymbol(cx, field);
|
||||
|
||||
// Do not populate backing fields.
|
||||
// Populate Tuple fields.
|
||||
|
||||
@@ -71,7 +71,7 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
TypeMention.Create(Context, syntax.Type, this, type);
|
||||
}
|
||||
|
||||
public static new Indexer Create(Context cx, IPropertySymbol prop) => IndexerFactory.Instance.CreateEntity(cx, prop);
|
||||
public static new Indexer Create(Context cx, IPropertySymbol prop) => IndexerFactory.Instance.CreateEntityFromSymbol(cx, prop);
|
||||
|
||||
public override void WriteId(TextWriter trapFile)
|
||||
{
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
trapFile.Write('*');
|
||||
}
|
||||
|
||||
public static new LocalFunction Create(Context cx, IMethodSymbol field) => LocalFunctionFactory.Instance.CreateEntity(cx, field);
|
||||
public static new LocalFunction Create(Context cx, IMethodSymbol field) => LocalFunctionFactory.Instance.CreateEntityFromSymbol(cx, field);
|
||||
|
||||
class LocalFunctionFactory : ICachedEntityFactory<IMethodSymbol, LocalFunction>
|
||||
{
|
||||
|
||||
@@ -43,7 +43,7 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
|
||||
public static LocalVariable Create(Context cx, ISymbol local)
|
||||
{
|
||||
return LocalVariableFactory.Instance.CreateEntity(cx, local);
|
||||
return LocalVariableFactory.Instance.CreateEntityFromSymbol(cx, local);
|
||||
}
|
||||
|
||||
void DefineConstantValue(TextWriter trapFile)
|
||||
|
||||
@@ -51,7 +51,7 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
ExtractCompilerGenerated(trapFile);
|
||||
}
|
||||
|
||||
public new static OrdinaryMethod Create(Context cx, IMethodSymbol method) => OrdinaryMethodFactory.Instance.CreateEntity(cx, method);
|
||||
public new static OrdinaryMethod Create(Context cx, IMethodSymbol method) => OrdinaryMethodFactory.Instance.CreateEntityFromSymbol(cx, method);
|
||||
|
||||
class OrdinaryMethodFactory : ICachedEntityFactory<IMethodSymbol, OrdinaryMethod>
|
||||
{
|
||||
|
||||
@@ -113,7 +113,7 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
{
|
||||
bool isIndexer = prop.IsIndexer || prop.Parameters.Any();
|
||||
|
||||
return isIndexer ? Indexer.Create(cx, prop) : PropertyFactory.Instance.CreateEntity(cx, prop);
|
||||
return isIndexer ? Indexer.Create(cx, prop) : PropertyFactory.Instance.CreateEntityFromSymbol(cx, prop);
|
||||
}
|
||||
|
||||
public void VisitDeclaration(Context cx, PropertyDeclarationSyntax p)
|
||||
|
||||
@@ -36,7 +36,7 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
trapFile.Write(";type");
|
||||
}
|
||||
|
||||
public static ArrayType Create(Context cx, IArrayTypeSymbol symbol) => ArrayTypeFactory.Instance.CreateEntity(cx, symbol);
|
||||
public static ArrayType Create(Context cx, IArrayTypeSymbol symbol) => ArrayTypeFactory.Instance.CreateEntityFromSymbol(cx, symbol);
|
||||
|
||||
class ArrayTypeFactory : ICachedEntityFactory<IArrayTypeSymbol, ArrayType>
|
||||
{
|
||||
|
||||
@@ -9,7 +9,7 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
DynamicType(Context cx, IDynamicTypeSymbol init)
|
||||
: base(cx, init) { }
|
||||
|
||||
public static DynamicType Create(Context cx, IDynamicTypeSymbol type) => DynamicTypeFactory.Instance.CreateEntity(cx, type);
|
||||
public static DynamicType Create(Context cx, IDynamicTypeSymbol type) => DynamicTypeFactory.Instance.CreateEntityFromSymbol(cx, type);
|
||||
|
||||
public override Microsoft.CodeAnalysis.Location ReportingLocation => Context.Compilation.ObjectType.Locations.FirstOrDefault();
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
typeArgumentsLazy = new Lazy<Type[]>(() => symbol.TypeArguments.Select(t => Create(cx, t)).ToArray());
|
||||
}
|
||||
|
||||
public static NamedType Create(Context cx, INamedTypeSymbol type) => NamedTypeFactory.Instance.CreateEntity(cx, type);
|
||||
public static NamedType Create(Context cx, INamedTypeSymbol type) => NamedTypeFactory.Instance.CreateEntityFromSymbol(cx, type);
|
||||
|
||||
public override bool NeedsPopulation => base.NeedsPopulation || symbol.TypeKind == TypeKind.Error;
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
|
||||
public Type PointedAtType { get; private set; }
|
||||
|
||||
public static PointerType Create(Context cx, IPointerTypeSymbol symbol) => PointerTypeFactory.Instance.CreateEntity(cx, symbol);
|
||||
public static PointerType Create(Context cx, IPointerTypeSymbol symbol) => PointerTypeFactory.Instance.CreateEntityFromSymbol(cx, symbol);
|
||||
|
||||
class PointerTypeFactory : ICachedEntityFactory<IPointerTypeSymbol, PointerType>
|
||||
{
|
||||
|
||||
@@ -13,7 +13,7 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
/// </summary>
|
||||
class TupleType : Type<INamedTypeSymbol>
|
||||
{
|
||||
public static TupleType Create(Context cx, INamedTypeSymbol type) => TupleTypeFactory.Instance.CreateEntity(cx, type);
|
||||
public static TupleType Create(Context cx, INamedTypeSymbol type) => TupleTypeFactory.Instance.CreateEntityFromSymbol(cx, type);
|
||||
|
||||
class TupleTypeFactory : ICachedEntityFactory<INamedTypeSymbol, TupleType>
|
||||
{
|
||||
|
||||
@@ -324,6 +324,14 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
}
|
||||
|
||||
public override TrapStackBehaviour TrapStackBehaviour => TrapStackBehaviour.NoLabel;
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
var other = obj as Type;
|
||||
return other?.GetType() == GetType() && SymbolEqualityComparer.IncludeNullability.Equals(other.symbol, symbol);
|
||||
}
|
||||
|
||||
public override int GetHashCode() => SymbolEqualityComparer.IncludeNullability.GetHashCode(symbol);
|
||||
}
|
||||
|
||||
abstract class Type<T> : Type where T : ITypeSymbol
|
||||
|
||||
@@ -88,7 +88,7 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
}
|
||||
|
||||
static public TypeParameter Create(Context cx, ITypeParameterSymbol p) =>
|
||||
TypeParameterFactory.Instance.CreateEntity(cx, p);
|
||||
TypeParameterFactory.Instance.CreateEntityFromSymbol(cx, p);
|
||||
|
||||
/// <summary>
|
||||
/// The variance of this type parameter.
|
||||
|
||||
@@ -190,7 +190,7 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
return result;
|
||||
}
|
||||
|
||||
public new static UserOperator Create(Context cx, IMethodSymbol symbol) => UserOperatorFactory.Instance.CreateEntity(cx, symbol);
|
||||
public new static UserOperator Create(Context cx, IMethodSymbol symbol) => UserOperatorFactory.Instance.CreateEntityFromSymbol(cx, symbol);
|
||||
|
||||
class UserOperatorFactory : ICachedEntityFactory<IMethodSymbol, UserOperator>
|
||||
{
|
||||
|
||||
@@ -62,7 +62,7 @@ namespace Semmle.Extraction
|
||||
/// <returns>The new/existing entity.</returns>
|
||||
public Entity CreateNullableEntity<Type, Entity>(ICachedEntityFactory<Type, Entity> factory, Type init) where Entity : ICachedEntity
|
||||
{
|
||||
return init == null ? CreateEntity2(factory, init) : CreateNonNullEntity(factory, init);
|
||||
return init == null ? CreateEntity2(factory, init) : CreateNonNullEntity(factory, init, objectEntityCache);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -161,10 +161,14 @@ namespace Semmle.Extraction
|
||||
|
||||
public Entity CreateNonNullEntity<Type, Entity>(ICachedEntityFactory<Type, Entity> factory, Type init)
|
||||
where Entity : ICachedEntity
|
||||
=> CreateNonNullEntity(factory, init, objectEntityCache);
|
||||
|
||||
|
||||
private Entity CreateNonNullEntity<Type, Entity>(ICachedEntityFactory<Type, Entity> factory, Type init, IDictionary<object, ICachedEntity> dictionary) where Entity : ICachedEntity
|
||||
{
|
||||
if (init is null) throw new ArgumentException("Unexpected null value", nameof(init));
|
||||
|
||||
if (objectEntityCache.TryGetValue(init, out var cached))
|
||||
if (dictionary.TryGetValue(init, out var cached))
|
||||
return (Entity)cached;
|
||||
|
||||
using (StackGuard)
|
||||
@@ -173,7 +177,7 @@ namespace Semmle.Extraction
|
||||
var entity = factory.Create(this, init);
|
||||
entity.Label = label;
|
||||
|
||||
objectEntityCache[init] = entity;
|
||||
dictionary[init] = entity;
|
||||
|
||||
DefineLabel(entity, TrapWriter.Writer, Extractor);
|
||||
if (entity.NeedsPopulation)
|
||||
@@ -227,7 +231,17 @@ namespace Semmle.Extraction
|
||||
#if DEBUG_LABELS
|
||||
readonly Dictionary<string, ICachedEntity> idLabelCache = new Dictionary<string, ICachedEntity>();
|
||||
#endif
|
||||
readonly Dictionary<object, ICachedEntity> objectEntityCache = new Dictionary<object, ICachedEntity>();
|
||||
class SymbolComparer : IEqualityComparer<object>
|
||||
{
|
||||
IEqualityComparer<ISymbol> comparer = SymbolEqualityComparer.IncludeNullability;
|
||||
|
||||
bool IEqualityComparer<object>.Equals(object x, object y) => comparer.Equals((ISymbol)x, (ISymbol)y);
|
||||
|
||||
int IEqualityComparer<object>.GetHashCode(object obj) => comparer.GetHashCode((ISymbol)obj);
|
||||
}
|
||||
|
||||
readonly IDictionary<object, ICachedEntity> objectEntityCache = new Dictionary<object, ICachedEntity>();
|
||||
readonly IDictionary<object, ICachedEntity> symbolEntityCache = new Dictionary<object, ICachedEntity>(10000, new SymbolComparer());
|
||||
readonly Dictionary<ICachedEntity, Label> entityLabelCache = new Dictionary<ICachedEntity, Label>();
|
||||
readonly HashSet<Label> extractedGenerics = new HashSet<Label>();
|
||||
|
||||
|
||||
@@ -133,6 +133,19 @@ namespace Semmle.Extraction
|
||||
public static Entity CreateNullableEntity<Type, Entity>(this ICachedEntityFactory<Type, Entity> factory, Context cx, Type init)
|
||||
where Entity : ICachedEntity => cx.CreateNullableEntity(factory, init);
|
||||
|
||||
/// <summary>
|
||||
/// Creates and populates a new entity, or returns the existing one from the cache.
|
||||
/// </summary>
|
||||
/// <typeparam name="Type">The symbol type used to construct the entity.</typeparam>
|
||||
/// <typeparam name="Entity">The type of the entity to create.</typeparam>
|
||||
/// <param name="cx">The extractor context.</param>
|
||||
/// <param name="factory">The factory used to construct the entity.</param>
|
||||
/// <param name="init">The initializer for the entity, which may not be null.</param>
|
||||
/// <returns>The entity.</returns>
|
||||
public static Entity CreateEntityFromSymbol<Type, Entity>(this ICachedEntityFactory<Type, Entity> factory, Context cx, Type init)
|
||||
where Entity : ICachedEntity
|
||||
where Type : ISymbol => cx.CreateEntityFromSymbol(factory, init);
|
||||
|
||||
/// <summary>
|
||||
/// Creates and populates a new entity, but uses a different cache.
|
||||
/// </summary>
|
||||
|
||||
@@ -241,7 +241,7 @@ expressionTypes
|
||||
| NullableRefTypes.cs:17:29:17:32 | null | null |
|
||||
| NullableRefTypes.cs:18:31:18:34 | this access | MyClass! |
|
||||
| NullableRefTypes.cs:19:33:19:36 | this access | MyClass! |
|
||||
| NullableRefTypes.cs:26:44:26:53 | throw ... | MyClass?[]! |
|
||||
| NullableRefTypes.cs:26:44:26:53 | throw ... | MyClass![]! |
|
||||
| NullableRefTypes.cs:26:50:26:53 | null | null |
|
||||
| NullableRefTypes.cs:27:44:27:53 | throw ... | MyClass?[]! |
|
||||
| NullableRefTypes.cs:27:50:27:53 | null | null |
|
||||
|
||||
Reference in New Issue
Block a user