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);
|
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;
|
yield return c;
|
||||||
|
|
||||||
foreach (var c in PopulateFlags)
|
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.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_source_declaration(this, this);
|
||||||
yield return Tuples.cil_method_location(this, Cx.Assembly);
|
yield return Tuples.cil_method_location(this, Cx.Assembly);
|
||||||
|
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ namespace Semmle.Extraction.CIL.Entities
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// An entity representing a field.
|
/// An entity representing a field.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal abstract class Field : GenericContext, IMember
|
internal abstract class Field : GenericContext, IMember, ICustomModifierReceiver
|
||||||
{
|
{
|
||||||
protected Field(Context cx) : base(cx)
|
protected Field(Context cx) : base(cx)
|
||||||
{
|
{
|
||||||
@@ -45,7 +45,13 @@ namespace Semmle.Extraction.CIL.Entities
|
|||||||
{
|
{
|
||||||
get
|
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);
|
var typeSignature = mr.DecodeMethodSignature(Cx.TypeSignatureDecoder, this);
|
||||||
|
|
||||||
Parameters = MakeParameters(typeSignature.ParameterTypes).ToArray();
|
var parameters = GetParameterExtractionProducts(typeSignature.ParameterTypes).ToArray();
|
||||||
foreach (var p in Parameters) yield return p;
|
Parameters = parameters.OfType<Parameter>().ToArray();
|
||||||
|
foreach (var p in parameters) yield return p;
|
||||||
|
|
||||||
foreach (var f in PopulateFlags) yield return f;
|
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)
|
if (SourceDeclaration != null)
|
||||||
yield return Tuples.cil_method_source_declaration(this, SourceDeclaration);
|
yield return Tuples.cil_method_source_declaration(this, SourceDeclaration);
|
||||||
|
|||||||
@@ -3,14 +3,13 @@ using System.Reflection.Metadata;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using Semmle.Util;
|
|
||||||
|
|
||||||
namespace Semmle.Extraction.CIL.Entities
|
namespace Semmle.Extraction.CIL.Entities
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A method entity.
|
/// A method entity.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal abstract class Method : TypeContainer, IMember
|
internal abstract class Method : TypeContainer, IMember, ICustomModifierReceiver
|
||||||
{
|
{
|
||||||
protected MethodTypeParameter[]? genericParams;
|
protected MethodTypeParameter[]? genericParams;
|
||||||
protected GenericContext gc;
|
protected GenericContext gc;
|
||||||
@@ -21,6 +20,8 @@ namespace Semmle.Extraction.CIL.Entities
|
|||||||
this.gc = gc;
|
this.gc = gc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ITypeSignature ReturnType => signature.ReturnType;
|
||||||
|
|
||||||
public override IEnumerable<Type> TypeParameters => gc.TypeParameters.Concat(DeclaringType.TypeParameters);
|
public override IEnumerable<Type> TypeParameters => gc.TypeParameters.Concat(DeclaringType.TypeParameters);
|
||||||
|
|
||||||
public override IEnumerable<Type> MethodParameters =>
|
public override IEnumerable<Type> MethodParameters =>
|
||||||
@@ -76,7 +77,7 @@ namespace Semmle.Extraction.CIL.Entities
|
|||||||
|
|
||||||
public abstract bool IsStatic { get; }
|
public abstract bool IsStatic { get; }
|
||||||
|
|
||||||
protected IEnumerable<Parameter> MakeParameters(IEnumerable<Type> parameterTypes)
|
protected IEnumerable<IExtractionProduct> GetParameterExtractionProducts(IEnumerable<Type> parameterTypes)
|
||||||
{
|
{
|
||||||
var i = 0;
|
var i = 0;
|
||||||
|
|
||||||
@@ -86,7 +87,26 @@ namespace Semmle.Extraction.CIL.Entities
|
|||||||
}
|
}
|
||||||
|
|
||||||
foreach (var p in parameterTypes)
|
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}");
|
throw new InternalError($"Unexpected constructed method handle kind {ms.Method.Kind}");
|
||||||
}
|
}
|
||||||
|
|
||||||
Parameters = MakeParameters(constructedTypeSignature.ParameterTypes).ToArray();
|
var parameters = GetParameterExtractionProducts(constructedTypeSignature.ParameterTypes).ToArray();
|
||||||
foreach (var p in Parameters)
|
Parameters = parameters.OfType<Parameter>().ToArray();
|
||||||
|
foreach (var p in parameters)
|
||||||
yield return p;
|
yield return p;
|
||||||
|
|
||||||
foreach (var f in PopulateFlags)
|
foreach (var f in PopulateFlags)
|
||||||
yield return f;
|
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);
|
yield return Tuples.cil_method_source_declaration(this, SourceDeclaration);
|
||||||
|
|
||||||
if (typeParams.Length != unboundMethod.GenericParameterCount)
|
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>
|
/// <summary>
|
||||||
/// A property.
|
/// A property.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal sealed class Property : LabelledEntity
|
internal sealed class Property : LabelledEntity, ICustomModifierReceiver
|
||||||
{
|
{
|
||||||
private readonly Handle handle;
|
private readonly Handle handle;
|
||||||
private readonly Type type;
|
private readonly Type type;
|
||||||
@@ -54,7 +54,15 @@ namespace Semmle.Extraction.CIL.Entities
|
|||||||
yield return Tuples.metadata_handle(this, Cx.Assembly, MetadataTokens.GetToken(handle));
|
yield return Tuples.metadata_handle(this, Cx.Assembly, MetadataTokens.GetToken(handle));
|
||||||
var sig = pd.DecodeSignature(Cx.TypeSignatureDecoder, type);
|
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();
|
var accessors = pd.GetAccessors();
|
||||||
if (!accessors.Getter.IsNil)
|
if (!accessors.Getter.IsNil)
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using System.Reflection.Metadata;
|
using System.Reflection.Metadata;
|
||||||
using System.Collections.Immutable;
|
using System.Collections.Immutable;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace Semmle.Extraction.CIL.Entities
|
namespace Semmle.Extraction.CIL.Entities
|
||||||
{
|
{
|
||||||
@@ -138,21 +139,28 @@ namespace Semmle.Extraction.CIL.Entities
|
|||||||
private class Modified : ITypeSignature
|
private class Modified : ITypeSignature
|
||||||
{
|
{
|
||||||
private readonly ITypeSignature unmodifiedType;
|
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.unmodifiedType = unmodifiedType;
|
||||||
|
this.modifier = modifier;
|
||||||
|
this.isRequired = isRequired;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void WriteId(TextWriter trapFile, GenericContext gc)
|
public void WriteId(TextWriter trapFile, GenericContext gc)
|
||||||
{
|
{
|
||||||
unmodifiedType.WriteId(trapFile, 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)
|
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
|
private class Pinned : ITypeSignature
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ namespace Semmle.Extraction.CIL.Entities
|
|||||||
genericContext.GetGenericTypeParameter(index);
|
genericContext.GetGenericTypeParameter(index);
|
||||||
|
|
||||||
Type ISignatureTypeProvider<Type, GenericContext>.GetModifiedType(Type modifier, Type unmodifiedType, bool isRequired) =>
|
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) =>
|
Type ISignatureTypeProvider<Type, GenericContext>.GetPinnedType(Type elementType) =>
|
||||||
cx.Populate(new PointerType(cx, 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) =>
|
internal static Tuple cil_virtual(Method method) =>
|
||||||
new Tuple("cil_virtual", 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) =>
|
internal static Tuple containerparent(Folder parent, IFileOrFolder child) =>
|
||||||
new Tuple("containerparent", parent, child);
|
new Tuple("containerparent", parent, child);
|
||||||
|
|
||||||
|
|||||||
@@ -247,8 +247,12 @@ class Setter extends Accessor {
|
|||||||
|
|
||||||
override Property getProperty() { cil_setter(result, this) }
|
override Property getProperty() { cil_setter(result, this) }
|
||||||
|
|
||||||
/** Holds if this setter is an `init`-only accessor. */
|
/** Holds if this setter is an `init` accessor. */
|
||||||
predicate isInitOnly() { none() }
|
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_variable = @cil_field | @cil_stack_variable;
|
||||||
@cil_stack_variable = @cil_local_variable | @cil_parameter;
|
@cil_stack_variable = @cil_local_variable | @cil_parameter;
|
||||||
@cil_member = @cil_method | @cil_type | @cil_field | @cil_property | @cil_event;
|
@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]
|
#keyset[method, index]
|
||||||
cil_parameter(
|
cil_parameter(
|
||||||
@@ -1726,6 +1727,12 @@ cil_parameter_out(unique int id: @cil_parameter ref);
|
|||||||
cil_setter(unique int prop: @cil_property ref,
|
cil_setter(unique int prop: @cil_property ref,
|
||||||
int method: @cil_method 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,
|
cil_getter(unique int prop: @cil_property ref,
|
||||||
int method: @cil_method 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_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