mirror of
https://github.com/github/codeql.git
synced 2025-12-20 10:46:30 +01:00
C#: Extract init only accessors and custom modifiers
This commit is contained in:
@@ -76,9 +76,10 @@ namespace Semmle.Extraction.CIL.Entities
|
||||
|
||||
var typeSignature = md.DecodeSignature(Cx.TypeSignatureDecoder, this);
|
||||
|
||||
Parameters = MakeParameters(typeSignature.ParameterTypes).ToArray();
|
||||
var parameters = GetParameterExtractionProducts(typeSignature.ParameterTypes).ToArray();
|
||||
Parameters = parameters.OfType<Parameter>().ToArray();
|
||||
|
||||
foreach (var c in Parameters)
|
||||
foreach (var c in parameters)
|
||||
yield return c;
|
||||
|
||||
foreach (var c in PopulateFlags)
|
||||
@@ -95,7 +96,12 @@ namespace Semmle.Extraction.CIL.Entities
|
||||
}
|
||||
|
||||
yield return Tuples.metadata_handle(this, Cx.Assembly, MetadataTokens.GetToken(handle));
|
||||
yield return Tuples.cil_method(this, Name, declaringType, typeSignature.ReturnType);
|
||||
|
||||
foreach (var m in GetMethodExtractionProducts(Name, declaringType, typeSignature.ReturnType))
|
||||
{
|
||||
yield return m;
|
||||
}
|
||||
|
||||
yield return Tuples.cil_method_source_declaration(this, this);
|
||||
yield return Tuples.cil_method_location(this, Cx.Assembly);
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace Semmle.Extraction.CIL.Entities
|
||||
/// <summary>
|
||||
/// An entity representing a field.
|
||||
/// </summary>
|
||||
internal abstract class Field : GenericContext, IMember
|
||||
internal abstract class Field : GenericContext, IMember, ICustomModifierReceiver
|
||||
{
|
||||
protected Field(Context cx) : base(cx)
|
||||
{
|
||||
@@ -45,7 +45,13 @@ namespace Semmle.Extraction.CIL.Entities
|
||||
{
|
||||
get
|
||||
{
|
||||
yield return Tuples.cil_field(this, DeclaringType, Name, Type);
|
||||
var t = Type;
|
||||
if (t is ModifiedType mt)
|
||||
{
|
||||
t = mt.Unmodified;
|
||||
yield return Tuples.cil_custom_modifiers(this, mt.Modifier, mt.IsRequired);
|
||||
}
|
||||
yield return Tuples.cil_field(this, DeclaringType, Name, t);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -76,12 +76,16 @@ namespace Semmle.Extraction.CIL.Entities
|
||||
|
||||
var typeSignature = mr.DecodeMethodSignature(Cx.TypeSignatureDecoder, this);
|
||||
|
||||
Parameters = MakeParameters(typeSignature.ParameterTypes).ToArray();
|
||||
foreach (var p in Parameters) yield return p;
|
||||
var parameters = GetParameterExtractionProducts(typeSignature.ParameterTypes).ToArray();
|
||||
Parameters = parameters.OfType<Parameter>().ToArray();
|
||||
foreach (var p in parameters) yield return p;
|
||||
|
||||
foreach (var f in PopulateFlags) yield return f;
|
||||
|
||||
yield return Tuples.cil_method(this, Name, DeclaringType, typeSignature.ReturnType);
|
||||
foreach (var m in GetMethodExtractionProducts(Name, DeclaringType, typeSignature.ReturnType))
|
||||
{
|
||||
yield return m;
|
||||
}
|
||||
|
||||
if (SourceDeclaration != null)
|
||||
yield return Tuples.cil_method_source_declaration(this, SourceDeclaration);
|
||||
|
||||
@@ -3,14 +3,13 @@ using System.Reflection.Metadata;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.IO;
|
||||
using Semmle.Util;
|
||||
|
||||
namespace Semmle.Extraction.CIL.Entities
|
||||
{
|
||||
/// <summary>
|
||||
/// A method entity.
|
||||
/// </summary>
|
||||
internal abstract class Method : TypeContainer, IMember
|
||||
internal abstract class Method : TypeContainer, IMember, ICustomModifierReceiver
|
||||
{
|
||||
protected MethodTypeParameter[]? genericParams;
|
||||
protected GenericContext gc;
|
||||
@@ -21,6 +20,8 @@ namespace Semmle.Extraction.CIL.Entities
|
||||
this.gc = gc;
|
||||
}
|
||||
|
||||
public ITypeSignature ReturnType => signature.ReturnType;
|
||||
|
||||
public override IEnumerable<Type> TypeParameters => gc.TypeParameters.Concat(DeclaringType.TypeParameters);
|
||||
|
||||
public override IEnumerable<Type> MethodParameters =>
|
||||
@@ -76,7 +77,7 @@ namespace Semmle.Extraction.CIL.Entities
|
||||
|
||||
public abstract bool IsStatic { get; }
|
||||
|
||||
protected IEnumerable<Parameter> MakeParameters(IEnumerable<Type> parameterTypes)
|
||||
protected IEnumerable<IExtractionProduct> GetParameterExtractionProducts(IEnumerable<Type> parameterTypes)
|
||||
{
|
||||
var i = 0;
|
||||
|
||||
@@ -86,7 +87,26 @@ namespace Semmle.Extraction.CIL.Entities
|
||||
}
|
||||
|
||||
foreach (var p in parameterTypes)
|
||||
yield return Cx.Populate(new Parameter(Cx, this, i++, p));
|
||||
{
|
||||
var t = p;
|
||||
if (t is ModifiedType mt)
|
||||
{
|
||||
t = mt.Unmodified;
|
||||
yield return Tuples.cil_custom_modifiers(this, mt.Modifier, mt.IsRequired);
|
||||
}
|
||||
yield return Cx.Populate(new Parameter(Cx, this, i++, t));
|
||||
}
|
||||
}
|
||||
|
||||
protected IEnumerable<IExtractionProduct> GetMethodExtractionProducts(string name, Type declaringType, Type returnType)
|
||||
{
|
||||
var t = returnType;
|
||||
if (t is ModifiedType mt)
|
||||
{
|
||||
t = mt.Unmodified;
|
||||
yield return Tuples.cil_custom_modifiers(this, mt.Modifier, mt.IsRequired);
|
||||
}
|
||||
yield return Tuples.cil_method(this, name, declaringType, t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,14 +77,19 @@ namespace Semmle.Extraction.CIL.Entities
|
||||
throw new InternalError($"Unexpected constructed method handle kind {ms.Method.Kind}");
|
||||
}
|
||||
|
||||
Parameters = MakeParameters(constructedTypeSignature.ParameterTypes).ToArray();
|
||||
foreach (var p in Parameters)
|
||||
var parameters = GetParameterExtractionProducts(constructedTypeSignature.ParameterTypes).ToArray();
|
||||
Parameters = parameters.OfType<Parameter>().ToArray();
|
||||
foreach (var p in parameters)
|
||||
yield return p;
|
||||
|
||||
foreach (var f in PopulateFlags)
|
||||
yield return f;
|
||||
|
||||
yield return Tuples.cil_method(this, Name, DeclaringType, constructedTypeSignature.ReturnType);
|
||||
foreach (var m in GetMethodExtractionProducts(Name, DeclaringType, constructedTypeSignature.ReturnType))
|
||||
{
|
||||
yield return m;
|
||||
}
|
||||
|
||||
yield return Tuples.cil_method_source_declaration(this, SourceDeclaration);
|
||||
|
||||
if (typeParams.Length != unboundMethod.GenericParameterCount)
|
||||
|
||||
@@ -0,0 +1,49 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
namespace Semmle.Extraction.CIL.Entities
|
||||
{
|
||||
/// <summary>
|
||||
/// Modified types are not written directly to trap files. Instead, the modifiers are stored
|
||||
/// on the modifiable entity (field type, property/method/function pointer parameter or return types).
|
||||
/// </summary>
|
||||
internal sealed class ModifiedType : Type
|
||||
{
|
||||
public ModifiedType(Context cx, Type unmodified, Type modifier, bool isRequired) : base(cx)
|
||||
{
|
||||
Unmodified = unmodified;
|
||||
Modifier = modifier;
|
||||
IsRequired = isRequired;
|
||||
}
|
||||
|
||||
public Type Unmodified { get; }
|
||||
public Type Modifier { get; }
|
||||
public bool IsRequired { get; }
|
||||
|
||||
public override CilTypeKind Kind => throw new NotImplementedException();
|
||||
|
||||
public override Namespace? ContainingNamespace => throw new NotImplementedException();
|
||||
|
||||
public override Type? ContainingType => throw new NotImplementedException();
|
||||
|
||||
public override IEnumerable<Type> TypeParameters => throw new NotImplementedException();
|
||||
|
||||
public override int ThisTypeParameterCount => throw new NotImplementedException();
|
||||
|
||||
public override Type Construct(IEnumerable<Type> typeArguments) => throw new NotImplementedException();
|
||||
|
||||
public override string Name => Unmodified.Name + (IsRequired ? " modreq" : " modopt") + $"({Modifier.Name})";
|
||||
|
||||
public override void WriteAssemblyPrefix(TextWriter trapFile) => Unmodified.WriteAssemblyPrefix(trapFile);
|
||||
|
||||
public override void WriteId(TextWriter trapFile, bool inContext)
|
||||
{
|
||||
Unmodified.WriteId(trapFile, inContext);
|
||||
trapFile.Write(IsRequired ? " modreq" : " modopt");
|
||||
trapFile.Write("(");
|
||||
Modifier.WriteId(trapFile, inContext);
|
||||
trapFile.Write(")");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,7 @@ namespace Semmle.Extraction.CIL.Entities
|
||||
/// <summary>
|
||||
/// A property.
|
||||
/// </summary>
|
||||
internal sealed class Property : LabelledEntity
|
||||
internal sealed class Property : LabelledEntity, ICustomModifierReceiver
|
||||
{
|
||||
private readonly Handle handle;
|
||||
private readonly Type type;
|
||||
@@ -54,7 +54,15 @@ namespace Semmle.Extraction.CIL.Entities
|
||||
yield return Tuples.metadata_handle(this, Cx.Assembly, MetadataTokens.GetToken(handle));
|
||||
var sig = pd.DecodeSignature(Cx.TypeSignatureDecoder, type);
|
||||
|
||||
yield return Tuples.cil_property(this, type, Cx.ShortName(pd.Name), sig.ReturnType);
|
||||
var name = Cx.ShortName(pd.Name);
|
||||
|
||||
var t = sig.ReturnType;
|
||||
if (t is ModifiedType mt)
|
||||
{
|
||||
t = mt.Unmodified;
|
||||
yield return Tuples.cil_custom_modifiers(this, mt.Modifier, mt.IsRequired);
|
||||
}
|
||||
yield return Tuples.cil_property(this, type, name, t);
|
||||
|
||||
var accessors = pd.GetAccessors();
|
||||
if (!accessors.Getter.IsNil)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System.Reflection.Metadata;
|
||||
using System.Collections.Immutable;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
namespace Semmle.Extraction.CIL.Entities
|
||||
{
|
||||
@@ -138,21 +139,28 @@ namespace Semmle.Extraction.CIL.Entities
|
||||
private class Modified : ITypeSignature
|
||||
{
|
||||
private readonly ITypeSignature unmodifiedType;
|
||||
private readonly ITypeSignature modifier;
|
||||
private readonly bool isRequired;
|
||||
|
||||
public Modified(ITypeSignature unmodifiedType)
|
||||
public Modified(ITypeSignature unmodifiedType, ITypeSignature modifier, bool isRequired)
|
||||
{
|
||||
this.unmodifiedType = unmodifiedType;
|
||||
this.modifier = modifier;
|
||||
this.isRequired = isRequired;
|
||||
}
|
||||
|
||||
public void WriteId(TextWriter trapFile, GenericContext gc)
|
||||
{
|
||||
unmodifiedType.WriteId(trapFile, gc);
|
||||
trapFile.Write(isRequired ? " modreq(" : " modopt(");
|
||||
modifier.WriteId(trapFile, gc);
|
||||
trapFile.Write(")");
|
||||
}
|
||||
}
|
||||
|
||||
ITypeSignature ISignatureTypeProvider<ITypeSignature, object>.GetModifiedType(ITypeSignature modifier, ITypeSignature unmodifiedType, bool isRequired)
|
||||
{
|
||||
return new Modified(unmodifiedType);
|
||||
return new Modified(unmodifiedType, modifier, isRequired);
|
||||
}
|
||||
|
||||
private class Pinned : ITypeSignature
|
||||
|
||||
@@ -35,7 +35,7 @@ namespace Semmle.Extraction.CIL.Entities
|
||||
genericContext.GetGenericTypeParameter(index);
|
||||
|
||||
Type ISignatureTypeProvider<Type, GenericContext>.GetModifiedType(Type modifier, Type unmodifiedType, bool isRequired) =>
|
||||
unmodifiedType; // !! Not implemented properly
|
||||
new ModifiedType(cx, unmodifiedType, modifier, isRequired);
|
||||
|
||||
Type ISignatureTypeProvider<Type, GenericContext>.GetPinnedType(Type elementType) =>
|
||||
cx.Populate(new PointerType(cx, elementType));
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
namespace Semmle.Extraction.CIL
|
||||
{
|
||||
internal interface ICustomModifierReceiver
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -188,6 +188,9 @@ namespace Semmle.Extraction.CIL
|
||||
internal static Tuple cil_virtual(Method method) =>
|
||||
new Tuple("cil_virtual", method);
|
||||
|
||||
internal static Tuple cil_custom_modifiers(ICustomModifierReceiver receiver, Type modifier, bool isRequired) =>
|
||||
new Tuple("cil_custom_modifiers", receiver, modifier, isRequired ? 1 : 0);
|
||||
|
||||
internal static Tuple containerparent(Folder parent, IFileOrFolder child) =>
|
||||
new Tuple("containerparent", parent, child);
|
||||
|
||||
|
||||
@@ -247,8 +247,12 @@ class Setter extends Accessor {
|
||||
|
||||
override Property getProperty() { cil_setter(result, this) }
|
||||
|
||||
/** Holds if this setter is an `init`-only accessor. */
|
||||
predicate isInitOnly() { none() }
|
||||
/** Holds if this setter is an `init` accessor. */
|
||||
predicate isInitOnly() {
|
||||
exists(Type t | t.getQualifiedName() = "System.Runtime.CompilerServices.IsExternalInit" |
|
||||
cil_custom_modifiers(this, t, 1)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1712,6 +1712,7 @@ cil_field(
|
||||
@cil_variable = @cil_field | @cil_stack_variable;
|
||||
@cil_stack_variable = @cil_local_variable | @cil_parameter;
|
||||
@cil_member = @cil_method | @cil_type | @cil_field | @cil_property | @cil_event;
|
||||
@cil_custom_modifier_receiver = @cil_method | @cil_property | @cil_parameter | @cil_field; // todo: add function pointer type
|
||||
|
||||
#keyset[method, index]
|
||||
cil_parameter(
|
||||
@@ -1726,6 +1727,12 @@ cil_parameter_out(unique int id: @cil_parameter ref);
|
||||
cil_setter(unique int prop: @cil_property ref,
|
||||
int method: @cil_method ref);
|
||||
|
||||
#keyset[id, modifier]
|
||||
cil_custom_modifiers(
|
||||
int id: @cil_custom_modifier_receiver ref,
|
||||
int modifier: @cil_type ref,
|
||||
int kind: int ref); // modreq: 1, modopt: 0
|
||||
|
||||
cil_getter(unique int prop: @cil_property ref,
|
||||
int method: @cil_method ref);
|
||||
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
| cil-init-prop.dll:0:0:0:0 | set_Prop1 | set |
|
||||
| cil-init-prop.dll:0:0:0:0 | set_Prop2 | set |
|
||||
| cil-init-prop.dll:0:0:0:0 | set_Prop2 | init |
|
||||
|
||||
Reference in New Issue
Block a user