mirror of
https://github.com/github/codeql.git
synced 2026-04-28 02:05:14 +02:00
C#: Extract function pointer types from CIL
This commit is contained in:
@@ -8,6 +8,7 @@ namespace Semmle.Extraction.CIL.Entities
|
||||
ValueOrRefType,
|
||||
TypeParameter,
|
||||
Array,
|
||||
Pointer
|
||||
Pointer,
|
||||
FunctionPointer
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,116 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Reflection.Metadata;
|
||||
|
||||
namespace Semmle.Extraction.CIL.Entities
|
||||
{
|
||||
internal sealed class FunctionPointerType : Type, IParameterizable, ICustomModifierReceiver
|
||||
{
|
||||
private readonly MethodSignature<Type> signature;
|
||||
|
||||
public FunctionPointerType(Context cx, MethodSignature<Type> signature) : base(cx)
|
||||
{
|
||||
this.signature = signature;
|
||||
}
|
||||
|
||||
public override CilTypeKind Kind => CilTypeKind.FunctionPointer;
|
||||
|
||||
public override string Name
|
||||
{
|
||||
get
|
||||
{
|
||||
using var id = new StringWriter();
|
||||
WriteName(
|
||||
id.Write,
|
||||
t => id.Write(t.Name),
|
||||
signature
|
||||
);
|
||||
return id.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
public override Namespace? ContainingNamespace => Cx.GlobalNamespace;
|
||||
|
||||
public override Type? ContainingType => null;
|
||||
|
||||
public override int ThisTypeParameterCount => throw new System.NotImplementedException();
|
||||
|
||||
public override IEnumerable<Type> TypeParameters => throw new System.NotImplementedException();
|
||||
|
||||
public override Type Construct(IEnumerable<Type> typeArguments) => throw new System.NotImplementedException();
|
||||
|
||||
public override void WriteAssemblyPrefix(TextWriter trapFile) { }
|
||||
|
||||
public override void WriteId(TextWriter trapFile, bool inContext)
|
||||
{
|
||||
WriteName(
|
||||
trapFile.Write,
|
||||
t => t.WriteId(trapFile, inContext),
|
||||
signature
|
||||
);
|
||||
}
|
||||
|
||||
internal static void WriteName<TType>(Action<string> write, Action<TType> writeType, MethodSignature<TType> signature)
|
||||
{
|
||||
write("delegate* ");
|
||||
write(GetCallingConvention(signature.Header.CallingConvention));
|
||||
write("<");
|
||||
foreach (var pt in signature.ParameterTypes)
|
||||
{
|
||||
writeType(pt);
|
||||
write(",");
|
||||
}
|
||||
writeType(signature.ReturnType);
|
||||
write(">");
|
||||
}
|
||||
|
||||
internal static string GetCallingConvention(SignatureCallingConvention callingConvention)
|
||||
{
|
||||
if (callingConvention == SignatureCallingConvention.Default)
|
||||
{
|
||||
return "managed";
|
||||
}
|
||||
|
||||
if (callingConvention == SignatureCallingConvention.Unmanaged)
|
||||
{
|
||||
return "unmanaged";
|
||||
}
|
||||
|
||||
return $"unmanaged[{callingConvention}]";
|
||||
}
|
||||
|
||||
public override IEnumerable<IExtractionProduct> Contents
|
||||
{
|
||||
get
|
||||
{
|
||||
foreach (var c in base.Contents)
|
||||
{
|
||||
yield return c;
|
||||
}
|
||||
|
||||
var retType = signature.ReturnType;
|
||||
if (retType is ModifiedType mt)
|
||||
{
|
||||
retType = mt.Unmodified;
|
||||
yield return Tuples.cil_custom_modifiers(this, mt.Modifier, mt.IsRequired);
|
||||
}
|
||||
yield return Tuples.cil_function_pointer_return_type(this, retType);
|
||||
|
||||
yield return Tuples.cil_function_pointer_calling_conventions(this, signature.Header.CallingConvention);
|
||||
|
||||
var i = 0;
|
||||
foreach (var p in signature.ParameterTypes)
|
||||
{
|
||||
var t = p;
|
||||
if (t is ModifiedType mtparam)
|
||||
{
|
||||
t = mtparam.Unmodified;
|
||||
yield return Tuples.cil_custom_modifiers(this, mtparam.Modifier, mtparam.IsRequired);
|
||||
}
|
||||
yield return Cx.Populate(new Parameter(Cx, this, i++, t));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace Semmle.Extraction.CIL.Entities
|
||||
{
|
||||
internal interface IParameterizable : IEntity
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -9,7 +9,7 @@ namespace Semmle.Extraction.CIL.Entities
|
||||
/// <summary>
|
||||
/// A method entity.
|
||||
/// </summary>
|
||||
internal abstract class Method : TypeContainer, IMember, ICustomModifierReceiver
|
||||
internal abstract class Method : TypeContainer, IMember, ICustomModifierReceiver, IParameterizable
|
||||
{
|
||||
protected MethodTypeParameter[]? genericParams;
|
||||
protected GenericContext gc;
|
||||
|
||||
@@ -37,6 +37,13 @@ namespace Semmle.Extraction.CIL.Entities
|
||||
|
||||
public override void WriteAssemblyPrefix(TextWriter trapFile) => throw new NotImplementedException();
|
||||
|
||||
public override void WriteId(TextWriter trapFile, bool inContext) => throw new NotImplementedException();
|
||||
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,11 +8,11 @@ namespace Semmle.Extraction.CIL.Entities
|
||||
/// </summary>
|
||||
internal sealed class Parameter : LabelledEntity
|
||||
{
|
||||
private readonly Method method;
|
||||
private readonly IParameterizable method;
|
||||
private readonly int index;
|
||||
private readonly Type type;
|
||||
|
||||
public Parameter(Context cx, Method m, int i, Type t) : base(cx)
|
||||
public Parameter(Context cx, IParameterizable m, int i, Type t) : base(cx)
|
||||
{
|
||||
method = m;
|
||||
index = i;
|
||||
|
||||
@@ -48,10 +48,20 @@ namespace Semmle.Extraction.CIL.Entities
|
||||
|
||||
private struct FnPtr : ITypeSignature
|
||||
{
|
||||
private readonly MethodSignature<ITypeSignature> signature;
|
||||
|
||||
public FnPtr(MethodSignature<ITypeSignature> signature)
|
||||
{
|
||||
this.signature = signature;
|
||||
}
|
||||
|
||||
public void WriteId(TextWriter trapFile, GenericContext gc)
|
||||
{
|
||||
trapFile.Write("<method signature>");
|
||||
FunctionPointerType.WriteName(
|
||||
trapFile.Write,
|
||||
t => t.WriteId(trapFile, gc),
|
||||
signature
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,7 +72,7 @@ namespace Semmle.Extraction.CIL.Entities
|
||||
new ByRef(elementType);
|
||||
|
||||
ITypeSignature ISignatureTypeProvider<ITypeSignature, object>.GetFunctionPointerType(MethodSignature<ITypeSignature> signature) =>
|
||||
new FnPtr();
|
||||
new FnPtr(signature);
|
||||
|
||||
private class Instantiation : ITypeSignature
|
||||
{
|
||||
|
||||
@@ -23,7 +23,7 @@ namespace Semmle.Extraction.CIL.Entities
|
||||
elementType; // ??
|
||||
|
||||
Type ISignatureTypeProvider<Type, GenericContext>.GetFunctionPointerType(MethodSignature<Type> signature) =>
|
||||
cx.ErrorType; // Don't know what to do !!
|
||||
cx.Populate(new FunctionPointerType(cx, signature));
|
||||
|
||||
Type IConstructedTypeProvider<Type>.GetGenericInstantiation(Type genericType, ImmutableArray<Type> typeArguments) =>
|
||||
genericType.Construct(typeArguments);
|
||||
|
||||
@@ -86,6 +86,12 @@ namespace Semmle.Extraction.CIL
|
||||
internal static Tuple cil_method(Method method, string name, Type declType, Type returnType) =>
|
||||
new Tuple("cil_method", method, name, declType, returnType);
|
||||
|
||||
internal static Tuple cil_function_pointer_return_type(FunctionPointerType fnptr, Type returnType) =>
|
||||
new Tuple("cil_function_pointer_return_type", fnptr, returnType);
|
||||
|
||||
internal static Tuple cil_function_pointer_calling_conventions(FunctionPointerType fnptr, System.Reflection.Metadata.SignatureCallingConvention callingConvention) =>
|
||||
new Tuple("cil_function_pointer_calling_conventions", fnptr, (int)callingConvention);
|
||||
|
||||
internal static Tuple cil_method_implementation(MethodImplementation impl, Method method, Assembly assembly) =>
|
||||
new Tuple("cil_method_implementation", impl, method, assembly);
|
||||
|
||||
@@ -101,7 +107,7 @@ namespace Semmle.Extraction.CIL
|
||||
internal static Tuple cil_newslot(Method method) =>
|
||||
new Tuple("cil_newslot", method);
|
||||
|
||||
internal static Tuple cil_parameter(Parameter p, Method m, int i, Type t) =>
|
||||
internal static Tuple cil_parameter(Parameter p, IParameterizable m, int i, Type t) =>
|
||||
new Tuple("cil_parameter", p, m, i, t);
|
||||
|
||||
internal static Tuple cil_parameter_in(Parameter p) =>
|
||||
|
||||
Reference in New Issue
Block a user