mirror of
https://github.com/github/codeql.git
synced 2025-12-16 16:53:25 +01:00
Merge pull request #15884 from michaelnebel/csharp/cleanupcil
C#: CIL and Dotnet cleanup (removal).
This commit is contained in:
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,2 @@
|
||||
description: Add `cil` and `dotnet` related relations and types.
|
||||
compatibility: backwards
|
||||
@@ -144,50 +144,5 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
public override bool NeedsPopulation => Context.Defines(Symbol);
|
||||
|
||||
public Extraction.Entities.Location Location => Context.CreateLocation(ReportingLocation);
|
||||
|
||||
protected void PopulateMetadataHandle(TextWriter trapFile)
|
||||
{
|
||||
var handle = MetadataHandle;
|
||||
|
||||
if (handle.HasValue)
|
||||
trapFile.metadata_handle(this, Location, MetadataTokens.GetToken(handle.Value));
|
||||
}
|
||||
|
||||
private static System.Reflection.PropertyInfo? GetPropertyInfo(object o, string name)
|
||||
{
|
||||
return o.GetType().GetProperty(name, System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.GetProperty);
|
||||
}
|
||||
|
||||
public Handle? MetadataHandle
|
||||
{
|
||||
get
|
||||
{
|
||||
var handleProp = GetPropertyInfo(Symbol, "Handle");
|
||||
object handleObj = Symbol;
|
||||
|
||||
if (handleProp is null)
|
||||
{
|
||||
var underlyingSymbolProp = GetPropertyInfo(Symbol, "UnderlyingSymbol");
|
||||
if (underlyingSymbolProp?.GetValue(Symbol) is object underlying)
|
||||
{
|
||||
handleProp = GetPropertyInfo(underlying, "Handle");
|
||||
handleObj = underlying;
|
||||
}
|
||||
}
|
||||
|
||||
if (handleProp is not null)
|
||||
{
|
||||
switch (handleProp.GetValue(handleObj))
|
||||
{
|
||||
case MethodDefinitionHandle md: return md;
|
||||
case TypeDefinitionHandle td: return td;
|
||||
case PropertyDefinitionHandle pd: return pd;
|
||||
case FieldDefinitionHandle fd: return fd;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,6 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
|
||||
public override void Populate(TextWriter trapFile)
|
||||
{
|
||||
PopulateMetadataHandle(trapFile);
|
||||
PopulateAttributes();
|
||||
ContainingType!.PopulateGenerics();
|
||||
PopulateNullability(trapFile, Symbol.GetAnnotatedType());
|
||||
|
||||
@@ -360,7 +360,6 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
PopulateParameters();
|
||||
PopulateMethodBody(trapFile);
|
||||
PopulateGenerics(trapFile);
|
||||
PopulateMetadataHandle(trapFile);
|
||||
PopulateNullability(trapFile, Symbol.GetAnnotatedReturnType());
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +34,6 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
|
||||
public override void Populate(TextWriter trapFile)
|
||||
{
|
||||
PopulateMetadataHandle(trapFile);
|
||||
PopulateAttributes();
|
||||
PopulateModifiers(trapFile);
|
||||
BindComments();
|
||||
|
||||
@@ -77,7 +77,6 @@ namespace Semmle.Extraction.CSharp.Entities
|
||||
|
||||
protected void PopulateType(TextWriter trapFile, bool constructUnderlyingTupleType = false)
|
||||
{
|
||||
PopulateMetadataHandle(trapFile);
|
||||
PopulateAttributes();
|
||||
|
||||
trapFile.Write("types(");
|
||||
|
||||
@@ -233,9 +233,6 @@ namespace Semmle.Extraction.CSharp
|
||||
internal static void localvars(this TextWriter trapFile, LocalVariable key, VariableKind kind, string name, int @var, Type type, Expression expr) =>
|
||||
trapFile.WriteTuple("localvars", key, (int)kind, name, @var, type, expr);
|
||||
|
||||
public static void metadata_handle(this TextWriter trapFile, IEntity entity, Location assembly, int handleValue) =>
|
||||
trapFile.WriteTuple("metadata_handle", entity, assembly, handleValue);
|
||||
|
||||
internal static void method_location(this TextWriter trapFile, Method method, Location location) =>
|
||||
trapFile.WriteTuple("method_location", method, location);
|
||||
|
||||
|
||||
4
csharp/ql/lib/change-notes/2024-09-16-delete-cil.md
Normal file
4
csharp/ql/lib/change-notes/2024-09-16-delete-cil.md
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: breaking
|
||||
---
|
||||
* C#: Remove all CIL tables and related QL library functionality.
|
||||
@@ -1,5 +0,0 @@
|
||||
/**
|
||||
* The default QL library for modeling the Common Intermediate Language (CIL).
|
||||
*/
|
||||
|
||||
import semmle.code.cil.CIL as CIL
|
||||
@@ -1,5 +0,0 @@
|
||||
/**
|
||||
* The default QL library for modeling .NET definitions for both C# and CIL code.
|
||||
*/
|
||||
|
||||
deprecated import semmle.code.dotnet.DotNet as DotNet
|
||||
@@ -1,98 +0,0 @@
|
||||
/**
|
||||
* Provides classes for accesses.
|
||||
*
|
||||
* An access is any read or write of a variable.
|
||||
*/
|
||||
|
||||
private import CIL
|
||||
|
||||
/** An instruction that accesses a variable. */
|
||||
deprecated class Access extends Instruction, @cil_access {
|
||||
/** Gets the declaration referenced by this instruction. */
|
||||
Variable getTarget() { cil_access(this, result) }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that accesses a variable.
|
||||
* This class is provided for consistency with the C# data model.
|
||||
*/
|
||||
deprecated class VariableAccess extends Access, @cil_access { }
|
||||
|
||||
/** An instruction that reads a variable. */
|
||||
deprecated class ReadAccess extends VariableAccess, Expr, @cil_read_access {
|
||||
override Type getType() { result = this.getTarget().getType() }
|
||||
}
|
||||
|
||||
/** An instruction yielding an address. */
|
||||
deprecated class ReadRef extends Expr, @cil_read_ref { }
|
||||
|
||||
/** An instruction that reads the address of a variable. */
|
||||
deprecated class ReadRefAccess extends ReadAccess, ReadRef { }
|
||||
|
||||
/** An instruction that writes a variable. */
|
||||
deprecated class WriteAccess extends VariableAccess, @cil_write_access {
|
||||
/** Gets the expression whose value is used in this variable write. */
|
||||
Expr getExpr() { none() }
|
||||
}
|
||||
|
||||
/** An instruction that accesses a parameter. */
|
||||
deprecated class ParameterAccess extends StackVariableAccess, @cil_arg_access {
|
||||
override MethodParameter getTarget() { result = StackVariableAccess.super.getTarget() }
|
||||
}
|
||||
|
||||
/** An instruction that reads a parameter. */
|
||||
deprecated class ParameterReadAccess extends ParameterAccess, ReadAccess {
|
||||
override int getPopCount() { result = 0 }
|
||||
}
|
||||
|
||||
/** An instruction that writes to a parameter. */
|
||||
deprecated class ParameterWriteAccess extends ParameterAccess, WriteAccess {
|
||||
override int getPopCount() { result = 1 }
|
||||
|
||||
override Expr getExpr() { result = this.getOperand(0) }
|
||||
}
|
||||
|
||||
/** An access to the `this` parameter. */
|
||||
deprecated class ThisAccess extends ParameterReadAccess {
|
||||
ThisAccess() { this.getTarget() instanceof ThisParameter }
|
||||
}
|
||||
|
||||
/** An instruction that accesses a stack variable. */
|
||||
deprecated class StackVariableAccess extends VariableAccess, @cil_stack_access {
|
||||
override StackVariable getTarget() { result = VariableAccess.super.getTarget() }
|
||||
}
|
||||
|
||||
/** An instruction that accesses a local variable. */
|
||||
deprecated class LocalVariableAccess extends StackVariableAccess, @cil_local_access {
|
||||
override LocalVariable getTarget() { result = StackVariableAccess.super.getTarget() }
|
||||
}
|
||||
|
||||
/** An instruction that writes to a local variable. */
|
||||
deprecated class LocalVariableWriteAccess extends LocalVariableAccess, WriteAccess {
|
||||
override int getPopCount() { result = 1 }
|
||||
|
||||
override Expr getExpr() { result = this.getOperand(0) }
|
||||
|
||||
override string getExtra() { result = "L" + this.getTarget().getIndex() }
|
||||
}
|
||||
|
||||
/** An instruction that reads a local variable. */
|
||||
deprecated class LocalVariableReadAccess extends LocalVariableAccess, ReadAccess {
|
||||
override int getPopCount() { result = 0 }
|
||||
}
|
||||
|
||||
/** An instruction that accesses a field. */
|
||||
deprecated class FieldAccess extends VariableAccess, @cil_field_access {
|
||||
override Field getTarget() { result = VariableAccess.super.getTarget() }
|
||||
|
||||
override string getExtra() { result = this.getTarget().getName() }
|
||||
|
||||
/** Gets the qualifier of the access, if any. */
|
||||
abstract Expr getQualifier();
|
||||
}
|
||||
|
||||
/** An instruction that reads a field. */
|
||||
abstract deprecated class FieldReadAccess extends FieldAccess, ReadAccess { }
|
||||
|
||||
/** An instruction that writes a field. */
|
||||
abstract deprecated class FieldWriteAccess extends FieldAccess, WriteAccess { }
|
||||
@@ -1,45 +0,0 @@
|
||||
/** Provides the `Attribute` class. */
|
||||
|
||||
private import CIL
|
||||
private import semmle.code.csharp.Location as CS
|
||||
|
||||
/** An attribute to a declaration, such as a method, field, type or parameter. */
|
||||
deprecated class Attribute extends Element, @cil_attribute {
|
||||
/** Gets the declaration this attribute is attached to. */
|
||||
Declaration getDeclaration() { cil_attribute(this, result, _) }
|
||||
|
||||
/** Gets the constructor used to construct this attribute. */
|
||||
Method getConstructor() { cil_attribute(this, _, result) }
|
||||
|
||||
/** Gets the type of this attribute. */
|
||||
Type getType() { result = this.getConstructor().getDeclaringType() }
|
||||
|
||||
override string toString() { result = "[" + this.getType().getName() + "(...)]" }
|
||||
|
||||
/** Gets the value of the `i`th argument of this attribute. */
|
||||
string getArgument(int i) { cil_attribute_positional_argument(this, i, result) }
|
||||
|
||||
/** Gets the value of the named argument `name`. */
|
||||
string getNamedArgument(string name) { cil_attribute_named_argument(this, name, result) }
|
||||
|
||||
/** Gets an argument of this attribute, if any. */
|
||||
string getAnArgument() { result = this.getArgument(_) or result = this.getNamedArgument(_) }
|
||||
|
||||
override CS::Location getLocation() { result = this.getDeclaration().getLocation() }
|
||||
}
|
||||
|
||||
/** A generic attribute to a declaration. */
|
||||
deprecated class GenericAttribute extends Attribute {
|
||||
private ConstructedType type;
|
||||
|
||||
GenericAttribute() { type = this.getType() }
|
||||
|
||||
/** Gets the total number of type arguments. */
|
||||
int getNumberOfTypeArguments() { result = count(int i | cil_type_argument(type, i, _)) }
|
||||
|
||||
/** Gets the `i`th type argument, if any. */
|
||||
Type getTypeArgument(int i) { result = type.getTypeArgument(i) }
|
||||
|
||||
/** Get a type argument. */
|
||||
Type getATypeArgument() { result = this.getTypeArgument(_) }
|
||||
}
|
||||
@@ -1,401 +0,0 @@
|
||||
/**
|
||||
* Provides classes representing basic blocks.
|
||||
*/
|
||||
|
||||
private import CIL
|
||||
|
||||
/**
|
||||
* A basic block, that is, a maximal straight-line sequence of control flow nodes
|
||||
* without branches or joins.
|
||||
*/
|
||||
deprecated class BasicBlock extends Cached::TBasicBlockStart {
|
||||
/** Gets an immediate successor of this basic block, if any. */
|
||||
BasicBlock getASuccessor() { result.getFirstNode() = this.getLastNode().getASuccessor() }
|
||||
|
||||
/** Gets an immediate predecessor of this basic block, if any. */
|
||||
BasicBlock getAPredecessor() { result.getASuccessor() = this }
|
||||
|
||||
/**
|
||||
* Gets an immediate `true` successor, if any.
|
||||
*
|
||||
* An immediate `true` successor is a successor that is reached when
|
||||
* the condition that ends this basic block evaluates to `true`.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```csharp
|
||||
* if (x < 0)
|
||||
* x = -x;
|
||||
* ```
|
||||
*
|
||||
* The basic block on line 2 is an immediate `true` successor of the
|
||||
* basic block on line 1.
|
||||
*/
|
||||
BasicBlock getATrueSuccessor() { result.getFirstNode() = this.getLastNode().getTrueSuccessor() }
|
||||
|
||||
/**
|
||||
* Gets an immediate `false` successor, if any.
|
||||
*
|
||||
* An immediate `false` successor is a successor that is reached when
|
||||
* the condition that ends this basic block evaluates to `false`.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```csharp
|
||||
* if (!(x >= 0))
|
||||
* x = -x;
|
||||
* ```
|
||||
*
|
||||
* The basic block on line 2 is an immediate `false` successor of the
|
||||
* basic block on line 1.
|
||||
*/
|
||||
BasicBlock getAFalseSuccessor() { result.getFirstNode() = this.getLastNode().getFalseSuccessor() }
|
||||
|
||||
/** Gets the control flow node at a specific (zero-indexed) position in this basic block. */
|
||||
ControlFlowNode getNode(int pos) { Cached::bbIndex(this.getFirstNode(), result, pos) }
|
||||
|
||||
/** Gets a control flow node in this basic block. */
|
||||
ControlFlowNode getANode() { result = this.getNode(_) }
|
||||
|
||||
/** Gets the first control flow node in this basic block. */
|
||||
ControlFlowNode getFirstNode() { this = Cached::TBasicBlockStart(result) }
|
||||
|
||||
/** Gets the last control flow node in this basic block. */
|
||||
ControlFlowNode getLastNode() { result = this.getNode(this.length() - 1) }
|
||||
|
||||
/** Gets the length of this basic block. */
|
||||
int length() { result = strictcount(this.getANode()) }
|
||||
|
||||
/**
|
||||
* Holds if this basic block strictly dominates basic block `bb`.
|
||||
*
|
||||
* That is, all paths reaching basic block `bb` from some entry point
|
||||
* basic block must go through this basic block (which must be different
|
||||
* from `bb`).
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```csharp
|
||||
* int M(string s) {
|
||||
* if (s == null)
|
||||
* throw new ArgumentNullException(nameof(s));
|
||||
* return s.Length;
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* The basic block starting on line 2 strictly dominates the
|
||||
* basic block on line 4 (all paths from the entry point of `M`
|
||||
* to `return s.Length;` must go through the null check).
|
||||
*/
|
||||
predicate strictlyDominates(BasicBlock bb) { bbIDominates+(this, bb) }
|
||||
|
||||
/**
|
||||
* Holds if this basic block dominates basic block `bb`.
|
||||
*
|
||||
* That is, all paths reaching basic block `bb` from some entry point
|
||||
* basic block must go through this basic block.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```csharp
|
||||
* int M(string s) {
|
||||
* if (s == null)
|
||||
* throw new ArgumentNullException(nameof(s));
|
||||
* return s.Length;
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* The basic block starting on line 2 dominates the basic
|
||||
* block on line 4 (all paths from the entry point of `M` to
|
||||
* `return s.Length;` must go through the null check).
|
||||
*
|
||||
* This predicate is *reflexive*, so for example `if (s == null)` dominates
|
||||
* itself.
|
||||
*/
|
||||
predicate dominates(BasicBlock bb) {
|
||||
bb = this or
|
||||
this.strictlyDominates(bb)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `df` is in the dominance frontier of this basic block.
|
||||
* That is, this basic block dominates a predecessor of `df`, but
|
||||
* does not dominate `df` itself.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```csharp
|
||||
* if (x < 0) {
|
||||
* x = -x;
|
||||
* if (x > 10)
|
||||
* x--;
|
||||
* }
|
||||
* Console.Write(x);
|
||||
* ```
|
||||
*
|
||||
* The basic block on line 6 is in the dominance frontier
|
||||
* of the basic block starting on line 2 because that block
|
||||
* dominates the basic block on line 4, which is a predecessor of
|
||||
* `Console.Write(x);`. Also, the basic block starting on line 2
|
||||
* does not dominate the basic block on line 6.
|
||||
*/
|
||||
predicate inDominanceFrontier(BasicBlock df) {
|
||||
this.dominatesPredecessor(df) and
|
||||
not this.strictlyDominates(df)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this basic block dominates a predecessor of `df`.
|
||||
*/
|
||||
private predicate dominatesPredecessor(BasicBlock df) { this.dominates(df.getAPredecessor()) }
|
||||
|
||||
/**
|
||||
* Gets the basic block that immediately dominates this basic block, if any.
|
||||
*
|
||||
* That is, all paths reaching this basic block from some entry point
|
||||
* basic block must go through the result, which is an immediate basic block
|
||||
* predecessor of this basic block.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```csharp
|
||||
* int M(string s) {
|
||||
* if (s == null)
|
||||
* throw new ArgumentNullException(nameof(s));
|
||||
* return s.Length;
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* The basic block starting on line 2 is an immediate dominator of
|
||||
* the basic block online 4 (all paths from the entry point of `M`
|
||||
* to `return s.Length;` must go through the null check, and the null check
|
||||
* is an immediate predecessor of `return s.Length;`).
|
||||
*/
|
||||
BasicBlock getImmediateDominator() { bbIDominates(result, this) }
|
||||
|
||||
/**
|
||||
* Holds if this basic block strictly post-dominates basic block `bb`.
|
||||
*
|
||||
* That is, all paths reaching an exit point basic block from basic
|
||||
* block `bb` must go through this basic block (which must be different
|
||||
* from `bb`).
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```csharp
|
||||
* int M(string s) {
|
||||
* try {
|
||||
* return s.Length;
|
||||
* }
|
||||
* finally {
|
||||
* Console.WriteLine("M");
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* The basic block on line 6 strictly post-dominates the basic block on
|
||||
* line 3 (all paths to the exit point of `M` from `return s.Length;`
|
||||
* must go through the `WriteLine` call).
|
||||
*/
|
||||
predicate strictlyPostDominates(BasicBlock bb) { bbIPostDominates+(this, bb) }
|
||||
|
||||
/**
|
||||
* Holds if this basic block post-dominates basic block `bb`.
|
||||
*
|
||||
* That is, all paths reaching an exit point basic block from basic
|
||||
* block `bb` must go through this basic block.
|
||||
*
|
||||
* Example:
|
||||
*
|
||||
* ```csharp
|
||||
* int M(string s) {
|
||||
* try {
|
||||
* return s.Length;
|
||||
* }
|
||||
* finally {
|
||||
* Console.WriteLine("M");
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* The basic block on line 6 post-dominates the basic block on line 3
|
||||
* (all paths to the exit point of `M` from `return s.Length;` must go
|
||||
* through the `WriteLine` call).
|
||||
*
|
||||
* This predicate is *reflexive*, so for example `Console.WriteLine("M");`
|
||||
* post-dominates itself.
|
||||
*/
|
||||
predicate postDominates(BasicBlock bb) {
|
||||
this.strictlyPostDominates(bb) or
|
||||
this = bb
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this basic block is in a loop in the control flow graph. This
|
||||
* includes loops created by `goto` statements. This predicate may not hold
|
||||
* even if this basic block is syntactically inside a `while` loop if the
|
||||
* necessary back edges are unreachable.
|
||||
*/
|
||||
predicate inLoop() { this.getASuccessor+() = this }
|
||||
|
||||
/** Gets a textual representation of this basic block. */
|
||||
string toString() { result = this.getFirstNode().toString() }
|
||||
|
||||
/** Gets the location of this basic block. */
|
||||
Location getLocation() { result = this.getFirstNode().getLocation() }
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal implementation details.
|
||||
*/
|
||||
cached
|
||||
deprecated private module Cached {
|
||||
/** Internal representation of basic blocks. */
|
||||
cached
|
||||
newtype TBasicBlock = TBasicBlockStart(ControlFlowNode cfn) { startsBB(cfn) }
|
||||
|
||||
/** Holds if `cfn` starts a new basic block. */
|
||||
private predicate startsBB(ControlFlowNode cfn) {
|
||||
not exists(cfn.getAPredecessor()) and exists(cfn.getASuccessor())
|
||||
or
|
||||
cfn.isJoin()
|
||||
or
|
||||
cfn.getAPredecessor().isBranch()
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `succ` is a control flow successor of `pred` within
|
||||
* the same basic block.
|
||||
*/
|
||||
private predicate intraBBSucc(ControlFlowNode pred, ControlFlowNode succ) {
|
||||
succ = pred.getASuccessor() and
|
||||
not startsBB(succ)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `cfn` is the `i`th node in basic block `bb`.
|
||||
*
|
||||
* In other words, `i` is the shortest distance from a node `bb`
|
||||
* that starts a basic block to `cfn` along the `intraBBSucc` relation.
|
||||
*/
|
||||
cached
|
||||
predicate bbIndex(ControlFlowNode bbStart, ControlFlowNode cfn, int i) =
|
||||
shortestDistances(startsBB/1, intraBBSucc/2)(bbStart, cfn, i)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the first node of basic block `succ` is a control flow
|
||||
* successor of the last node of basic block `pred`.
|
||||
*/
|
||||
deprecated private predicate succBB(BasicBlock pred, BasicBlock succ) {
|
||||
succ = pred.getASuccessor()
|
||||
}
|
||||
|
||||
/** Holds if `dom` is an immediate dominator of `bb`. */
|
||||
deprecated predicate bbIDominates(BasicBlock dom, BasicBlock bb) =
|
||||
idominance(entryBB/1, succBB/2)(_, dom, bb)
|
||||
|
||||
/** Holds if `pred` is a basic block predecessor of `succ`. */
|
||||
deprecated private predicate predBB(BasicBlock succ, BasicBlock pred) { succBB(pred, succ) }
|
||||
|
||||
/** Holds if `dom` is an immediate post-dominator of `bb`. */
|
||||
deprecated predicate bbIPostDominates(BasicBlock dom, BasicBlock bb) =
|
||||
idominance(exitBB/1, predBB/2)(_, dom, bb)
|
||||
|
||||
/**
|
||||
* An entry basic block, that is, a basic block whose first node is
|
||||
* the entry node of a callable.
|
||||
*/
|
||||
deprecated class EntryBasicBlock extends BasicBlock {
|
||||
EntryBasicBlock() { entryBB(this) }
|
||||
}
|
||||
|
||||
/** Holds if `bb` is an entry basic block. */
|
||||
deprecated private predicate entryBB(BasicBlock bb) {
|
||||
bb.getFirstNode() instanceof MethodImplementation
|
||||
}
|
||||
|
||||
/**
|
||||
* An exit basic block, that is, a basic block whose last node is
|
||||
* an exit node.
|
||||
*/
|
||||
deprecated class ExitBasicBlock extends BasicBlock {
|
||||
ExitBasicBlock() { exitBB(this) }
|
||||
}
|
||||
|
||||
/** Holds if `bb` is an exit basic block. */
|
||||
deprecated private predicate exitBB(BasicBlock bb) { not exists(bb.getLastNode().getASuccessor()) }
|
||||
|
||||
/**
|
||||
* A basic block with more than one predecessor.
|
||||
*/
|
||||
deprecated class JoinBlock extends BasicBlock {
|
||||
JoinBlock() { this.getFirstNode().isJoin() }
|
||||
}
|
||||
|
||||
/** A basic block that terminates in a condition, splitting the subsequent control flow. */
|
||||
deprecated class ConditionBlock extends BasicBlock {
|
||||
ConditionBlock() {
|
||||
exists(BasicBlock succ |
|
||||
succ = this.getATrueSuccessor()
|
||||
or
|
||||
succ = this.getAFalseSuccessor()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if basic block `controlled` is controlled by this basic block with
|
||||
* Boolean value `testIsTrue`. That is, `controlled` can only be reached from
|
||||
* the callable entry point by going via the true edge (`testIsTrue = true`)
|
||||
* or false edge (`testIsTrue = false`) out of this basic block.
|
||||
*/
|
||||
predicate controls(BasicBlock controlled, boolean testIsTrue) {
|
||||
/*
|
||||
* For this block to control the block `controlled` with `testIsTrue` the following must be true:
|
||||
* Execution must have passed through the test i.e. `this` must strictly dominate `controlled`.
|
||||
* Execution must have passed through the `testIsTrue` edge leaving `this`.
|
||||
*
|
||||
* Although "passed through the true edge" implies that `this.getATrueSuccessor()` dominates `controlled`,
|
||||
* the reverse is not true, as flow may have passed through another edge to get to `this.getATrueSuccessor()`
|
||||
* so we need to assert that `this.getATrueSuccessor()` dominates `controlled` *and* that
|
||||
* all predecessors of `this.getATrueSuccessor()` are either `this` or dominated by `this.getATrueSuccessor()`.
|
||||
*
|
||||
* For example, in the following C# snippet:
|
||||
* ```csharp
|
||||
* if (x)
|
||||
* controlled;
|
||||
* false_successor;
|
||||
* uncontrolled;
|
||||
* ```
|
||||
* `false_successor` dominates `uncontrolled`, but not all of its predecessors are `this` (`if (x)`)
|
||||
* or dominated by itself. Whereas in the following code:
|
||||
* ```csharp
|
||||
* if (x)
|
||||
* while (controlled)
|
||||
* also_controlled;
|
||||
* false_successor;
|
||||
* uncontrolled;
|
||||
* ```
|
||||
* the block `while controlled` is controlled because all of its predecessors are `this` (`if (x)`)
|
||||
* or (in the case of `also_controlled`) dominated by itself.
|
||||
*
|
||||
* The additional constraint on the predecessors of the test successor implies
|
||||
* that `this` strictly dominates `controlled` so that isn't necessary to check
|
||||
* directly.
|
||||
*/
|
||||
|
||||
exists(BasicBlock succ |
|
||||
this.isCandidateSuccessor(succ, testIsTrue) and
|
||||
succ.dominates(controlled)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate isCandidateSuccessor(BasicBlock succ, boolean testIsTrue) {
|
||||
(
|
||||
testIsTrue = true and succ = this.getATrueSuccessor()
|
||||
or
|
||||
testIsTrue = false and succ = this.getAFalseSuccessor()
|
||||
) and
|
||||
forall(BasicBlock pred | pred = succ.getAPredecessor() and pred != this | succ.dominates(pred))
|
||||
}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
/** Provides the core CIL data model. */
|
||||
|
||||
import semmle.code.csharp.Location
|
||||
import Element
|
||||
import Instruction
|
||||
import Instructions
|
||||
import Access
|
||||
import Variable
|
||||
import Declaration
|
||||
import Generics
|
||||
import Type
|
||||
import Types
|
||||
import Method
|
||||
import InstructionGroups
|
||||
import BasicBlock
|
||||
import Handler
|
||||
import ControlFlow
|
||||
import DataFlow
|
||||
import Attribute
|
||||
import Stubs
|
||||
import CustomModifierReceiver
|
||||
import Parameterizable
|
||||
import semmle.code.cil.Ssa
|
||||
@@ -1,74 +0,0 @@
|
||||
/**
|
||||
* Provides predicates for analysing the return values of callables.
|
||||
*/
|
||||
|
||||
private import CIL
|
||||
|
||||
cached
|
||||
private module Cached {
|
||||
/** Holds if method `m` always returns null. */
|
||||
cached
|
||||
deprecated predicate alwaysNullMethod(Method m) {
|
||||
forex(Expr e | m.canReturn(e) | alwaysNullExpr(e))
|
||||
}
|
||||
|
||||
/** Holds if method `m` always returns non-null. */
|
||||
cached
|
||||
deprecated predicate alwaysNotNullMethod(Method m) {
|
||||
forex(Expr e | m.canReturn(e) | alwaysNotNullExpr(e))
|
||||
}
|
||||
|
||||
/** Holds if method `m` always throws an exception. */
|
||||
cached
|
||||
deprecated predicate alwaysThrowsMethod(Method m) {
|
||||
m.hasBody() and
|
||||
not exists(m.getImplementation().getAnInstruction().(Return))
|
||||
}
|
||||
|
||||
/** Holds if method `m` always throws an exception of type `t`. */
|
||||
cached
|
||||
deprecated predicate alwaysThrowsException(Method m, Type t) {
|
||||
alwaysThrowsMethod(m) and
|
||||
forex(Throw ex | ex = m.getImplementation().getAnInstruction() | t = ex.getExceptionType())
|
||||
}
|
||||
}
|
||||
|
||||
import Cached
|
||||
|
||||
pragma[noinline]
|
||||
deprecated private predicate alwaysNullVariableUpdate(VariableUpdate vu) {
|
||||
forex(Expr src | src = vu.getSource() | alwaysNullExpr(src))
|
||||
}
|
||||
|
||||
/** Holds if expression `expr` always evaluates to `null`. */
|
||||
deprecated private predicate alwaysNullExpr(Expr expr) {
|
||||
expr instanceof NullLiteral
|
||||
or
|
||||
alwaysNullMethod(expr.(StaticCall).getTarget())
|
||||
or
|
||||
forex(Ssa::Definition def |
|
||||
expr = any(Ssa::Definition def0 | def = def0.getAnUltimateDefinition()).getARead()
|
||||
|
|
||||
alwaysNullVariableUpdate(def.getVariableUpdate())
|
||||
)
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
deprecated private predicate alwaysNotNullVariableUpdate(VariableUpdate vu) {
|
||||
forex(Expr src | src = vu.getSource() | alwaysNotNullExpr(src))
|
||||
}
|
||||
|
||||
/** Holds if expression `expr` always evaluates to non-null. */
|
||||
deprecated private predicate alwaysNotNullExpr(Expr expr) {
|
||||
expr instanceof Opcodes::NewObj
|
||||
or
|
||||
expr instanceof Literal and not expr instanceof NullLiteral
|
||||
or
|
||||
alwaysNotNullMethod(expr.(StaticCall).getTarget())
|
||||
or
|
||||
forex(Ssa::Definition def |
|
||||
expr = any(Ssa::Definition def0 | def = def0.getAnUltimateDefinition()).getARead()
|
||||
|
|
||||
alwaysNotNullVariableUpdate(def.getVariableUpdate())
|
||||
)
|
||||
}
|
||||
@@ -1,787 +0,0 @@
|
||||
/**
|
||||
* Provides checks for the consistency of the data model and database.
|
||||
*/
|
||||
|
||||
private import CIL
|
||||
private import csharp as CS
|
||||
private import semmle.code.csharp.commons.QualifiedName
|
||||
|
||||
private newtype ConsistencyCheck =
|
||||
MissingEntityCheck() or
|
||||
deprecated TypeCheck(Type t) or
|
||||
deprecated CfgCheck(ControlFlowNode n) or
|
||||
deprecated DeclarationCheck(Declaration d) or
|
||||
MissingCSharpCheck(CS::Declaration d)
|
||||
|
||||
/**
|
||||
* A consistency violation in the database or data model.
|
||||
*/
|
||||
abstract deprecated class ConsistencyViolation extends ConsistencyCheck {
|
||||
abstract string toString();
|
||||
|
||||
abstract string getMessage();
|
||||
}
|
||||
|
||||
/**
|
||||
* A check that is deliberately disabled.
|
||||
*/
|
||||
abstract deprecated class DisabledCheck extends ConsistencyViolation {
|
||||
DisabledCheck() { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A consistency violation on a control flow node.
|
||||
*/
|
||||
abstract deprecated class CfgViolation extends ConsistencyViolation, CfgCheck {
|
||||
ControlFlowNode node;
|
||||
|
||||
CfgViolation() { this = CfgCheck(node) }
|
||||
|
||||
override string toString() { result = node.toString() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A consistency violation in a specific instruction.
|
||||
*/
|
||||
abstract deprecated class InstructionViolation extends CfgViolation, CfgCheck {
|
||||
Instruction instruction;
|
||||
|
||||
InstructionViolation() { this = CfgCheck(instruction) }
|
||||
|
||||
private string getInstructionsUpTo() {
|
||||
result =
|
||||
concat(Instruction i |
|
||||
i.getIndex() <= instruction.getIndex() and
|
||||
i.getImplementation() = instruction.getImplementation()
|
||||
|
|
||||
i.toString() + " [push: " + i.getPushCount() + ", pop: " + i.getPopCount() + "]", "; "
|
||||
order by
|
||||
i.getIndex()
|
||||
)
|
||||
}
|
||||
|
||||
override string toString() {
|
||||
result =
|
||||
instruction.getImplementation().getMethod().toStringWithTypes() + ": " +
|
||||
instruction.toString() + ", " + this.getInstructionsUpTo()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A literal that does not have exactly one `getValue()`.
|
||||
*/
|
||||
deprecated class MissingValue extends InstructionViolation {
|
||||
MissingValue() { exists(Literal l | l = instruction | count(l.getValue()) != 1) }
|
||||
|
||||
override string getMessage() { result = "Literal has invalid getValue()" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A call that does not have exactly one `getTarget()`.
|
||||
*/
|
||||
deprecated class MissingCallTarget extends InstructionViolation {
|
||||
MissingCallTarget() {
|
||||
exists(Call c | c = instruction |
|
||||
count(c.getTarget()) != 1 and not c instanceof Opcodes::Calli
|
||||
or
|
||||
count(c.(Opcodes::Calli).getTargetType()) != 1 and c instanceof Opcodes::Calli
|
||||
)
|
||||
}
|
||||
|
||||
override string getMessage() { result = "Call has invalid target" }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that has not been assigned a specific QL class.
|
||||
*/
|
||||
deprecated class MissingOpCode extends InstructionViolation {
|
||||
MissingOpCode() { not exists(instruction.getOpcodeName()) }
|
||||
|
||||
override string getMessage() {
|
||||
result = "Opcode " + instruction.getOpcode() + " is missing a QL class"
|
||||
}
|
||||
|
||||
override string toString() {
|
||||
result = "Unknown instruction in " + instruction.getImplementation().getMethod().toString()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that is missing an operand. It means that there is no instruction which pushes
|
||||
* a value onto the stack for this instruction to pop.
|
||||
*
|
||||
* If this fails, it means that the `getPopCount`/`getPushCount`/control flow graph has failed.
|
||||
* It could also mean that the target of a call has failed and has not determined the
|
||||
* correct number of arguments.
|
||||
*/
|
||||
deprecated class MissingOperand extends InstructionViolation {
|
||||
MissingOperand() {
|
||||
exists(int op | op in [0 .. instruction.getPopCount() - 1] |
|
||||
not exists(instruction.getOperand(op)) and not instruction instanceof DeadInstruction
|
||||
)
|
||||
}
|
||||
|
||||
int getMissingOperand() {
|
||||
result in [0 .. instruction.getPopCount() - 1] and
|
||||
not exists(instruction.getOperand(result))
|
||||
}
|
||||
|
||||
override string getMessage() {
|
||||
result = "This instruction is missing operand " + this.getMissingOperand()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A dead instruction, not reachable from any entry point.
|
||||
* These should not exist, however it turns out that the Mono compiler sometimes
|
||||
* emits them.
|
||||
*/
|
||||
deprecated class DeadInstruction extends Instruction {
|
||||
DeadInstruction() { not exists(EntryPoint e | e.getASuccessor+() = this) }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that is not reachable from any entry point.
|
||||
*
|
||||
* If this fails, it means that the calculation of the call graph is incorrect.
|
||||
* Disabled, because Mono compiler sometimes emits dead instructions.
|
||||
*/
|
||||
deprecated class DeadInstructionViolation extends InstructionViolation, DisabledCheck {
|
||||
DeadInstructionViolation() { instruction instanceof DeadInstruction }
|
||||
|
||||
override string getMessage() { result = "This instruction is not reachable" }
|
||||
}
|
||||
|
||||
deprecated class YesNoBranch extends ConditionalBranch {
|
||||
YesNoBranch() { not this instanceof Opcodes::Switch }
|
||||
}
|
||||
|
||||
/**
|
||||
* A branch instruction that does not have exactly 2 successors.
|
||||
*/
|
||||
deprecated class InvalidBranchSuccessors extends InstructionViolation {
|
||||
InvalidBranchSuccessors() {
|
||||
// Mono compiler sometimes generates branches to the next instruction, which is just wrong.
|
||||
// However it is valid CIL.
|
||||
exists(YesNoBranch i | i = instruction | not count(i.getASuccessor()) in [1 .. 2])
|
||||
}
|
||||
|
||||
override string getMessage() {
|
||||
result = "Conditional branch has " + count(instruction.getASuccessor()) + " successors"
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that has a true/false successor but is not a branch.
|
||||
*/
|
||||
deprecated class OnlyYesNoBranchHasTrueFalseSuccessors extends InstructionViolation {
|
||||
OnlyYesNoBranchHasTrueFalseSuccessors() {
|
||||
(exists(instruction.getTrueSuccessor()) or exists(instruction.getFalseSuccessor())) and
|
||||
not instruction instanceof YesNoBranch
|
||||
}
|
||||
|
||||
override string getMessage() { result = "This instruction has getTrue/FalseSuccessor()" }
|
||||
}
|
||||
|
||||
/**
|
||||
* An unconditional branch instruction that has more than one successor.
|
||||
*/
|
||||
deprecated class UnconditionalBranchSuccessors extends InstructionViolation {
|
||||
UnconditionalBranchSuccessors() {
|
||||
exists(UnconditionalBranch i | i = instruction | count(i.getASuccessor()) != 1)
|
||||
}
|
||||
|
||||
override string getMessage() {
|
||||
result = "Unconditional branch has " + count(instruction.getASuccessor()) + " successors"
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A branch instruction that does not have a true successor.
|
||||
*/
|
||||
deprecated class NoTrueSuccessor extends InstructionViolation {
|
||||
NoTrueSuccessor() { exists(YesNoBranch i | i = instruction | not exists(i.getTrueSuccessor())) }
|
||||
|
||||
override string getMessage() { result = "Missing a true successor" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A branch instruction that does not have a false successor.
|
||||
*/
|
||||
deprecated class NoFalseSuccessor extends InstructionViolation {
|
||||
NoFalseSuccessor() { exists(YesNoBranch i | i = instruction | not exists(i.getFalseSuccessor())) }
|
||||
|
||||
override string getMessage() { result = "Missing a false successor" }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction whose true successor is not a successor.
|
||||
*/
|
||||
deprecated class TrueSuccessorIsSuccessor extends InstructionViolation {
|
||||
TrueSuccessorIsSuccessor() {
|
||||
exists(instruction.getTrueSuccessor()) and
|
||||
not instruction.getTrueSuccessor() = instruction.getASuccessor()
|
||||
}
|
||||
|
||||
override string getMessage() { result = "True successor isn't a successor" }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction whose false successor is not a successor.
|
||||
*/
|
||||
deprecated class FalseSuccessorIsSuccessor extends InstructionViolation {
|
||||
FalseSuccessorIsSuccessor() {
|
||||
exists(instruction.getFalseSuccessor()) and
|
||||
not instruction.getFalseSuccessor() = instruction.getASuccessor()
|
||||
}
|
||||
|
||||
override string getMessage() { result = "True successor isn't a successor" }
|
||||
}
|
||||
|
||||
/**
|
||||
* An access that does not have exactly one target.
|
||||
*/
|
||||
deprecated class AccessMissingTarget extends InstructionViolation {
|
||||
AccessMissingTarget() { exists(Access i | i = instruction | count(i.getTarget()) != 1) }
|
||||
|
||||
override string getMessage() { result = "Access has invalid getTarget()" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A catch handler that doesn't have a caught exception type.
|
||||
*/
|
||||
deprecated class CatchHandlerMissingType extends CfgViolation {
|
||||
CatchHandlerMissingType() { exists(CatchHandler h | h = node | not exists(h.getCaughtType())) }
|
||||
|
||||
override string getMessage() { result = "Catch handler missing caught type" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A CFG node that does not have a stack size.
|
||||
*/
|
||||
deprecated class MissingStackSize extends CfgViolation {
|
||||
MissingStackSize() {
|
||||
(
|
||||
not exists(node.getStackSizeAfter()) or
|
||||
not exists(node.getStackSizeBefore())
|
||||
) and
|
||||
not node instanceof DeadInstruction
|
||||
}
|
||||
|
||||
override string getMessage() { result = "Inconsistent stack size" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A CFG node that does not have exactly one stack size.
|
||||
* Disabled because inconsistent stack sizes have been observed.
|
||||
*/
|
||||
deprecated class InvalidStackSize extends CfgViolation, DisabledCheck {
|
||||
InvalidStackSize() {
|
||||
(
|
||||
count(node.getStackSizeAfter()) != 1 or
|
||||
count(node.getStackSizeBefore()) != 1
|
||||
) and
|
||||
not node instanceof DeadInstruction
|
||||
}
|
||||
|
||||
override string getMessage() {
|
||||
result =
|
||||
"Inconsistent stack sizes " + count(node.getStackSizeBefore()) + " before and " +
|
||||
count(node.getStackSizeAfter()) + " after"
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A CFG node that does not have exactly 1 `getPopCount()`.
|
||||
*/
|
||||
deprecated class InconsistentPopCount extends CfgViolation {
|
||||
InconsistentPopCount() { count(node.getPopCount()) != 1 }
|
||||
|
||||
override string getMessage() {
|
||||
result = "Cfg node has " + count(node.getPopCount()) + " pop counts"
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A CFG node that does not have exactly one `getPushCount()`.
|
||||
*/
|
||||
deprecated class InconsistentPushCount extends CfgViolation {
|
||||
InconsistentPushCount() { count(node.getPushCount()) != 1 }
|
||||
|
||||
override string getMessage() {
|
||||
result = "Cfg node has " + count(node.getPushCount()) + " push counts"
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A return instruction that does not have a stack size of 0 after it.
|
||||
*/
|
||||
deprecated class InvalidReturn extends InstructionViolation {
|
||||
InvalidReturn() { instruction instanceof Return and instruction.getStackSizeAfter() != 0 }
|
||||
|
||||
override string getMessage() { result = "Return has invalid stack size" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A throw instruction that does not have a stack size of 0 after it.
|
||||
*/
|
||||
deprecated class InvalidThrow extends InstructionViolation, DisabledCheck {
|
||||
InvalidThrow() { instruction instanceof Throw and instruction.getStackSizeAfter() != 0 }
|
||||
|
||||
override string getMessage() {
|
||||
result = "Throw has invalid stack size: " + instruction.getStackSizeAfter()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A field access where the field is "static" but the instruction is "instance".
|
||||
*/
|
||||
deprecated class StaticFieldTarget extends InstructionViolation {
|
||||
StaticFieldTarget() {
|
||||
exists(FieldAccess i | i = instruction |
|
||||
(i instanceof Opcodes::Stfld or i instanceof Opcodes::Stfld) and
|
||||
i.getTarget().isStatic()
|
||||
)
|
||||
}
|
||||
|
||||
override string getMessage() { result = "Inconsistent static field" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A branch without a target.
|
||||
*/
|
||||
deprecated class BranchWithoutTarget extends InstructionViolation {
|
||||
BranchWithoutTarget() {
|
||||
instruction = any(Branch b | not exists(b.getTarget()) and not b instanceof Opcodes::Switch)
|
||||
}
|
||||
|
||||
override string getMessage() { result = "Branch without target" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A consistency violation in a type.
|
||||
*/
|
||||
deprecated class TypeViolation extends ConsistencyViolation, TypeCheck {
|
||||
/** Gets the type containing the violation. */
|
||||
Type getType() { this = TypeCheck(result) }
|
||||
|
||||
override string toString() { result = this.getType().toString() }
|
||||
|
||||
abstract override string getMessage();
|
||||
}
|
||||
|
||||
/**
|
||||
* A type that has both type arguments and type parameters.
|
||||
*/
|
||||
deprecated class TypeIsBothConstructedAndUnbound extends TypeViolation {
|
||||
TypeIsBothConstructedAndUnbound() {
|
||||
this.getType() instanceof ConstructedGeneric and this.getType() instanceof UnboundGeneric
|
||||
}
|
||||
|
||||
override string getMessage() { result = "Type is both constructed and unbound" }
|
||||
}
|
||||
|
||||
/**
|
||||
* The location of a constructed generic type should be the same
|
||||
* as the location of its unbound generic type.
|
||||
*/
|
||||
deprecated class InconsistentTypeLocation extends TypeViolation {
|
||||
InconsistentTypeLocation() {
|
||||
this.getType().getLocation() != this.getType().getUnboundDeclaration().getLocation()
|
||||
}
|
||||
|
||||
override string getMessage() { result = "Inconsistent constructed type location" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A constructed type that does not match its unbound generic type.
|
||||
*/
|
||||
deprecated class TypeParameterMismatch extends TypeViolation {
|
||||
TypeParameterMismatch() {
|
||||
this.getType().(ConstructedGeneric).getNumberOfTypeArguments() !=
|
||||
this.getType().getUnboundType().(UnboundGeneric).getNumberOfTypeParameters()
|
||||
}
|
||||
|
||||
override string getMessage() {
|
||||
result =
|
||||
"Constructed type (" + this.getType().toStringWithTypes() + ") has " +
|
||||
this.getType().(ConstructedGeneric).getNumberOfTypeArguments() +
|
||||
" type arguments and unbound type (" + this.getType().getUnboundType().toStringWithTypes() +
|
||||
") has " + this.getType().getUnboundType().(UnboundGeneric).getNumberOfTypeParameters() +
|
||||
" type parameters"
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A consistency violation in a method.
|
||||
*/
|
||||
deprecated class MethodViolation extends ConsistencyViolation, DeclarationCheck {
|
||||
/** Gets the method containing the violation. */
|
||||
Method getMethod() { this = DeclarationCheck(result) }
|
||||
|
||||
override string toString() { result = this.getMethod().toString() }
|
||||
|
||||
override string getMessage() { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
* The location of a constructed method should be equal to the
|
||||
* location of its unbound generic.
|
||||
*/
|
||||
deprecated class InconsistentMethodLocation extends MethodViolation {
|
||||
InconsistentMethodLocation() {
|
||||
this.getMethod().getLocation() != this.getMethod().getUnboundDeclaration().getLocation()
|
||||
}
|
||||
|
||||
override string getMessage() { result = "Inconsistent constructed method location" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A constructed method that does not match its unbound method.
|
||||
*/
|
||||
deprecated class ConstructedMethodTypeParams extends MethodViolation {
|
||||
ConstructedMethodTypeParams() {
|
||||
this.getMethod().(ConstructedGeneric).getNumberOfTypeArguments() !=
|
||||
this.getMethod().getUnboundDeclaration().(UnboundGeneric).getNumberOfTypeParameters()
|
||||
}
|
||||
|
||||
override string getMessage() {
|
||||
result =
|
||||
"The constructed method " + this.getMethod().toStringWithTypes() +
|
||||
" does not match unbound method " +
|
||||
this.getMethod().getUnboundDeclaration().toStringWithTypes()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A violation marking an entity that should be present but is not.
|
||||
*/
|
||||
abstract deprecated class MissingEntityViolation extends ConsistencyViolation, MissingEntityCheck {
|
||||
override string toString() { result = "Missing entity" }
|
||||
}
|
||||
|
||||
/**
|
||||
* The type `object` is missing from the database.
|
||||
*/
|
||||
deprecated class MissingObjectViolation extends MissingEntityViolation {
|
||||
MissingObjectViolation() {
|
||||
exists(this) and
|
||||
not exists(ObjectType o)
|
||||
}
|
||||
|
||||
override string getMessage() { result = "Object missing" }
|
||||
}
|
||||
|
||||
/**
|
||||
* An override that is invalid because the overridden method is not in a base class.
|
||||
*/
|
||||
deprecated class InvalidOverride extends MethodViolation {
|
||||
private Method base;
|
||||
|
||||
InvalidOverride() {
|
||||
base = this.getMethod().getOverriddenMethod() and
|
||||
not this.getMethod().getDeclaringType().getABaseType+() = base.getDeclaringType() and
|
||||
base.getDeclaringType().isUnboundDeclaration() // Bases classes of constructed types aren't extracted properly.
|
||||
}
|
||||
|
||||
override string getMessage() {
|
||||
exists(string qualifier, string type |
|
||||
base.getDeclaringType().hasFullyQualifiedName(qualifier, type)
|
||||
|
|
||||
result =
|
||||
"Overridden method from " + getQualifiedName(qualifier, type) + " is not in a base type"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A pointer type that does not have a pointee type.
|
||||
*/
|
||||
deprecated class InvalidPointerType extends TypeViolation {
|
||||
InvalidPointerType() {
|
||||
exists(PointerType p | p = this.getType() | count(p.getReferentType()) != 1)
|
||||
}
|
||||
|
||||
override string getMessage() { result = "Invalid Pointertype.getPointeeType()" }
|
||||
}
|
||||
|
||||
/**
|
||||
* An array with an invalid `getElementType`.
|
||||
*/
|
||||
deprecated class ArrayTypeMissingElement extends TypeViolation {
|
||||
ArrayTypeMissingElement() {
|
||||
exists(ArrayType t | t = this.getType() | count(t.getElementType()) != 1)
|
||||
}
|
||||
|
||||
override string getMessage() { result = "Invalid ArrayType.getElementType()" }
|
||||
}
|
||||
|
||||
/**
|
||||
* An array with an invalid `getRank`.
|
||||
*/
|
||||
deprecated class ArrayTypeInvalidRank extends TypeViolation {
|
||||
ArrayTypeInvalidRank() { exists(ArrayType t | t = this.getType() | not t.getRank() > 0) }
|
||||
|
||||
override string getMessage() { result = "Invalid ArrayType.getRank()" }
|
||||
}
|
||||
|
||||
/**
|
||||
* A type should have at most one kind, except for missing referenced types
|
||||
* where the interface/class is unknown.
|
||||
*/
|
||||
deprecated class KindViolation extends TypeViolation {
|
||||
KindViolation() {
|
||||
count(typeKind(this.getType())) != 1 and
|
||||
exists(this.getType().getLocation())
|
||||
}
|
||||
|
||||
override string getMessage() {
|
||||
result = "Invalid kinds on type: " + concat(typeKind(this.getType()), " ")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The type of a kind must be consistent between a constructed generic and its
|
||||
* unbound generic.
|
||||
*/
|
||||
deprecated class InconsistentKind extends TypeViolation {
|
||||
InconsistentKind() {
|
||||
typeKind(this.getType()) != typeKind(this.getType().getUnboundDeclaration())
|
||||
}
|
||||
|
||||
override string getMessage() { result = "Inconsistent type kind of source declaration" }
|
||||
}
|
||||
|
||||
deprecated private string typeKind(Type t) {
|
||||
t instanceof Interface and result = "interface"
|
||||
or
|
||||
t instanceof Class and result = "class"
|
||||
or
|
||||
t instanceof TypeParameter and result = "type parameter"
|
||||
or
|
||||
t instanceof ArrayType and result = "array"
|
||||
or
|
||||
t instanceof PointerType and result = "pointer"
|
||||
}
|
||||
|
||||
/**
|
||||
* A violation in a `Member`.
|
||||
*/
|
||||
abstract deprecated class DeclarationViolation extends ConsistencyViolation, DeclarationCheck {
|
||||
abstract override string getMessage();
|
||||
|
||||
/** Gets the member containing the potential violation. */
|
||||
Declaration getDeclaration() { this = DeclarationCheck(result) }
|
||||
|
||||
override string toString() { result = this.getDeclaration().toString() }
|
||||
}
|
||||
|
||||
/**
|
||||
* Properties that have no accessors.
|
||||
*/
|
||||
deprecated class PropertyWithNoAccessors extends DeclarationViolation {
|
||||
PropertyWithNoAccessors() {
|
||||
exists(Property p | p = this.getDeclaration() | not exists(p.getAnAccessor()))
|
||||
}
|
||||
|
||||
override string getMessage() { result = "Property has no accessors" }
|
||||
}
|
||||
|
||||
/**
|
||||
* An expression that have an unexpected push count.
|
||||
*/
|
||||
deprecated class ExprPushCount extends InstructionViolation {
|
||||
ExprPushCount() {
|
||||
instruction instanceof Expr and
|
||||
not instruction instanceof Opcodes::Dup and
|
||||
if instruction instanceof Call
|
||||
then not instruction.getPushCount() in [0 .. 1]
|
||||
else instruction.(Expr).getPushCount() != 1
|
||||
}
|
||||
|
||||
override string getMessage() {
|
||||
result = "Instruction has unexpected push count " + instruction.getPushCount()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An expression that does not have exactly one type.
|
||||
* Note that calls with no return have type `System.Void`.
|
||||
*/
|
||||
deprecated class ExprMissingType extends InstructionViolation {
|
||||
ExprMissingType() {
|
||||
// Don't have types for the following op codes:
|
||||
not instruction instanceof Opcodes::Ldftn and
|
||||
not instruction instanceof Opcodes::Localloc and
|
||||
not instruction instanceof Opcodes::Ldvirtftn and
|
||||
not instruction instanceof Opcodes::Arglist and
|
||||
not instruction instanceof Opcodes::Refanytype and
|
||||
instruction.getPushCount() >= 1 and
|
||||
count(instruction.getType()) != 1 and
|
||||
// OS specific (osx) specific inconsistency
|
||||
not instruction
|
||||
.getImplementation()
|
||||
.getMethod()
|
||||
.hasFullyQualifiedName("System.Runtime.InteropServices.RuntimeInformation",
|
||||
"get_OSDescription")
|
||||
}
|
||||
|
||||
override string getMessage() { result = "Expression is missing getType()" }
|
||||
}
|
||||
|
||||
/**
|
||||
* An instruction that has a push count of 0, yet is still used as an operand
|
||||
*/
|
||||
deprecated class InvalidExpressionViolation extends InstructionViolation {
|
||||
InvalidExpressionViolation() {
|
||||
instruction.getPushCount() = 0 and
|
||||
exists(Instruction expr | instruction = expr.getAnOperand())
|
||||
}
|
||||
|
||||
override string getMessage() {
|
||||
result = "This instruction is used as an operand but pushes no values"
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A type that has multiple entities with the same qualified name in `System`.
|
||||
* .NET Core does sometimes duplicate types, so this check is disabled.
|
||||
*/
|
||||
deprecated class TypeMultiplyDefined extends TypeViolation, DisabledCheck {
|
||||
TypeMultiplyDefined() {
|
||||
this.getType().getParent().getName() = "System" and
|
||||
not this.getType() instanceof ConstructedGeneric and
|
||||
not this.getType() instanceof ArrayType and
|
||||
this.getType().isPublic() and
|
||||
count(Type t |
|
||||
not t instanceof ConstructedGeneric and
|
||||
t.toStringWithTypes() = this.getType().toStringWithTypes()
|
||||
) != 1
|
||||
}
|
||||
|
||||
override string getMessage() {
|
||||
result =
|
||||
"This type (" + this.getType().toStringWithTypes() + ") has " +
|
||||
count(Type t |
|
||||
not t instanceof ConstructedGeneric and
|
||||
t.toStringWithTypes() = this.getType().toStringWithTypes()
|
||||
) + " entities"
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A C# declaration which is expected to have a corresponding CIL declaration, but for some reason does not.
|
||||
*/
|
||||
deprecated class MissingCilDeclaration extends ConsistencyViolation, MissingCSharpCheck {
|
||||
MissingCilDeclaration() {
|
||||
exists(CS::Declaration decl | this = MissingCSharpCheck(decl) |
|
||||
expectedCilDeclaration(decl) and
|
||||
not exists(Declaration d | decl = d.getCSharpDeclaration())
|
||||
)
|
||||
}
|
||||
|
||||
CS::Declaration getDeclaration() { this = MissingCSharpCheck(result) }
|
||||
|
||||
override string getMessage() {
|
||||
result =
|
||||
"Cannot locate CIL for " + this.getDeclaration().toStringWithTypes() + " of class " +
|
||||
this.getDeclaration().getPrimaryQlClasses()
|
||||
}
|
||||
|
||||
override string toString() { result = this.getDeclaration().toStringWithTypes() }
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the C# declaration is expected to have a CIl declaration.
|
||||
*/
|
||||
deprecated private predicate expectedCilDeclaration(CS::Declaration decl) {
|
||||
decl = decl.getUnboundDeclaration() and
|
||||
not decl instanceof CS::ArrayType and
|
||||
decl.getALocation() instanceof CS::Assembly and
|
||||
not decl.(CS::Modifiable).isInternal() and
|
||||
not decl.(CS::Constructor).getNumberOfParameters() = 0 and // These are sometimes implicit
|
||||
not decl.(CS::Method).getReturnType() instanceof CS::UnknownType and
|
||||
not exists(CS::Parameter p | p = decl.(CS::Parameterizable).getAParameter() |
|
||||
not expectedCilDeclaration(p)
|
||||
) and
|
||||
not decl instanceof CS::AnonymousClass and
|
||||
(decl instanceof CS::Parameter implies expectedCilDeclaration(decl.(CS::Parameter).getType())) and
|
||||
(decl instanceof CS::Parameter implies expectedCilDeclaration(decl.getParent())) and
|
||||
(decl instanceof CS::Member implies expectedCilDeclaration(decl.getParent())) and
|
||||
(
|
||||
decl instanceof CS::Field
|
||||
or
|
||||
decl instanceof CS::Property
|
||||
or
|
||||
decl instanceof CS::ValueOrRefType
|
||||
or
|
||||
decl instanceof CS::Event
|
||||
or
|
||||
decl instanceof CS::Constructor
|
||||
or
|
||||
decl instanceof CS::Destructor
|
||||
or
|
||||
decl instanceof CS::Operator
|
||||
or
|
||||
decl instanceof CS::Method
|
||||
or
|
||||
decl instanceof CS::Parameter
|
||||
)
|
||||
}
|
||||
|
||||
/** A member with an invalid name. */
|
||||
deprecated class MemberWithInvalidName extends DeclarationViolation {
|
||||
MemberWithInvalidName() {
|
||||
exists(string name | name = this.getDeclaration().(Member).getName() |
|
||||
exists(name.indexOf(".")) and
|
||||
not name = ".ctor" and
|
||||
not name = ".cctor"
|
||||
)
|
||||
}
|
||||
|
||||
override string getMessage() {
|
||||
result = "Invalid name " + this.getDeclaration().(Member).getName()
|
||||
}
|
||||
}
|
||||
|
||||
deprecated class ConstructedSourceDeclarationMethod extends MethodViolation {
|
||||
Method method;
|
||||
|
||||
ConstructedSourceDeclarationMethod() {
|
||||
method = this.getMethod() and
|
||||
method = method.getUnboundDeclaration() and
|
||||
(
|
||||
method instanceof ConstructedGeneric or
|
||||
method.getDeclaringType() instanceof ConstructedGeneric
|
||||
)
|
||||
}
|
||||
|
||||
override string getMessage() {
|
||||
result = "Source declaration " + method.toStringWithTypes() + " is constructed"
|
||||
}
|
||||
}
|
||||
|
||||
/** A declaration with multiple labels. */
|
||||
deprecated class DeclarationWithMultipleLabels extends DeclarationViolation {
|
||||
DeclarationWithMultipleLabels() {
|
||||
exists(Declaration d | this = DeclarationCheck(d) | strictcount(d.getLabel()) > 1)
|
||||
}
|
||||
|
||||
override string getMessage() {
|
||||
result = "Multiple labels " + concat(this.getDeclaration().getLabel(), ", ")
|
||||
}
|
||||
}
|
||||
|
||||
/** A declaration without a label. */
|
||||
deprecated class DeclarationWithoutLabel extends DeclarationViolation {
|
||||
DeclarationWithoutLabel() {
|
||||
exists(Declaration d | this = DeclarationCheck(d) |
|
||||
d.isUnboundDeclaration() and
|
||||
not d instanceof TypeParameter and
|
||||
not exists(d.getLabel()) and
|
||||
(d instanceof Callable or d instanceof Type)
|
||||
)
|
||||
}
|
||||
|
||||
override string getMessage() { result = "No label" }
|
||||
}
|
||||
@@ -1,179 +0,0 @@
|
||||
/**
|
||||
* Provides classes for control flow.
|
||||
*/
|
||||
|
||||
private import CIL
|
||||
|
||||
/** A node in the control flow graph. */
|
||||
deprecated class ControlFlowNode extends @cil_controlflow_node {
|
||||
/** Gets a textual representation of this control flow node. */
|
||||
string toString() { none() }
|
||||
|
||||
/** Gets the location of this control flow node. */
|
||||
Location getLocation() { none() }
|
||||
|
||||
/**
|
||||
* Gets the number of items this node pushes onto the stack.
|
||||
* This value is either 0 or 1, except for the instruction `dup`
|
||||
* which pushes 2 values onto the stack.
|
||||
*/
|
||||
int getPushCount() { result = 0 }
|
||||
|
||||
/** Gets the number of items this node pops from the stack. */
|
||||
int getPopCount() { result = 0 }
|
||||
|
||||
/** Gets a successor of this node, if any. */
|
||||
final Instruction getASuccessor() { result = this.getASuccessorType(_) }
|
||||
|
||||
/** Gets a true successor of this node, if any. */
|
||||
final Instruction getTrueSuccessor() { result = this.getASuccessorType(any(TrueFlow f)) }
|
||||
|
||||
/** Gets a false successor of this node, if any. */
|
||||
final Instruction getFalseSuccessor() { result = this.getASuccessorType(any(FalseFlow f)) }
|
||||
|
||||
/** Gets a successor to this node, of type `type`, if any. */
|
||||
cached
|
||||
Instruction getASuccessorType(FlowType t) { none() }
|
||||
|
||||
/** Gets a predecessor of this node, if any. */
|
||||
ControlFlowNode getAPredecessor() { result.getASuccessor() = this }
|
||||
|
||||
/**
|
||||
* Gets an instruction that supplies the `i`th operand to this instruction.
|
||||
* Note that this can be multi-valued.
|
||||
*/
|
||||
cached
|
||||
ControlFlowNode getOperand(int i) {
|
||||
// Immediate predecessor pushes the operand
|
||||
i in [0 .. this.getPopCount() - 1] and
|
||||
result = this.getAPredecessor() and
|
||||
i < result.getPushCount()
|
||||
or
|
||||
// Transitive predecessor pushes the operand
|
||||
exists(ControlFlowNode mid, int pushes | this.getOperandRec(mid, i, pushes) |
|
||||
pushes - mid.getStackDelta() < result.getPushCount() and
|
||||
result = mid.getAPredecessor()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the type of the `i`th operand. Unlike `getOperand(i).getType()`, this
|
||||
* predicate takes into account when there are multiple possible operands with
|
||||
* different types.
|
||||
*/
|
||||
Type getOperandType(int i) {
|
||||
strictcount(this.getOperand(i)) = 1 and
|
||||
result = this.getOperand(i).getType()
|
||||
or
|
||||
strictcount(this.getOperand(i)) = 2 and
|
||||
exists(ControlFlowNode op1, ControlFlowNode op2, Type t2 |
|
||||
op1 = this.getOperand(i) and
|
||||
op2 = this.getOperand(i) and
|
||||
op1 != op2 and
|
||||
result = op1.getType() and
|
||||
t2 = op2.getType()
|
||||
|
|
||||
result = t2
|
||||
or
|
||||
result.(PrimitiveType).getUnderlyingType().getConversionIndex() >
|
||||
t2.(PrimitiveType).getUnderlyingType().getConversionIndex()
|
||||
or
|
||||
op2 instanceof NullLiteral
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets an operand of this instruction, if any. */
|
||||
ControlFlowNode getAnOperand() { result = this.getOperand(_) }
|
||||
|
||||
/** Gets an expression that consumes the output of this instruction on the stack. */
|
||||
Instruction getParentExpr() { this = result.getAnOperand() }
|
||||
|
||||
/**
|
||||
* Holds if `pred` is a transitive predecessor of this instruction, this
|
||||
* instruction pops operand `i`, `pushes` additional pushes are required
|
||||
* for operand `i` at node `pred`, and no instruction between (and including)
|
||||
* `pred` and this instruction is a push for operand `i`.
|
||||
*/
|
||||
private predicate getOperandRec(ControlFlowNode pred, int i, int pushes) {
|
||||
// Invariant: no node is a push for operand `i`
|
||||
pushes >= pred.getPushCount() and
|
||||
(
|
||||
i in [0 .. this.getPopCount() - 1] and
|
||||
pred = this.getAPredecessor() and
|
||||
pushes = i
|
||||
or
|
||||
exists(ControlFlowNode mid, int pushes0 | this.getOperandRec(mid, i, pushes0) |
|
||||
pushes = pushes0 - mid.getStackDelta() and
|
||||
// This is a guard to prevent ill formed programs
|
||||
// and other logic errors going into an infinite loop.
|
||||
pushes <= this.getImplementation().getStackSize() and
|
||||
pred = mid.getAPredecessor()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
private int getStackDelta() { result = this.getPushCount() - this.getPopCount() }
|
||||
|
||||
/** Gets the stack size before this instruction. */
|
||||
int getStackSizeBefore() { result = this.getAPredecessor().getStackSizeAfter() }
|
||||
|
||||
/** Gets the stack size after this instruction. */
|
||||
final int getStackSizeAfter() {
|
||||
// This is a guard to prevent ill formed programs
|
||||
// and other logic errors going into an infinite loop.
|
||||
result in [0 .. this.getImplementation().getStackSize()] and
|
||||
result = this.getStackSizeBefore() + this.getStackDelta()
|
||||
}
|
||||
|
||||
/** Gets the method containing this control flow node. */
|
||||
MethodImplementation getImplementation() { none() }
|
||||
|
||||
/**
|
||||
* Gets the type of the item pushed onto the stack, if any.
|
||||
*
|
||||
* If called via `ControlFlowNode::getOperand(i).getType()`, consider using
|
||||
* `ControlFlowNode::getOperandType(i)` instead.
|
||||
*/
|
||||
cached
|
||||
Type getType() { none() }
|
||||
|
||||
/** Holds if this control flow node has more than one predecessor. */
|
||||
predicate isJoin() { strictcount(this.getAPredecessor()) > 1 }
|
||||
|
||||
/** Holds if this control flow node has more than one successor. */
|
||||
predicate isBranch() { strictcount(this.getASuccessor()) > 1 }
|
||||
}
|
||||
|
||||
/**
|
||||
* A control flow entry point. Either a method (`MethodImplementation`) or a handler (`Handler`).
|
||||
*
|
||||
* Handlers are control flow nodes because they push the handled exception onto the stack.
|
||||
*/
|
||||
deprecated class EntryPoint extends ControlFlowNode, @cil_entry_point {
|
||||
override int getStackSizeBefore() { result = 0 }
|
||||
}
|
||||
|
||||
deprecated private newtype TFlowType =
|
||||
TNormalFlow() or
|
||||
TTrueFlow() or
|
||||
TFalseFlow()
|
||||
|
||||
/** A type of control flow. Either normal flow (`NormalFlow`), true flow (`TrueFlow`) or false flow (`FalseFlow`). */
|
||||
abstract deprecated class FlowType extends TFlowType {
|
||||
abstract string toString();
|
||||
}
|
||||
|
||||
/** Normal control flow. */
|
||||
deprecated class NormalFlow extends FlowType, TNormalFlow {
|
||||
override string toString() { result = "" }
|
||||
}
|
||||
|
||||
/** True control flow. */
|
||||
deprecated class TrueFlow extends FlowType, TTrueFlow {
|
||||
override string toString() { result = "true" }
|
||||
}
|
||||
|
||||
/** False control flow. */
|
||||
deprecated class FalseFlow extends FlowType, TFalseFlow {
|
||||
override string toString() { result = "false" }
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
/**
|
||||
* Provides a class to represent `modopt` and `modreq` declarations.
|
||||
*/
|
||||
|
||||
private import CIL
|
||||
private import dotnet
|
||||
|
||||
/**
|
||||
* A class to represent entities that can receive custom modifiers. Custom modifiers can be attached to
|
||||
* - the type of a `Field`,
|
||||
* - the return type of a `Method` or `Property`,
|
||||
* - the type of parameters.
|
||||
* A `CustomModifierReceiver` is therefore either a `Field`, `Property`, `Method`, or `Parameter`.
|
||||
*/
|
||||
deprecated class CustomModifierReceiver extends Declaration, @cil_custom_modifier_receiver {
|
||||
/** Holds if this targeted type has `modifier` applied as `modreq`. */
|
||||
predicate hasRequiredCustomModifier(Type modifier) { cil_custom_modifiers(this, modifier, 1) }
|
||||
|
||||
/** Holds if this targeted type has `modifier` applied as `modopt`. */
|
||||
predicate hasOptionalCustomModifier(Type modifier) { cil_custom_modifiers(this, modifier, 0) }
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
/**
|
||||
* Provides a collection of building blocks and utilities for data flow.
|
||||
*/
|
||||
|
||||
private import CIL
|
||||
|
||||
/**
|
||||
* A node in the data flow graph.
|
||||
*
|
||||
* Either an instruction (`Instruction`), a method return (`Method`), or a variable (`Variable`).
|
||||
*/
|
||||
deprecated class DataFlowNode extends @cil_dataflow_node {
|
||||
/** Gets a textual representation of this data flow node. */
|
||||
abstract string toString();
|
||||
|
||||
/** Gets the type of this data flow node. */
|
||||
Type getType() { none() }
|
||||
|
||||
/** Gets the method that contains this dataflow node. */
|
||||
Method getMethod() { none() }
|
||||
|
||||
/** Gets the location of this dataflow node. */
|
||||
Location getLocation() { none() }
|
||||
}
|
||||
|
||||
/** A node that updates a variable. */
|
||||
abstract deprecated class VariableUpdate extends DataFlowNode {
|
||||
/** Gets the value assigned, if any. */
|
||||
abstract DataFlowNode getSource();
|
||||
|
||||
/** Gets the variable that is updated. */
|
||||
abstract Variable getVariable();
|
||||
|
||||
/** Holds if this variable update happens at index `i` in basic block `bb`. */
|
||||
abstract predicate updatesAt(BasicBlock bb, int i);
|
||||
}
|
||||
|
||||
deprecated private class MethodParameterDef extends VariableUpdate, MethodParameter {
|
||||
override MethodParameter getSource() { result = this }
|
||||
|
||||
override MethodParameter getVariable() { result = this }
|
||||
|
||||
override predicate updatesAt(BasicBlock bb, int i) {
|
||||
bb.(EntryBasicBlock).getANode().getImplementation().getMethod() = this.getMethod() and
|
||||
i = -1
|
||||
}
|
||||
}
|
||||
|
||||
deprecated private class VariableWrite extends VariableUpdate, WriteAccess {
|
||||
override Expr getSource() { result = this.getExpr() }
|
||||
|
||||
override Variable getVariable() { result = this.getTarget() }
|
||||
|
||||
override predicate updatesAt(BasicBlock bb, int i) { this = bb.getNode(i) }
|
||||
}
|
||||
|
||||
deprecated private class MethodOutOrRefTarget extends VariableUpdate, Call {
|
||||
int parameterIndex;
|
||||
|
||||
MethodOutOrRefTarget() { this.getTarget().getRawParameter(parameterIndex).hasOutFlag() }
|
||||
|
||||
override Variable getVariable() {
|
||||
result = this.getRawArgument(parameterIndex).(ReadAccess).getTarget()
|
||||
}
|
||||
|
||||
override Expr getSource() { none() }
|
||||
|
||||
override predicate updatesAt(BasicBlock bb, int i) { this = bb.getNode(i) }
|
||||
}
|
||||
@@ -1,148 +0,0 @@
|
||||
/**
|
||||
* Provides classes for declarations and members.
|
||||
*/
|
||||
|
||||
import CIL
|
||||
private import dotnet
|
||||
private import semmle.code.csharp.Member as CS
|
||||
private import semmle.code.csharp.commons.QualifiedName
|
||||
|
||||
/**
|
||||
* A declaration. Either a member (`Member`) or a variable (`Variable`).
|
||||
*/
|
||||
deprecated class Declaration extends DotNet::Declaration, Element, @cil_declaration {
|
||||
/** Gets an attribute (for example `[Obsolete]`) of this declaration, if any. */
|
||||
Attribute getAnAttribute() { result.getDeclaration() = this }
|
||||
|
||||
/**
|
||||
* Gets the C# declaration corresponding to this CIL declaration, if any.
|
||||
* Note that this is only for source/unconstructed declarations.
|
||||
*/
|
||||
CS::Declaration getCSharpDeclaration() {
|
||||
result = toCSharpNonTypeParameter(this) or
|
||||
result = toCSharpTypeParameter(this)
|
||||
}
|
||||
|
||||
override Declaration getUnboundDeclaration() { result = this }
|
||||
|
||||
deprecated override predicate hasQualifiedName(string qualifier, string name) {
|
||||
exists(string dqualifier, string dname |
|
||||
this.getDeclaringType().hasQualifiedName(dqualifier, dname) and
|
||||
qualifier = getQualifiedName(dqualifier, dname)
|
||||
) and
|
||||
name = this.getName()
|
||||
}
|
||||
|
||||
override predicate hasFullyQualifiedName(string qualifier, string name) {
|
||||
exists(string dqualifier, string dname |
|
||||
this.getDeclaringType().hasFullyQualifiedName(dqualifier, dname) and
|
||||
qualifier = getQualifiedName(dqualifier, dname)
|
||||
) and
|
||||
name = this.getName()
|
||||
}
|
||||
}
|
||||
|
||||
deprecated private CS::Declaration toCSharpNonTypeParameter(Declaration d) {
|
||||
result.(DotNet::Declaration).matchesHandle(d)
|
||||
}
|
||||
|
||||
deprecated private CS::TypeParameter toCSharpTypeParameter(TypeParameter tp) {
|
||||
toCSharpTypeParameterJoin(tp, result.getIndex(), result.getGeneric())
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
deprecated private predicate toCSharpTypeParameterJoin(
|
||||
TypeParameter tp, int i, CS::UnboundGeneric ug
|
||||
) {
|
||||
exists(TypeContainer tc |
|
||||
tp.getIndex() = i and
|
||||
tc = tp.getGeneric() and
|
||||
ug = toCSharpNonTypeParameter(tc)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* A member of a type. Either a type (`Type`), a method (`Method`), a property (`Property`), or an event (`Event`).
|
||||
*/
|
||||
deprecated class Member extends DotNet::Member, Declaration, @cil_member {
|
||||
override predicate isPublic() { cil_public(this) }
|
||||
|
||||
override predicate isProtected() { cil_protected(this) }
|
||||
|
||||
override predicate isPrivate() { cil_private(this) }
|
||||
|
||||
override predicate isInternal() { cil_internal(this) }
|
||||
|
||||
override predicate isSealed() { cil_sealed(this) }
|
||||
|
||||
override predicate isAbstract() { cil_abstract(this) }
|
||||
|
||||
override predicate isStatic() { cil_static(this) }
|
||||
|
||||
/** Holds if this member has a security attribute. */
|
||||
predicate hasSecurity() { cil_security(this) }
|
||||
|
||||
override Location getLocation() { result = this.getDeclaringType().getLocation() }
|
||||
}
|
||||
|
||||
/** A property. */
|
||||
deprecated class Property extends DotNet::Property, Member, CustomModifierReceiver, @cil_property {
|
||||
override string getName() { cil_property(this, _, result, _) }
|
||||
|
||||
/** Gets the type of this property. */
|
||||
override Type getType() { cil_property(this, _, _, result) }
|
||||
|
||||
override ValueOrRefType getDeclaringType() { cil_property(this, result, _, _) }
|
||||
|
||||
/** Gets the getter of this property, if any. */
|
||||
override Getter getGetter() { this = result.getProperty() }
|
||||
|
||||
/** Gets the setter of this property, if any. */
|
||||
override Setter getSetter() { this = result.getProperty() }
|
||||
|
||||
/** Gets an accessor of this property. */
|
||||
Accessor getAnAccessor() { result = this.getGetter() or result = this.getSetter() }
|
||||
|
||||
override string toString() { result = "property " + this.getName() }
|
||||
|
||||
override string toStringWithTypes() {
|
||||
result =
|
||||
this.getType().toStringWithTypes() + " " + this.getDeclaringType().toStringWithTypes() + "." +
|
||||
this.getName()
|
||||
}
|
||||
}
|
||||
|
||||
/** A property that is trivial (wraps a field). */
|
||||
deprecated class TrivialProperty extends Property {
|
||||
TrivialProperty() {
|
||||
this.getGetter().(TrivialGetter).getField() = this.getSetter().(TrivialSetter).getField()
|
||||
}
|
||||
|
||||
/** Gets the underlying field of this property. */
|
||||
Field getField() { result = this.getGetter().(TrivialGetter).getField() }
|
||||
}
|
||||
|
||||
/** An event. */
|
||||
deprecated class Event extends DotNet::Event, Member, @cil_event {
|
||||
override string getName() { cil_event(this, _, result, _) }
|
||||
|
||||
/** Gets the type of this event. */
|
||||
Type getType() { cil_event(this, _, _, result) }
|
||||
|
||||
override ValueOrRefType getDeclaringType() { cil_event(this, result, _, _) }
|
||||
|
||||
/** Gets the add event accessor. */
|
||||
Method getAddEventAccessor() { cil_adder(this, result) }
|
||||
|
||||
/** Gets the remove event accessor. */
|
||||
Method getRemoveEventAccessor() { cil_remover(this, result) }
|
||||
|
||||
/** Gets the raiser. */
|
||||
Method getRaiser() { cil_raiser(this, result) }
|
||||
|
||||
override string toString() { result = "event " + this.getName() }
|
||||
|
||||
override string toStringWithTypes() {
|
||||
result = this.getDeclaringType().toStringWithTypes() + "." + this.getName()
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
/** Provides the `Element` class, the base class of all CIL program elements. */
|
||||
|
||||
private import dotnet
|
||||
import semmle.code.csharp.Location
|
||||
|
||||
/** An element. */
|
||||
deprecated class Element extends DotNet::Element, @cil_element {
|
||||
override Location getLocation() { result = bestLocation(this) }
|
||||
}
|
||||
|
||||
cached
|
||||
deprecated private Location bestLocation(Element e) {
|
||||
result = e.getALocation() and
|
||||
(e.getALocation().getFile().isPdbSourceFile() implies result.getFile().isPdbSourceFile())
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
/** Provides classes for generic types and methods. */
|
||||
|
||||
private import CIL
|
||||
private import dotnet
|
||||
|
||||
/**
|
||||
* A generic declaration. Either an unbound generic (`UnboundGeneric`) or a
|
||||
* constructed generic (`ConstructedGeneric`).
|
||||
*/
|
||||
deprecated class Generic extends DotNet::Generic, Declaration, TypeContainer {
|
||||
Generic() {
|
||||
cil_type_parameter(this, _, _) or
|
||||
cil_type_argument(this, _, _)
|
||||
}
|
||||
}
|
||||
|
||||
/** An unbound generic type or method. */
|
||||
deprecated class UnboundGeneric extends Generic, DotNet::UnboundGeneric {
|
||||
UnboundGeneric() { cil_type_parameter(this, _, _) }
|
||||
|
||||
final override TypeParameter getTypeParameter(int n) { cil_type_parameter(this, n, result) }
|
||||
}
|
||||
|
||||
/** A constructed generic type or method. */
|
||||
deprecated class ConstructedGeneric extends Generic, DotNet::ConstructedGeneric {
|
||||
ConstructedGeneric() { cil_type_argument(this, _, _) }
|
||||
|
||||
final override Type getTypeArgument(int n) { cil_type_argument(this, n, result) }
|
||||
}
|
||||
|
||||
/** Gets the concatenation of the `getName()` of type arguments. */
|
||||
language[monotonicAggregates]
|
||||
deprecated private string getTypeArgumentsNames(ConstructedGeneric cg) {
|
||||
result = strictconcat(Type t, int i | t = cg.getTypeArgument(i) | t.getName(), "," order by i)
|
||||
}
|
||||
|
||||
/** An unbound generic type. */
|
||||
deprecated class UnboundGenericType extends UnboundGeneric, Type { }
|
||||
|
||||
/** An unbound generic method. */
|
||||
deprecated class UnboundGenericMethod extends UnboundGeneric, Method { }
|
||||
|
||||
/** A constructed generic type. */
|
||||
deprecated class ConstructedType extends ConstructedGeneric, Type {
|
||||
final override UnboundGenericType getUnboundGeneric() { result = this.getUnboundType() }
|
||||
|
||||
override predicate isInterface() { this.getUnboundType().isInterface() }
|
||||
|
||||
override predicate isClass() { this.getUnboundType().isClass() }
|
||||
|
||||
final override string getName() {
|
||||
result = this.getUndecoratedName() + "<" + getTypeArgumentsNames(this) + ">"
|
||||
}
|
||||
}
|
||||
|
||||
/** A constructed generic method. */
|
||||
deprecated class ConstructedMethod extends ConstructedGeneric, Method {
|
||||
final override UnboundGenericMethod getUnboundGeneric() { result = this.getUnboundMethod() }
|
||||
}
|
||||
@@ -1,83 +0,0 @@
|
||||
/**
|
||||
* Provides classes for different types of handler.
|
||||
*/
|
||||
|
||||
private import CIL
|
||||
|
||||
/**
|
||||
* A handler is a piece of code that can be executed out of sequence, for example
|
||||
* when an instruction generates an exception or leaves a `finally` block.
|
||||
*
|
||||
* Each handler has a scope representing the block of instructions guarded by
|
||||
* this handler (corresponding to a C# `try { ... }` block), and a block of instructions
|
||||
* to execute when the handler is triggered (corresponding to a `catch` or `finally` block).
|
||||
*
|
||||
* Handlers are entry points (`EntryPoint`) so that they can
|
||||
* provide values on the stack, for example the value of the current exception. This is why
|
||||
* some handlers have a push count of 1.
|
||||
*
|
||||
* Either a finally handler (`FinallyHandler`), filter handler (`FilterHandler`),
|
||||
* catch handler (`CatchHandler`), or a fault handler (`FaultHandler`).
|
||||
*/
|
||||
deprecated class Handler extends Element, EntryPoint, @cil_handler {
|
||||
override MethodImplementation getImplementation() { cil_handler(this, result, _, _, _, _, _) }
|
||||
|
||||
/** Gets the 0-based index of this handler. Handlers are evaluated in this sequence. */
|
||||
int getIndex() { cil_handler(this, _, result, _, _, _, _) }
|
||||
|
||||
/** Gets the first instruction in the `try` block of this handler. */
|
||||
Instruction getTryStart() { cil_handler(this, _, _, _, result, _, _) }
|
||||
|
||||
/** Gets the last instruction in the `try` block of this handler. */
|
||||
Instruction getTryEnd() { cil_handler(this, _, _, _, _, result, _) }
|
||||
|
||||
/** Gets the first instruction in the `catch`/`finally` block. */
|
||||
Instruction getHandlerStart() { cil_handler(this, _, _, _, _, _, result) }
|
||||
|
||||
/**
|
||||
* Holds if the instruction `i` is in the scope of this handler.
|
||||
*/
|
||||
predicate isInScope(Instruction i) {
|
||||
i.getImplementation() = this.getImplementation() and
|
||||
i.getIndex() in [this.getTryStart().getIndex() .. this.getTryEnd().getIndex()]
|
||||
}
|
||||
|
||||
override string toString() { none() }
|
||||
|
||||
override Instruction getASuccessorType(FlowType t) {
|
||||
result = this.getHandlerStart() and
|
||||
t instanceof NormalFlow
|
||||
}
|
||||
|
||||
/** Gets the type of the caught exception, if any. */
|
||||
Type getCaughtType() { cil_handler_type(this, result) }
|
||||
|
||||
override Location getLocation() { result = this.getTryStart().getLocation() }
|
||||
}
|
||||
|
||||
/** A handler corresponding to a `finally` block. */
|
||||
deprecated class FinallyHandler extends Handler, @cil_finally_handler {
|
||||
override string toString() { result = "finally {...}" }
|
||||
}
|
||||
|
||||
/** A handler corresponding to a `where()` clause. */
|
||||
deprecated class FilterHandler extends Handler, @cil_filter_handler {
|
||||
override string toString() { result = "where (...)" }
|
||||
|
||||
/** Gets the filter clause - the start of a sequence of instructions to evaluate the filter function. */
|
||||
Instruction getFilterClause() { cil_handler_filter(this, result) }
|
||||
|
||||
override int getPushCount() { result = 1 }
|
||||
}
|
||||
|
||||
/** A handler corresponding to a `catch` clause. */
|
||||
deprecated class CatchHandler extends Handler, @cil_catch_handler {
|
||||
override string toString() { result = "catch(" + this.getCaughtType().getName() + ") {...}" }
|
||||
|
||||
override int getPushCount() { result = 1 }
|
||||
}
|
||||
|
||||
/** A handler for memory faults. */
|
||||
deprecated class FaultHandler extends Handler, @cil_fault_handler {
|
||||
override string toString() { result = "fault {...}" }
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
/** Provides the `Instruction` class. */
|
||||
|
||||
private import CIL
|
||||
|
||||
/** An instruction. */
|
||||
deprecated class Instruction extends Element, ControlFlowNode, DataFlowNode, @cil_instruction {
|
||||
override string toString() { result = this.getOpcodeName() }
|
||||
|
||||
/** Gets a more verbose textual representation of this instruction. */
|
||||
string toStringExtra() {
|
||||
result = this.getIndex() + ": " + this.getOpcodeName() + this.getExtraStr()
|
||||
}
|
||||
|
||||
/** Gets the method containing this instruction. */
|
||||
override MethodImplementation getImplementation() { cil_instruction(this, _, _, result) }
|
||||
|
||||
override Method getMethod() { result = this.getImplementation().getMethod() }
|
||||
|
||||
/**
|
||||
* Gets the index of this instruction.
|
||||
* Instructions are sequenced from 0.
|
||||
*/
|
||||
int getIndex() { cil_instruction(this, _, result, _) }
|
||||
|
||||
/** Gets the opcode of this instruction. */
|
||||
final int getOpcode() { cil_instruction(this, result, _, _) }
|
||||
|
||||
/** Gets the opcode name of this instruction, for example `ldnull`. */
|
||||
string getOpcodeName() { none() }
|
||||
|
||||
/** Gets an extra field to display for this instruction, if any. */
|
||||
string getExtra() { none() }
|
||||
|
||||
private string getExtraStr() {
|
||||
if exists(this.getExtra()) then result = " " + this.getExtra() else result = ""
|
||||
}
|
||||
|
||||
/** Gets the declaration accessed by this instruction, if any. */
|
||||
Declaration getAccess() { cil_access(this, result) }
|
||||
|
||||
/** Gets a successor instruction to this instruction. */
|
||||
override Instruction getASuccessorType(FlowType t) {
|
||||
t instanceof NormalFlow and
|
||||
this.canFlowNext() and
|
||||
result = this.getImplementation().getInstruction(this.getIndex() + 1)
|
||||
}
|
||||
|
||||
/** Holds if this instruction passes control flow into the next instruction. */
|
||||
predicate canFlowNext() { any() }
|
||||
|
||||
/**
|
||||
* Gets the `i`th handler that applies to this instruction.
|
||||
* Indexed from 0.
|
||||
*/
|
||||
Handler getHandler(int i) {
|
||||
result.isInScope(this) and
|
||||
result.getIndex() =
|
||||
rank[i + 1](int hi | exists(Handler h | h.isInScope(this) and hi = h.getIndex()))
|
||||
}
|
||||
|
||||
override Type getType() { result = ControlFlowNode.super.getType() }
|
||||
|
||||
override Location getALocation() {
|
||||
cil_instruction_location(this, result) // The source code, if available
|
||||
or
|
||||
result = this.getImplementation().getLocation() // The containing assembly
|
||||
}
|
||||
|
||||
override Location getLocation() { result = Element.super.getLocation() }
|
||||
}
|
||||
@@ -1,263 +0,0 @@
|
||||
/**
|
||||
* Provides classes representing various classes of expression
|
||||
* and other instructions.
|
||||
*/
|
||||
|
||||
private import CIL
|
||||
private import dotnet
|
||||
|
||||
/**
|
||||
* An instruction that pushes a value onto the stack.
|
||||
*/
|
||||
deprecated class Expr extends DotNet::Expr, Instruction, @cil_expr {
|
||||
override int getPushCount() { result = 1 }
|
||||
|
||||
override Type getType() { result = Instruction.super.getType() }
|
||||
|
||||
override Method getEnclosingCallable() { result = this.getImplementation().getMethod() }
|
||||
|
||||
/**
|
||||
* The "parent" of a CIL expression is taken to be the instruction
|
||||
* that consumes the value pushed by this instruction.
|
||||
*/
|
||||
override Expr getParent() { this = result.getAnOperand() }
|
||||
}
|
||||
|
||||
/** An instruction that changes control flow. */
|
||||
deprecated class Branch extends Instruction, @cil_jump {
|
||||
/** Gets the instruction that is jumped to. */
|
||||
Instruction getTarget() { cil_jump(this, result) }
|
||||
|
||||
override string getExtra() { result = this.getTarget().getIndex() + ":" }
|
||||
}
|
||||
|
||||
/** An instruction that unconditionally jumps to another instruction. */
|
||||
deprecated class UnconditionalBranch extends Branch, @cil_unconditional_jump {
|
||||
override Instruction getASuccessorType(FlowType t) {
|
||||
t instanceof NormalFlow and result = this.getTarget()
|
||||
}
|
||||
|
||||
override predicate canFlowNext() { none() }
|
||||
}
|
||||
|
||||
/** An instruction that jumps to a target based on a condition. */
|
||||
deprecated class ConditionalBranch extends Branch, @cil_conditional_jump {
|
||||
override Instruction getASuccessorType(FlowType t) {
|
||||
t instanceof TrueFlow and result = this.getTarget()
|
||||
or
|
||||
t instanceof FalseFlow and result = this.getImplementation().getInstruction(this.getIndex() + 1)
|
||||
}
|
||||
|
||||
override int getPushCount() { result = 0 }
|
||||
}
|
||||
|
||||
/** An expression with two operands. */
|
||||
deprecated class BinaryExpr extends Expr, @cil_binary_expr {
|
||||
override int getPopCount() { result = 2 }
|
||||
}
|
||||
|
||||
/** An expression with one operand. */
|
||||
deprecated class UnaryExpr extends Expr, @cil_unary_expr {
|
||||
override int getPopCount() { result = 1 }
|
||||
|
||||
/** Gets the operand of this unary expression. */
|
||||
Expr getOperand() { result = this.getOperand(0) }
|
||||
}
|
||||
|
||||
/** A binary expression that compares two values. */
|
||||
deprecated class ComparisonOperation extends BinaryExpr, @cil_comparison_operation {
|
||||
override BoolType getType() { exists(result) }
|
||||
}
|
||||
|
||||
/** A binary arithmetic expression. */
|
||||
deprecated class BinaryArithmeticExpr extends BinaryExpr, @cil_binary_arithmetic_operation {
|
||||
override Type getType() {
|
||||
exists(Type t0, Type t1 |
|
||||
t0 = this.getOperandType(0).getUnderlyingType() and
|
||||
t1 = this.getOperandType(1).getUnderlyingType()
|
||||
|
|
||||
t0 = t1 and result = t0
|
||||
or
|
||||
t0.getConversionIndex() < t1.getConversionIndex() and result = t1
|
||||
or
|
||||
t0.getConversionIndex() > t1.getConversionIndex() and result = t0
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/** A binary bitwise expression. */
|
||||
deprecated class BinaryBitwiseOperation extends BinaryExpr, @cil_binary_bitwise_operation {
|
||||
// This is wrong but efficient - should depend on the types of the operands.
|
||||
override IntType getType() { exists(result) }
|
||||
}
|
||||
|
||||
/** A unary bitwise expression. */
|
||||
deprecated class UnaryBitwiseOperation extends UnaryExpr, @cil_unary_bitwise_operation {
|
||||
// This is wrong but efficient - should depend on the types of the operands.
|
||||
override IntType getType() { exists(result) }
|
||||
}
|
||||
|
||||
/** A unary expression that converts a value from one primitive type to another. */
|
||||
deprecated class Conversion extends UnaryExpr, @cil_conversion_operation {
|
||||
/** Gets the expression being converted. */
|
||||
Expr getExpr() { result = this.getOperand(0) }
|
||||
}
|
||||
|
||||
/** A branch that leaves the scope of a `Handler`. */
|
||||
deprecated class Leave extends UnconditionalBranch, @cil_leave_any { }
|
||||
|
||||
/** An expression that pushes a literal value onto the stack. */
|
||||
deprecated class Literal extends DotNet::Literal, Expr, @cil_literal {
|
||||
/** Gets the pushed value. */
|
||||
override string getValue() { cil_value(this, result) }
|
||||
|
||||
override string getExtra() { result = this.getValue() }
|
||||
}
|
||||
|
||||
/** An integer literal. */
|
||||
deprecated class IntLiteral extends Literal, @cil_ldc_i {
|
||||
override string getExtra() { none() }
|
||||
|
||||
override IntType getType() { exists(result) }
|
||||
}
|
||||
|
||||
/** An expression that pushes a `float`/`Single`. */
|
||||
deprecated class FloatLiteral extends Literal, @cil_ldc_r { }
|
||||
|
||||
/** An expression that pushes a `null` value onto the stack. */
|
||||
deprecated class NullLiteral extends Literal, @cil_ldnull { }
|
||||
|
||||
/** An expression that pushes a string onto the stack. */
|
||||
deprecated class StringLiteral extends Literal, @cil_ldstr { }
|
||||
|
||||
/** A branch with one operand. */
|
||||
deprecated class UnaryBranch extends ConditionalBranch, @cil_unary_jump {
|
||||
override int getPopCount() { result = 1 }
|
||||
|
||||
override int getPushCount() { result = 0 }
|
||||
}
|
||||
|
||||
/** A branch with two operands. */
|
||||
deprecated class BinaryBranch extends ConditionalBranch, @cil_binary_jump {
|
||||
override int getPopCount() { result = 2 }
|
||||
|
||||
override int getPushCount() { result = 0 }
|
||||
}
|
||||
|
||||
/** A call. */
|
||||
deprecated class Call extends Expr, DotNet::Call, @cil_call_any {
|
||||
/** Gets the method that is called. */
|
||||
override Method getTarget() { cil_access(this, result) }
|
||||
|
||||
override Method getARuntimeTarget() { result = this.getTarget().getAnOverrider*() }
|
||||
|
||||
override string getExtra() { result = this.getTarget().getFullyQualifiedName() }
|
||||
|
||||
/**
|
||||
* Gets the return type of the call. Methods that do not return a value
|
||||
* return the `void` type, `System.Void`, although the value of `getPushCount` is
|
||||
* 0 in this case.
|
||||
*/
|
||||
override Type getType() { result = this.getTarget().getReturnType() }
|
||||
|
||||
// The number of items popped/pushed from the stack
|
||||
// depends on the target of the call.
|
||||
override int getPopCount() { result = this.getTarget().getCallPopCount() }
|
||||
|
||||
override int getPushCount() { result = this.getTarget().getCallPushCount() }
|
||||
|
||||
/**
|
||||
* Holds if this is a "tail call", meaning that control does not return to the
|
||||
* calling method.
|
||||
*/
|
||||
predicate isTailCall() {
|
||||
this.getImplementation().getInstruction(this.getIndex() - 1) instanceof Opcodes::Tail
|
||||
}
|
||||
|
||||
/** Holds if this call is virtual and could go to an overriding method. */
|
||||
predicate isVirtual() { none() }
|
||||
|
||||
override Expr getRawArgument(int i) { result = this.getOperand(this.getPopCount() - i - 1) }
|
||||
|
||||
/** Gets the qualifier of this call, if any. */
|
||||
Expr getQualifier() { result = this.getRawArgument(0) and not this.getTarget().isStatic() }
|
||||
|
||||
override Expr getArgument(int i) {
|
||||
if this.getTarget().isStatic()
|
||||
then result = this.getRawArgument(i)
|
||||
else (
|
||||
result = this.getRawArgument(i + 1) and i >= 0
|
||||
)
|
||||
}
|
||||
|
||||
override Expr getArgumentForParameter(DotNet::Parameter param) {
|
||||
exists(int index |
|
||||
result = this.getRawArgument(index) and param = this.getTarget().getRawParameter(index)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/** A tail call. */
|
||||
deprecated class TailCall extends Call {
|
||||
TailCall() { this.isTailCall() }
|
||||
|
||||
override predicate canFlowNext() { none() }
|
||||
}
|
||||
|
||||
/** A call to a static target. */
|
||||
deprecated class StaticCall extends Call {
|
||||
StaticCall() { not this.isVirtual() }
|
||||
}
|
||||
|
||||
/** A call to a virtual target. */
|
||||
deprecated class VirtualCall extends Call {
|
||||
VirtualCall() { this.isVirtual() }
|
||||
}
|
||||
|
||||
/** A read of an array element. */
|
||||
deprecated class ReadArrayElement extends BinaryExpr, @cil_read_array {
|
||||
/** Gets the array being read. */
|
||||
Expr getArray() { result = this.getOperand(1) }
|
||||
|
||||
/** Gets the index into the array. */
|
||||
Expr getArrayIndex() { result = this.getOperand(0) }
|
||||
}
|
||||
|
||||
/** A write of an array element. */
|
||||
deprecated class WriteArrayElement extends Instruction, @cil_write_array {
|
||||
override int getPushCount() { result = 0 }
|
||||
|
||||
override int getPopCount() { result = 3 }
|
||||
}
|
||||
|
||||
/** A `return` statement. */
|
||||
deprecated class Return extends Instruction, @cil_ret {
|
||||
/** Gets the expression being returned, if any. */
|
||||
Expr getExpr() { result = this.getOperand(0) }
|
||||
|
||||
override predicate canFlowNext() { none() }
|
||||
}
|
||||
|
||||
/** A `throw` statement. */
|
||||
deprecated class Throw extends Instruction, DotNet::Throw, @cil_throw_any {
|
||||
override Expr getExpr() { result = this.getOperand(0) }
|
||||
|
||||
/** Gets the type of the exception being thrown. */
|
||||
Type getExceptionType() { result = this.getOperandType(0) }
|
||||
|
||||
override predicate canFlowNext() { none() }
|
||||
}
|
||||
|
||||
/** Stores a value at an address/location. */
|
||||
deprecated class StoreIndirect extends Instruction, @cil_stind {
|
||||
override int getPopCount() { result = 2 }
|
||||
|
||||
/** Gets the location to store the value at. */
|
||||
Expr getAddress() { result = this.getOperand(1) }
|
||||
|
||||
/** Gets the value to store. */
|
||||
Expr getExpr() { result = this.getOperand(0) }
|
||||
}
|
||||
|
||||
/** Loads a value from an address/location. */
|
||||
deprecated class LoadIndirect extends UnaryExpr, @cil_ldind { }
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,296 +0,0 @@
|
||||
/**
|
||||
* Provides classes for methods.
|
||||
*
|
||||
* Methods and implementations are different because there can be several implementations for the same
|
||||
* method in different assemblies. It is not really possible to guarantee which methods will be loaded
|
||||
* at run-time.
|
||||
*/
|
||||
|
||||
private import CIL
|
||||
private import dotnet
|
||||
|
||||
/**
|
||||
* An implementation of a method in an assembly.
|
||||
*/
|
||||
deprecated class MethodImplementation extends EntryPoint, @cil_method_implementation {
|
||||
/** Gets the method of this implementation. */
|
||||
Method getMethod() { cil_method_implementation(this, result, _) }
|
||||
|
||||
override MethodImplementation getImplementation() { result = this }
|
||||
|
||||
/** Gets the location of this implementation. */
|
||||
override Assembly getLocation() { cil_method_implementation(this, _, result) }
|
||||
|
||||
/** Gets the instruction at index `index`. */
|
||||
Instruction getInstruction(int index) { cil_instruction(result, _, index, this) }
|
||||
|
||||
/** Gets the `n`th local variable of this implementation. */
|
||||
LocalVariable getLocalVariable(int n) { cil_local_variable(result, this, n, _) }
|
||||
|
||||
/** Gets a local variable of this implementation, if any. */
|
||||
LocalVariable getALocalVariable() { result = this.getLocalVariable(_) }
|
||||
|
||||
/** Gets an instruction in this implementation, if any. */
|
||||
Instruction getAnInstruction() { result = this.getInstruction(_) }
|
||||
|
||||
/** Gets the total number of instructions in this implementation. */
|
||||
int getNumberOfInstructions() { result = count(this.getAnInstruction()) }
|
||||
|
||||
/** Gets the `i`th handler in this implementation. */
|
||||
Handler getHandler(int i) { result.getImplementation() = this and result.getIndex() = i }
|
||||
|
||||
/** Gets a handler in this implementation, if any. */
|
||||
Handler getAHandler() { result.getImplementation() = this }
|
||||
|
||||
override Instruction getASuccessorType(FlowType t) {
|
||||
t instanceof NormalFlow and result.getImplementation() = this and result.getIndex() = 0
|
||||
}
|
||||
|
||||
/** Gets the maximum stack size of this implementation. */
|
||||
int getStackSize() { cil_method_stack_size(this, result) }
|
||||
|
||||
override string toString() { result = this.getMethod().toString() }
|
||||
|
||||
/** Gets a string representing the disassembly of this implementation. */
|
||||
string getDisassembly() {
|
||||
result =
|
||||
concat(Instruction i |
|
||||
i = this.getAnInstruction()
|
||||
|
|
||||
i.toStringExtra(), ", " order by i.getIndex()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A method, which corresponds to any callable in C#, including constructors,
|
||||
* destructors, operators, accessors and so on.
|
||||
*/
|
||||
deprecated class Method extends DotNet::Callable, Element, Member, TypeContainer, DataFlowNode,
|
||||
CustomModifierReceiver, Parameterizable, @cil_method
|
||||
{
|
||||
/**
|
||||
* Gets a method implementation, if any. Note that there can
|
||||
* be several implementations in different assemblies.
|
||||
*/
|
||||
MethodImplementation getAnImplementation() { result.getMethod() = this }
|
||||
|
||||
/** Gets the "best" implementation of this method, if any. */
|
||||
BestImplementation getImplementation() { result = this.getAnImplementation() }
|
||||
|
||||
override Method getMethod() { result = this }
|
||||
|
||||
override string getName() { cil_method(this, result, _, _) }
|
||||
|
||||
override string getUndecoratedName() { result = this.getName() }
|
||||
|
||||
override string toString() { result = this.getName() }
|
||||
|
||||
override Type getDeclaringType() { cil_method(this, _, result, _) }
|
||||
|
||||
override Location getLocation() { result = Element.super.getLocation() }
|
||||
|
||||
override Location getALocation() { cil_method_location(this.getUnboundMethod+(), result) }
|
||||
|
||||
override MethodParameter getParameter(int n) {
|
||||
if this.isStatic()
|
||||
then result = this.getRawParameter(n)
|
||||
else (
|
||||
result = this.getRawParameter(n + 1) and n >= 0
|
||||
)
|
||||
}
|
||||
|
||||
override Type getType() { result = this.getReturnType() }
|
||||
|
||||
/** Gets the return type of this method. */
|
||||
override Type getReturnType() { cil_method(this, _, _, result) }
|
||||
|
||||
/** Holds if the return type is `void`. */
|
||||
predicate returnsVoid() { this.getReturnType() instanceof VoidType }
|
||||
|
||||
/** Gets the number of stack items pushed in a call to this method. */
|
||||
int getCallPushCount() { if this.returnsVoid() then result = 0 else result = 1 }
|
||||
|
||||
/** Gets the number of stack items popped in a call to this method. */
|
||||
int getCallPopCount() { result = count(this.getRawParameter(_)) }
|
||||
|
||||
/** Gets a method called by this method. */
|
||||
Method getACallee() { result = this.getImplementation().getAnInstruction().(Call).getTarget() }
|
||||
|
||||
/** Holds if this method is `virtual`. */
|
||||
predicate isVirtual() { cil_virtual(this) }
|
||||
|
||||
/** Holds if the name of this method is special, for example an operator. */
|
||||
predicate isSpecial() { cil_specialname(this) }
|
||||
|
||||
/** Holds of this method is marked as secure. */
|
||||
predicate isSecureObject() { cil_requiresecobject(this) }
|
||||
|
||||
/** Holds if the method does not override an existing method. */
|
||||
predicate isNew() { cil_newslot(this) }
|
||||
|
||||
override predicate isStatic() { cil_static(this) }
|
||||
|
||||
/** Gets the unbound declaration of this method, or the method itself. */
|
||||
Method getUnboundMethod() { cil_method_source_declaration(this, result) }
|
||||
|
||||
override Method getUnboundDeclaration() { result = this.getUnboundMethod() }
|
||||
|
||||
/** Holds if this method is an instance constructor. */
|
||||
predicate isInstanceConstructor() { this.isSpecial() and this.getName() = ".ctor" }
|
||||
|
||||
/** Holds if this method is a static class constructor. */
|
||||
predicate isStaticConstructor() { this.isSpecial() and this.getName() = ".cctor" }
|
||||
|
||||
/** Holds if this method is a constructor (static or instance). */
|
||||
predicate isConstructor() { this.isStaticConstructor() or this.isInstanceConstructor() }
|
||||
|
||||
/** Holds if this method is a destructor/finalizer. */
|
||||
predicate isFinalizer() {
|
||||
this.getOverriddenMethod*().hasFullyQualifiedName("System", "Object", "Finalize")
|
||||
}
|
||||
|
||||
/** Holds if this method is an operator. */
|
||||
predicate isOperator() { this.isSpecial() and this.getName().matches("op\\_%") }
|
||||
|
||||
/** Holds if this method is a getter. */
|
||||
predicate isGetter() { this.isSpecial() and this.getName().matches("get\\_%") }
|
||||
|
||||
/** Holds if this method is a setter. */
|
||||
predicate isSetter() { this.isSpecial() and this.getName().matches("set\\_%") }
|
||||
|
||||
/** Holds if this method is an adder/add event accessor. */
|
||||
predicate isAdder() { this.isSpecial() and this.getName().matches("add\\_%") }
|
||||
|
||||
/** Holds if this method is a remover/remove event accessor. */
|
||||
predicate isRemove() { this.isSpecial() and this.getName().matches("remove\\_%") }
|
||||
|
||||
/** Holds if this method is an implicit conversion operator. */
|
||||
predicate isImplicitConversion() { this.isSpecial() and this.getName() = "op_Implicit" }
|
||||
|
||||
/** Holds if this method is an explicit conversion operator. */
|
||||
predicate isExplicitConversion() { this.isSpecial() and this.getName() = "op_Explicit" }
|
||||
|
||||
/** Holds if this method is a conversion operator. */
|
||||
predicate isConversion() { this.isImplicitConversion() or this.isExplicitConversion() }
|
||||
|
||||
/**
|
||||
* Gets a method that is overridden, either in a base class
|
||||
* or in an interface.
|
||||
*/
|
||||
Method getOverriddenMethod() { cil_implements(this, result) }
|
||||
|
||||
/** Gets a method that overrides this method, if any. */
|
||||
final Method getAnOverrider() { result.getOverriddenMethod() = this }
|
||||
|
||||
override predicate hasBody() { exists(this.getImplementation()) }
|
||||
|
||||
override predicate canReturn(DotNet::Expr expr) {
|
||||
exists(Return ret | ret.getImplementation() = this.getImplementation() and expr = ret.getExpr())
|
||||
}
|
||||
}
|
||||
|
||||
/** A destructor/finalizer. */
|
||||
deprecated class Destructor extends Method, DotNet::Destructor {
|
||||
Destructor() { this.isFinalizer() }
|
||||
}
|
||||
|
||||
/** A constructor. */
|
||||
deprecated class Constructor extends Method, DotNet::Constructor {
|
||||
Constructor() { this.isConstructor() }
|
||||
}
|
||||
|
||||
/** A static/class constructor. */
|
||||
deprecated class StaticConstructor extends Constructor {
|
||||
StaticConstructor() { this.isStaticConstructor() }
|
||||
}
|
||||
|
||||
/** An instance constructor. */
|
||||
deprecated class InstanceConstructor extends Constructor {
|
||||
InstanceConstructor() { this.isInstanceConstructor() }
|
||||
}
|
||||
|
||||
/** A method that always returns the `this` parameter. */
|
||||
deprecated class ChainingMethod extends Method {
|
||||
ChainingMethod() {
|
||||
forex(Return ret | ret = this.getImplementation().getAnInstruction() |
|
||||
ret.getExpr() instanceof ThisAccess
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/** An accessor. */
|
||||
abstract deprecated class Accessor extends Method {
|
||||
/** Gets the property declaring this accessor. */
|
||||
abstract Property getProperty();
|
||||
}
|
||||
|
||||
/** A getter. */
|
||||
deprecated class Getter extends Accessor {
|
||||
Getter() { cil_getter(_, this) }
|
||||
|
||||
override Property getProperty() { cil_getter(result, this) }
|
||||
}
|
||||
|
||||
/**
|
||||
* A method that does nothing but retrieve a field.
|
||||
* Note that this is not necessarily a property getter.
|
||||
*/
|
||||
deprecated class TrivialGetter extends Method {
|
||||
TrivialGetter() {
|
||||
exists(MethodImplementation impl | impl = this.getAnImplementation() |
|
||||
impl.getInstruction(0) instanceof ThisAccess and
|
||||
impl.getInstruction(1) instanceof FieldReadAccess and
|
||||
impl.getInstruction(2) instanceof Return
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets the underlying field of this getter. */
|
||||
Field getField() {
|
||||
this.getImplementation().getAnInstruction().(FieldReadAccess).getTarget() = result
|
||||
}
|
||||
}
|
||||
|
||||
/** A setter. */
|
||||
deprecated class Setter extends Accessor {
|
||||
Setter() { cil_setter(_, this) }
|
||||
|
||||
override Property getProperty() { cil_setter(result, this) }
|
||||
|
||||
/** Holds if this setter is an `init` accessor. */
|
||||
predicate isInitOnly() {
|
||||
exists(Type t | t.hasFullyQualifiedName("System.Runtime.CompilerServices", "IsExternalInit") |
|
||||
this.hasRequiredCustomModifier(t)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A method that does nothing but set a field.
|
||||
* This is not necessarily a property setter.
|
||||
*/
|
||||
deprecated class TrivialSetter extends Method {
|
||||
TrivialSetter() {
|
||||
exists(MethodImplementation impl | impl = this.getAnImplementation() |
|
||||
impl.getInstruction(0) instanceof ThisAccess and
|
||||
impl.getInstruction(1).(ParameterReadAccess).getTarget().getIndex() = 1 and
|
||||
impl.getInstruction(2) instanceof FieldWriteAccess
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets the underlying field of this setter. */
|
||||
Field getField() {
|
||||
result = this.getImplementation().getAnInstruction().(FieldWriteAccess).getTarget()
|
||||
}
|
||||
}
|
||||
|
||||
/** An alias for `Method` for compatibility with the C# data model. */
|
||||
deprecated class Callable = Method;
|
||||
|
||||
/** An operator. */
|
||||
deprecated class Operator extends Method {
|
||||
Operator() { this.isOperator() }
|
||||
|
||||
/** Gets the name of the implementing method (for compatibility with C# data model). */
|
||||
string getFunctionName() { result = this.getName() }
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
/**
|
||||
* Provides `Parameterizable` class.
|
||||
*/
|
||||
|
||||
private import CIL
|
||||
private import dotnet
|
||||
|
||||
/**
|
||||
* A parameterizable entity, such as `FunctionPointerType` or `Method`.
|
||||
*/
|
||||
deprecated class Parameterizable extends DotNet::Parameterizable, Element, @cil_parameterizable {
|
||||
override Parameter getRawParameter(int n) { cil_parameter(result, this, n, _) }
|
||||
|
||||
override Parameter getParameter(int n) { cil_parameter(result, this, n, _) }
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
/**
|
||||
* Provides the module `Ssa` for working with static single assignment (SSA) form.
|
||||
*/
|
||||
|
||||
private import CIL
|
||||
|
||||
/**
|
||||
* Provides classes for working with static single assignment (SSA) form.
|
||||
*/
|
||||
deprecated module Ssa {
|
||||
private import internal.SsaImpl as SsaImpl
|
||||
|
||||
/** An SSA definition. */
|
||||
class Definition extends SsaImpl::Definition {
|
||||
/** Gets a read of this SSA definition. */
|
||||
final ReadAccess getARead() { result = SsaImpl::getARead(this) }
|
||||
|
||||
/** Gets the underlying variable update, if any. */
|
||||
final VariableUpdate getVariableUpdate() {
|
||||
exists(BasicBlock bb, int i |
|
||||
result.updatesAt(bb, i) and
|
||||
this.definesAt(result.getVariable(), bb, i)
|
||||
)
|
||||
}
|
||||
|
||||
private Definition getAPhiInput() { result = this.(PhiNode).getAnInput() }
|
||||
|
||||
/**
|
||||
* Gets a definition that ultimately defines this SSA definition and is
|
||||
* not itself a phi node.
|
||||
*/
|
||||
final Definition getAnUltimateDefinition() {
|
||||
result = this.getAPhiInput*() and
|
||||
not result instanceof PhiNode
|
||||
}
|
||||
|
||||
/** Gets the location of this SSA definition. */
|
||||
override Location getLocation() { result = this.getVariableUpdate().getLocation() }
|
||||
}
|
||||
|
||||
/** A phi node. */
|
||||
class PhiNode extends SsaImpl::PhiNode, Definition {
|
||||
final override Location getLocation() { result = this.getBasicBlock().getLocation() }
|
||||
|
||||
/** Gets an input to this phi node. */
|
||||
final Definition getAnInput() { result = SsaImpl::getAPhiInput(this) }
|
||||
}
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
/**
|
||||
* Provides classes and predicates for identifying stub code.
|
||||
*/
|
||||
|
||||
import CIL
|
||||
|
||||
/**
|
||||
* The average number of instructions per method,
|
||||
* below which an assembly is probably a stub.
|
||||
*/
|
||||
deprecated private float stubInstructionThreshold() { result = 5.1 }
|
||||
|
||||
cached
|
||||
private module Cached {
|
||||
/**
|
||||
* A simple heuristic for determining whether an assembly is a
|
||||
* reference assembly where the method bodies have dummy implementations.
|
||||
* Look at the average number of instructions per method.
|
||||
*/
|
||||
cached
|
||||
deprecated predicate assemblyIsStubImpl(Assembly asm) {
|
||||
exists(int totalInstructions, int totalImplementations |
|
||||
totalInstructions = count(Instruction i | i.getImplementation().getLocation() = asm) and
|
||||
totalImplementations =
|
||||
count(MethodImplementation i | i.getImplementation().getLocation() = asm) and
|
||||
totalInstructions.(float) / totalImplementations.(float) < stubInstructionThreshold()
|
||||
)
|
||||
}
|
||||
|
||||
cached
|
||||
deprecated predicate bestImplementation(MethodImplementation mi) {
|
||||
exists(Assembly asm |
|
||||
asm = mi.getLocation() and
|
||||
(assemblyIsStubImpl(asm) implies asm.getFile().extractedQlTest()) and
|
||||
mi =
|
||||
max(MethodImplementation impl |
|
||||
mi.getMethod() = impl.getMethod()
|
||||
|
|
||||
impl order by impl.getNumberOfInstructions(), impl.getLocation().getFile().toString() desc
|
||||
) and
|
||||
exists(mi.getAnInstruction())
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private import Cached
|
||||
|
||||
deprecated predicate assemblyIsStub = assemblyIsStubImpl/1;
|
||||
|
||||
/**
|
||||
* A method implementation that is the "best" one for a particular method,
|
||||
* if there are several potential implementations to choose between, and
|
||||
* excludes implementations that are probably from stub/reference assemblies.
|
||||
*/
|
||||
deprecated class BestImplementation extends MethodImplementation {
|
||||
BestImplementation() { bestImplementation(this) }
|
||||
}
|
||||
@@ -1,125 +0,0 @@
|
||||
/**
|
||||
* Provides classes for types and associated classes.
|
||||
*/
|
||||
|
||||
import CIL
|
||||
private import dotnet
|
||||
private import semmle.code.csharp.commons.QualifiedName
|
||||
|
||||
/**
|
||||
* Something that contains other types.
|
||||
*
|
||||
* Either a type (`Type`), a method(`Method`), or a namespace (`Namespace`).
|
||||
*/
|
||||
deprecated class TypeContainer extends DotNet::NamedElement, @cil_type_container {
|
||||
/** Gets the parent of this type container, if any. */
|
||||
TypeContainer getParent() { none() }
|
||||
|
||||
override string toStringWithTypes() { result = this.getLabel() }
|
||||
}
|
||||
|
||||
/** A namespace. */
|
||||
deprecated class Namespace extends DotNet::Namespace, TypeContainer, @namespace {
|
||||
override string toString() { result = this.getFullName() }
|
||||
|
||||
override Namespace getParent() { result = this.getParentNamespace() }
|
||||
|
||||
override Namespace getParentNamespace() { parent_namespace(this, result) }
|
||||
|
||||
override Location getLocation() { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A type.
|
||||
*/
|
||||
deprecated class Type extends DotNet::Type, Declaration, TypeContainer, @cil_type {
|
||||
override TypeContainer getParent() { cil_type(this, _, _, result, _) }
|
||||
|
||||
override string getName() { cil_type(this, result, _, _, _) }
|
||||
|
||||
override string toString() { result = this.getName() }
|
||||
|
||||
/** Gets the containing type of this type, if any. */
|
||||
override Type getDeclaringType() { result = this.getParent() }
|
||||
|
||||
/** Gets a member of this type, if any. */
|
||||
Member getAMember() { result.getDeclaringType() = this }
|
||||
|
||||
/**
|
||||
* Gets the unbound generic type of this type, or `this` if the type
|
||||
* is already unbound.
|
||||
*/
|
||||
Type getUnboundType() { cil_type(this, _, _, _, result) }
|
||||
|
||||
deprecated override predicate hasQualifiedName(string qualifier, string name) {
|
||||
name = this.getName() and
|
||||
exists(string pqualifier, string pname | this.getParent().hasQualifiedName(pqualifier, pname) |
|
||||
qualifier = getQualifiedName(pqualifier, pname)
|
||||
)
|
||||
}
|
||||
|
||||
override predicate hasFullyQualifiedName(string qualifier, string name) {
|
||||
name = this.getName() and
|
||||
exists(string pqualifier, string pname |
|
||||
this.getParent().hasFullyQualifiedName(pqualifier, pname)
|
||||
|
|
||||
qualifier = getQualifiedName(pqualifier, pname)
|
||||
)
|
||||
}
|
||||
|
||||
override Location getALocation() { cil_type_location(this.getUnboundDeclaration(), result) }
|
||||
|
||||
/** Holds if this type is a class. */
|
||||
predicate isClass() { cil_class(this) }
|
||||
|
||||
/** Holds if this type is an interface. */
|
||||
predicate isInterface() { cil_interface(this) }
|
||||
|
||||
/**
|
||||
* Holds if this type is a member of the `System` namespace and has the name
|
||||
* `name`.
|
||||
*/
|
||||
predicate isSystemType(string name) {
|
||||
exists(Namespace system | this.getParent() = system |
|
||||
system.getName() = "System" and
|
||||
system.getParentNamespace().getName() = "" and
|
||||
name = this.getName()
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if this type is an `enum`. */
|
||||
predicate isEnum() { this.getBaseClass().isSystemType("Enum") }
|
||||
|
||||
/** Holds if this type is public. */
|
||||
predicate isPublic() { cil_public(this) }
|
||||
|
||||
/** Holds if this type is private. */
|
||||
predicate isPrivate() { cil_private(this) }
|
||||
|
||||
/** Gets the machine type used to store this type. */
|
||||
Type getUnderlyingType() { result = this }
|
||||
|
||||
// Class hierarchy
|
||||
/** Gets the immediate base class of this class, if any. */
|
||||
Type getBaseClass() { cil_base_class(this, result) }
|
||||
|
||||
/** Gets an immediate base interface of this class, if any. */
|
||||
Type getABaseInterface() { cil_base_interface(this, result) }
|
||||
|
||||
/** Gets an immediate base type of this type, if any. */
|
||||
Type getABaseType() { result = this.getBaseClass() or result = this.getABaseInterface() }
|
||||
|
||||
/** Gets an immediate subtype of this type, if any. */
|
||||
Type getASubtype() { result.getABaseType() = this }
|
||||
|
||||
/** Gets the namespace directly containing this type, if any. */
|
||||
Namespace getNamespace() { result = this.getParent() }
|
||||
|
||||
/**
|
||||
* Gets an index for implicit conversions. A type can be converted to another numeric type
|
||||
* of a higher index.
|
||||
*/
|
||||
int getConversionIndex() { result = 0 }
|
||||
|
||||
override Type getUnboundDeclaration() { cil_type(this, _, _, _, result) }
|
||||
}
|
||||
@@ -1,318 +0,0 @@
|
||||
/**
|
||||
* Provides classes representing various types.
|
||||
*/
|
||||
|
||||
private import CIL
|
||||
private import dotnet
|
||||
|
||||
/** A type parameter. */
|
||||
deprecated class TypeParameter extends DotNet::TypeParameter, Type, @cil_typeparameter {
|
||||
override int getIndex() { cil_type_parameter(_, result, this) }
|
||||
|
||||
/** Gets the generic type/method declaring this type parameter. */
|
||||
TypeContainer getGeneric() { cil_type_parameter(result, _, this) }
|
||||
|
||||
override Location getLocation() { result = this.getParent().getLocation() }
|
||||
|
||||
/** Holds if this type parameter has the `new` constraint. */
|
||||
predicate isDefaultConstructible() { cil_typeparam_new(this) }
|
||||
|
||||
/** Holds if this type parameter has the `struct` constraint. */
|
||||
predicate isStruct() { cil_typeparam_struct(this) }
|
||||
|
||||
override predicate isClass() { cil_typeparam_class(this) }
|
||||
|
||||
/** Holds if this type parameter is covariant/is `in`. */
|
||||
predicate isCovariant() { cil_typeparam_covariant(this) }
|
||||
|
||||
/** Holds if this type parameter is contravariant/is `out`. */
|
||||
predicate isContravariant() { cil_typeparam_contravariant(this) }
|
||||
|
||||
/** Gets a type constraint on this type parameter, if any. */
|
||||
Type getATypeConstraint() { cil_typeparam_constraint(this, result) }
|
||||
}
|
||||
|
||||
/** A value or reference type. */
|
||||
deprecated class ValueOrRefType extends DotNet::ValueOrRefType, Type, @cil_valueorreftype {
|
||||
override ValueOrRefType getDeclaringType() { result = this.getParent() }
|
||||
|
||||
override string getUndecoratedName() { cil_type(this, result, _, _, _) }
|
||||
|
||||
override Namespace getDeclaringNamespace() { result = this.getNamespace() }
|
||||
|
||||
override ValueOrRefType getABaseType() { result = Type.super.getABaseType() }
|
||||
}
|
||||
|
||||
/** An `enum`. */
|
||||
deprecated class Enum extends ValueOrRefType {
|
||||
Enum() { this.isEnum() }
|
||||
|
||||
override IntegralType getUnderlyingType() {
|
||||
cil_enum_underlying_type(this, result)
|
||||
or
|
||||
not cil_enum_underlying_type(this, _) and
|
||||
result instanceof IntType
|
||||
}
|
||||
}
|
||||
|
||||
/** A `class`. */
|
||||
deprecated class Class extends ValueOrRefType {
|
||||
Class() { this.isClass() }
|
||||
}
|
||||
|
||||
/** An `interface`. */
|
||||
deprecated class Interface extends ValueOrRefType {
|
||||
Interface() { this.isInterface() }
|
||||
}
|
||||
|
||||
/** An array. */
|
||||
deprecated class ArrayType extends DotNet::ArrayType, Type, @cil_array_type {
|
||||
override Type getElementType() { cil_array_type(this, result, _) }
|
||||
|
||||
/** Gets the rank of this array. */
|
||||
int getRank() { cil_array_type(this, _, result) }
|
||||
|
||||
override string toStringWithTypes() { result = DotNet::ArrayType.super.toStringWithTypes() }
|
||||
|
||||
override Location getLocation() { result = this.getElementType().getLocation() }
|
||||
|
||||
override ValueOrRefType getABaseType() { result = Type.super.getABaseType() }
|
||||
}
|
||||
|
||||
/** A pointer type. */
|
||||
deprecated class PointerType extends DotNet::PointerType, PrimitiveType, @cil_pointer_type {
|
||||
override Type getReferentType() { cil_pointer_type(this, result) }
|
||||
|
||||
override IntType getUnderlyingType() { any() }
|
||||
|
||||
override string getName() { result = DotNet::PointerType.super.getName() }
|
||||
|
||||
override Location getLocation() { result = this.getReferentType().getLocation() }
|
||||
|
||||
override string toString() { result = DotNet::PointerType.super.toString() }
|
||||
|
||||
override string toStringWithTypes() { result = DotNet::PointerType.super.toStringWithTypes() }
|
||||
}
|
||||
|
||||
/** A primitive type, built into the runtime. */
|
||||
abstract deprecated class PrimitiveType extends Type { }
|
||||
|
||||
/**
|
||||
* A primitive numeric type.
|
||||
* Either an integral type (`IntegralType`) or a floating point type (`FloatingPointType`).
|
||||
*/
|
||||
abstract deprecated class NumericType extends PrimitiveType, ValueOrRefType { }
|
||||
|
||||
/** A floating point type. Either single precision (`FloatType`) or double precision (`DoubleType`). */
|
||||
abstract deprecated class FloatingPointType extends NumericType { }
|
||||
|
||||
/**
|
||||
* An integral numeric type. Either a signed integral type (`SignedIntegralType`)
|
||||
* or an unsigned integral type (`UnsignedIntegralType`).
|
||||
*/
|
||||
abstract deprecated class IntegralType extends NumericType { }
|
||||
|
||||
/** A signed integral type. */
|
||||
abstract deprecated class SignedIntegralType extends IntegralType { }
|
||||
|
||||
/** An unsigned integral type. */
|
||||
abstract deprecated class UnsignedIntegralType extends IntegralType { }
|
||||
|
||||
/** The `void` type, `System.Void`. */
|
||||
deprecated class VoidType extends PrimitiveType {
|
||||
VoidType() { this.isSystemType("Void") }
|
||||
|
||||
override string toString() { result = "void" }
|
||||
|
||||
override string toStringWithTypes() { result = "void" }
|
||||
}
|
||||
|
||||
/** The type `System.Int32`. */
|
||||
deprecated class IntType extends SignedIntegralType {
|
||||
IntType() { this.isSystemType("Int32") }
|
||||
|
||||
override string toStringWithTypes() { result = "int" }
|
||||
|
||||
override int getConversionIndex() { result = 8 }
|
||||
|
||||
override IntType getUnderlyingType() { result = this }
|
||||
}
|
||||
|
||||
/** The type `System.IntPtr`. */
|
||||
deprecated class IntPtrType extends PrimitiveType {
|
||||
IntPtrType() { this.isSystemType("IntPtr") }
|
||||
|
||||
override IntType getUnderlyingType() { any() }
|
||||
}
|
||||
|
||||
/** The type `System.UIntPtr`. */
|
||||
deprecated class UIntPtrType extends PrimitiveType {
|
||||
UIntPtrType() { this.isSystemType("UIntPtr") }
|
||||
|
||||
override IntType getUnderlyingType() { any() }
|
||||
}
|
||||
|
||||
/** The type `System.UInt32`. */
|
||||
deprecated class UIntType extends UnsignedIntegralType {
|
||||
UIntType() { this.isSystemType("UInt32") }
|
||||
|
||||
override string toStringWithTypes() { result = "uint" }
|
||||
|
||||
override int getConversionIndex() { result = 7 }
|
||||
|
||||
override IntType getUnderlyingType() { any() }
|
||||
}
|
||||
|
||||
/** The type `System.SByte`. */
|
||||
deprecated class SByteType extends SignedIntegralType {
|
||||
SByteType() { this.isSystemType("SByte") }
|
||||
|
||||
override string toStringWithTypes() { result = "sbyte" }
|
||||
|
||||
override int getConversionIndex() { result = 2 }
|
||||
}
|
||||
|
||||
/** The type `System.Byte`. */
|
||||
deprecated class ByteType extends UnsignedIntegralType {
|
||||
ByteType() { this.isSystemType("Byte") }
|
||||
|
||||
override string toStringWithTypes() { result = "byte" }
|
||||
|
||||
override int getConversionIndex() { result = 1 }
|
||||
|
||||
override SByteType getUnderlyingType() { any() }
|
||||
}
|
||||
|
||||
/** The type `System.Int16`. */
|
||||
deprecated class ShortType extends SignedIntegralType {
|
||||
ShortType() { this.isSystemType("Int16") }
|
||||
|
||||
override string toStringWithTypes() { result = "short" }
|
||||
|
||||
override int getConversionIndex() { result = 4 }
|
||||
}
|
||||
|
||||
/** The type `System.UInt16`. */
|
||||
deprecated class UShortType extends UnsignedIntegralType {
|
||||
UShortType() { this.isSystemType("UInt16") }
|
||||
|
||||
override string toStringWithTypes() { result = "ushort" }
|
||||
|
||||
override int getConversionIndex() { result = 3 }
|
||||
|
||||
override ShortType getUnderlyingType() { any() }
|
||||
}
|
||||
|
||||
/** The type `System.Int64`. */
|
||||
deprecated class LongType extends SignedIntegralType {
|
||||
LongType() { this.isSystemType("Int64") }
|
||||
|
||||
override string toStringWithTypes() { result = "long" }
|
||||
|
||||
override int getConversionIndex() { result = 10 }
|
||||
}
|
||||
|
||||
/** The type `System.UInt64`. */
|
||||
deprecated class ULongType extends UnsignedIntegralType {
|
||||
ULongType() { this.isSystemType("UInt64") }
|
||||
|
||||
override string toStringWithTypes() { result = "ulong" }
|
||||
|
||||
override int getConversionIndex() { result = 9 }
|
||||
|
||||
override LongType getUnderlyingType() { any() }
|
||||
}
|
||||
|
||||
/** The type `System.Decimal`. */
|
||||
deprecated class DecimalType extends SignedIntegralType {
|
||||
DecimalType() { this.isSystemType("Decimal") }
|
||||
|
||||
override string toStringWithTypes() { result = "decimal" }
|
||||
|
||||
override int getConversionIndex() { result = 13 }
|
||||
}
|
||||
|
||||
/** The type `System.String`. */
|
||||
deprecated class StringType extends PrimitiveType, ValueOrRefType {
|
||||
StringType() { this.isSystemType("String") }
|
||||
|
||||
override string toStringWithTypes() { result = "string" }
|
||||
}
|
||||
|
||||
/** The type `System.Object`. */
|
||||
deprecated class ObjectType extends ValueOrRefType {
|
||||
ObjectType() { this.isSystemType("Object") }
|
||||
|
||||
override string toStringWithTypes() { result = "object" }
|
||||
}
|
||||
|
||||
/** The type `System.Boolean`. */
|
||||
deprecated class BoolType extends PrimitiveType, ValueOrRefType {
|
||||
BoolType() { this.isSystemType("Boolean") }
|
||||
|
||||
override string toStringWithTypes() { result = "bool" }
|
||||
|
||||
override IntType getUnderlyingType() { any() }
|
||||
}
|
||||
|
||||
/** The type `System.Double`. */
|
||||
deprecated class DoubleType extends FloatingPointType {
|
||||
DoubleType() { this.isSystemType("Double") }
|
||||
|
||||
override string toStringWithTypes() { result = "double" }
|
||||
|
||||
override int getConversionIndex() { result = 12 }
|
||||
}
|
||||
|
||||
/** The type `System.Single`. */
|
||||
deprecated class FloatType extends FloatingPointType {
|
||||
FloatType() { this.isSystemType("Single") }
|
||||
|
||||
override string toStringWithTypes() { result = "float" }
|
||||
|
||||
override int getConversionIndex() { result = 4 }
|
||||
}
|
||||
|
||||
/** The type `System.Char`. */
|
||||
deprecated class CharType extends IntegralType {
|
||||
CharType() { this.isSystemType("Char") }
|
||||
|
||||
override string toStringWithTypes() { result = "char" }
|
||||
|
||||
override int getConversionIndex() { result = 6 }
|
||||
|
||||
override IntType getUnderlyingType() { any() }
|
||||
}
|
||||
|
||||
/** The type `System.Type`. */
|
||||
deprecated class SystemType extends ValueOrRefType {
|
||||
SystemType() { this.isSystemType("Type") }
|
||||
}
|
||||
|
||||
/**
|
||||
* A function pointer type, for example
|
||||
*
|
||||
* ```csharp
|
||||
* delegate*<int, void>
|
||||
* ```
|
||||
*/
|
||||
deprecated class FunctionPointerType extends Type, CustomModifierReceiver, Parameterizable,
|
||||
@cil_function_pointer_type
|
||||
{
|
||||
/** Gets the return type of this function pointer. */
|
||||
Type getReturnType() { cil_function_pointer_return_type(this, result) }
|
||||
|
||||
/** Gets the calling convention. */
|
||||
int getCallingConvention() { cil_function_pointer_calling_conventions(this, result) }
|
||||
|
||||
/** Holds if the return type is `void`. */
|
||||
predicate returnsVoid() { this.getReturnType() instanceof VoidType }
|
||||
|
||||
/** Gets the number of stack items pushed in a call to this method. */
|
||||
int getCallPushCount() { if this.returnsVoid() then result = 0 else result = 1 }
|
||||
|
||||
/** Gets the number of stack items popped in a call to this method. */
|
||||
int getCallPopCount() { result = count(this.getRawParameter(_)) }
|
||||
|
||||
override string getLabel() { result = this.getName() }
|
||||
}
|
||||
@@ -1,160 +0,0 @@
|
||||
/**
|
||||
* Provides classes for variables.
|
||||
*/
|
||||
|
||||
private import CIL
|
||||
private import dotnet
|
||||
|
||||
/** A variable. Either a stack variable (`StackVariable`) or a field (`Field`). */
|
||||
deprecated class Variable extends DotNet::Variable, Declaration, DataFlowNode, @cil_variable {
|
||||
/** Gets the type of this variable. */
|
||||
override Type getType() { none() }
|
||||
|
||||
/** Gets a textual representation of this variable including type information. */
|
||||
override string toStringWithTypes() { none() }
|
||||
|
||||
/** Gets an access to this variable, if any. */
|
||||
VariableAccess getAnAccess() { result.getTarget() = this }
|
||||
|
||||
/** Gets a read access to this variable, if any. */
|
||||
ReadAccess getARead() { result = this.getAnAccess() }
|
||||
|
||||
/** Gets a write access to this variable, if any. */
|
||||
WriteAccess getAWrite() { result = this.getAnAccess() }
|
||||
|
||||
override string toString() { result = Declaration.super.toString() }
|
||||
|
||||
override Location getLocation() { result = Declaration.super.getLocation() }
|
||||
}
|
||||
|
||||
/** A stack variable. Either a local variable (`LocalVariable`) or a parameter (`Parameter`). */
|
||||
deprecated class StackVariable extends Variable, @cil_stack_variable {
|
||||
deprecated override predicate hasQualifiedName(string qualifier, string name) { none() }
|
||||
|
||||
override predicate hasFullyQualifiedName(string qualifier, string name) { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A local variable.
|
||||
*
|
||||
* Each method in CIL has a number of typed local variables, in addition to the evaluation stack.
|
||||
*/
|
||||
deprecated class LocalVariable extends StackVariable, @cil_local_variable {
|
||||
override string toString() {
|
||||
result =
|
||||
"Local variable " + this.getIndex() + " of method " +
|
||||
this.getImplementation().getMethod().getName()
|
||||
}
|
||||
|
||||
/** Gets the method implementation defining this local variable. */
|
||||
MethodImplementation getImplementation() { this = result.getALocalVariable() }
|
||||
|
||||
/** Gets the index number of this local variable. This is not usually significant. */
|
||||
int getIndex() { this = this.getImplementation().getLocalVariable(result) }
|
||||
|
||||
override Type getType() { cil_local_variable(this, _, _, result) }
|
||||
|
||||
override Location getLocation() { result = this.getImplementation().getLocation() }
|
||||
|
||||
override Method getMethod() { result = this.getImplementation().getMethod() }
|
||||
}
|
||||
|
||||
/** A parameter of a `Method` or `FunctionPointerType`. */
|
||||
deprecated class Parameter extends DotNet::Parameter, CustomModifierReceiver, @cil_parameter {
|
||||
override Parameterizable getDeclaringElement() { cil_parameter(this, result, _, _) }
|
||||
|
||||
/** Gets the index of this parameter. */
|
||||
int getIndex() { cil_parameter(this, _, result, _) }
|
||||
|
||||
override string toString() {
|
||||
result = "Parameter " + this.getIndex() + " of " + this.getDeclaringElement().getName()
|
||||
}
|
||||
|
||||
override Type getType() { cil_parameter(this, _, _, result) }
|
||||
|
||||
/**
|
||||
* Holds if this parameter has an "out" flag, meaning that it will
|
||||
* be passed by reference and written to.
|
||||
*/
|
||||
predicate hasOutFlag() { cil_parameter_out(this) }
|
||||
|
||||
/**
|
||||
* Holds if this parameter has an "in" flag, meaning that it will
|
||||
* be passed by reference and may be read from and written to.
|
||||
*/
|
||||
predicate hasInFlag() { cil_parameter_in(this) }
|
||||
|
||||
/** Holds if this parameter has C# `out` semantics. */
|
||||
override predicate isOut() { this.hasOutFlag() and not this.hasInFlag() }
|
||||
|
||||
/** Holds if this parameter has C# `ref` semantics. */
|
||||
override predicate isRef() { this.hasOutFlag() and this.hasInFlag() }
|
||||
|
||||
override string toStringWithTypes() {
|
||||
result = this.getPrefix() + this.getType().toStringWithTypes()
|
||||
}
|
||||
|
||||
private string getPrefix() {
|
||||
if this.isOut()
|
||||
then result = "out "
|
||||
else
|
||||
if this.isRef()
|
||||
then result = "ref "
|
||||
else result = ""
|
||||
}
|
||||
|
||||
override Location getLocation() { result = this.getDeclaringElement().getLocation() }
|
||||
}
|
||||
|
||||
/** A method parameter. */
|
||||
deprecated class MethodParameter extends Parameter, StackVariable {
|
||||
/** Gets the method declaring this parameter. */
|
||||
override Method getMethod() { this = result.getARawParameter() }
|
||||
|
||||
override ParameterAccess getAnAccess() { result.getTarget() = this }
|
||||
|
||||
/** Gets a parameter in an overridden method. */
|
||||
MethodParameter getOverriddenParameter() {
|
||||
result = this.getMethod().getOverriddenMethod().getRawParameter(this.getRawPosition())
|
||||
}
|
||||
|
||||
override MethodParameter getUnboundDeclaration() {
|
||||
result = this.getMethod().getUnboundDeclaration().getRawParameter(this.getRawPosition())
|
||||
}
|
||||
|
||||
override string toString() { result = Parameter.super.toString() }
|
||||
|
||||
override string toStringWithTypes() { result = Parameter.super.toStringWithTypes() }
|
||||
|
||||
override Type getType() { result = Parameter.super.getType() }
|
||||
|
||||
override Location getLocation() { result = Parameter.super.getLocation() }
|
||||
}
|
||||
|
||||
/** A parameter corresponding to `this`. */
|
||||
deprecated class ThisParameter extends MethodParameter {
|
||||
ThisParameter() {
|
||||
not this.getMethod().isStatic() and
|
||||
this.getIndex() = 0
|
||||
}
|
||||
}
|
||||
|
||||
/** A field. */
|
||||
deprecated class Field extends DotNet::Field, Variable, Member, CustomModifierReceiver, @cil_field {
|
||||
override string toString() { result = this.getName() }
|
||||
|
||||
override string toStringWithTypes() {
|
||||
result = this.getDeclaringType().toStringWithTypes() + "." + this.getName()
|
||||
}
|
||||
|
||||
override string getName() { cil_field(this, _, result, _) }
|
||||
|
||||
override Type getType() { cil_field(this, _, _, result) }
|
||||
|
||||
override ValueOrRefType getDeclaringType() { cil_field(this, result, _, _) }
|
||||
|
||||
override Location getLocation() { result = this.getDeclaringType().getLocation() }
|
||||
|
||||
/** Holds if this declaration is `ref`. */
|
||||
predicate isRef() { cil_type_annotation(this, 32) }
|
||||
}
|
||||
@@ -1,87 +0,0 @@
|
||||
private import cil
|
||||
private import CIL
|
||||
private import codeql.ssa.Ssa as SsaImplCommon
|
||||
|
||||
deprecated private module SsaInput implements SsaImplCommon::InputSig<CIL::Location> {
|
||||
class BasicBlock = CIL::BasicBlock;
|
||||
|
||||
class ControlFlowNode = CIL::ControlFlowNode;
|
||||
|
||||
BasicBlock getImmediateBasicBlockDominator(BasicBlock bb) { result = bb.getImmediateDominator() }
|
||||
|
||||
BasicBlock getABasicBlockSuccessor(BasicBlock bb) { result = bb.getASuccessor() }
|
||||
|
||||
class ExitBasicBlock extends BasicBlock, CIL::ExitBasicBlock { }
|
||||
|
||||
class SourceVariable = CIL::StackVariable;
|
||||
|
||||
predicate variableWrite(BasicBlock bb, int i, SourceVariable v, boolean certain) {
|
||||
forceCachingInSameStage() and
|
||||
exists(CIL::VariableUpdate vu |
|
||||
vu.updatesAt(bb, i) and
|
||||
v = vu.getVariable() and
|
||||
certain = true
|
||||
)
|
||||
}
|
||||
|
||||
predicate variableRead(BasicBlock bb, int i, SourceVariable v, boolean certain) {
|
||||
exists(CIL::ReadAccess ra | bb.getNode(i) = ra |
|
||||
ra.getTarget() = v and
|
||||
certain = true
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
deprecated import SsaImplCommon::Make<CIL::Location, SsaInput>
|
||||
|
||||
cached
|
||||
private module Cached {
|
||||
private import CIL
|
||||
|
||||
cached
|
||||
deprecated predicate forceCachingInSameStage() { any() }
|
||||
|
||||
cached
|
||||
deprecated ReadAccess getARead(Definition def) {
|
||||
exists(BasicBlock bb, int i |
|
||||
ssaDefReachesRead(_, def, bb, i) and
|
||||
result = bb.getNode(i)
|
||||
)
|
||||
}
|
||||
|
||||
cached
|
||||
deprecated ReadAccess getAFirstReadExt(DefinitionExt def) {
|
||||
exists(BasicBlock bb1, int i1, BasicBlock bb2, int i2 |
|
||||
def.definesAt(_, bb1, i1, _) and
|
||||
adjacentDefReadExt(def, _, bb1, i1, bb2, i2) and
|
||||
result = bb2.getNode(i2)
|
||||
)
|
||||
}
|
||||
|
||||
cached
|
||||
deprecated predicate hasAdjacentReadsExt(DefinitionExt def, ReadAccess first, ReadAccess second) {
|
||||
exists(BasicBlock bb1, int i1, BasicBlock bb2, int i2 |
|
||||
first = bb1.getNode(i1) and
|
||||
adjacentDefReadExt(def, _, bb1, i1, bb2, i2) and
|
||||
second = bb2.getNode(i2)
|
||||
)
|
||||
}
|
||||
|
||||
cached
|
||||
deprecated Definition getAPhiInput(PhiNode phi) { phiHasInputFromBlock(phi, result, _) }
|
||||
|
||||
cached
|
||||
deprecated predicate lastRefBeforeRedefExt(
|
||||
DefinitionExt def, BasicBlock bb, int i, DefinitionExt next
|
||||
) {
|
||||
lastRefRedefExt(def, _, bb, i, next)
|
||||
}
|
||||
}
|
||||
|
||||
import Cached
|
||||
|
||||
private module Deprecated {
|
||||
private import CIL
|
||||
}
|
||||
|
||||
import Deprecated
|
||||
@@ -21,70 +21,6 @@ private import TypeRef
|
||||
* (`LocalFunction`).
|
||||
*/
|
||||
class Callable extends Parameterizable, ExprOrStmtParent, @callable {
|
||||
pragma[noinline]
|
||||
deprecated private string getDeclaringTypeLabel() { result = this.getDeclaringType().getLabel() }
|
||||
|
||||
pragma[noinline]
|
||||
deprecated private string getParameterTypeLabelNonGeneric(int p) {
|
||||
not this instanceof Generic and
|
||||
result = this.getParameter(p).getType().getLabel()
|
||||
}
|
||||
|
||||
language[monotonicAggregates]
|
||||
pragma[nomagic]
|
||||
deprecated private string getMethodParamListNonGeneric() {
|
||||
result =
|
||||
concat(int p |
|
||||
p in [0 .. this.getNumberOfParameters() - 1]
|
||||
|
|
||||
this.getParameterTypeLabelNonGeneric(p), "," order by p
|
||||
)
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
deprecated private string getParameterTypeLabelGeneric(int p) {
|
||||
this instanceof Generic and
|
||||
result = this.getParameter(p).getType().getLabel()
|
||||
}
|
||||
|
||||
language[monotonicAggregates]
|
||||
pragma[nomagic]
|
||||
deprecated private string getMethodParamListGeneric() {
|
||||
result =
|
||||
concat(int p |
|
||||
p in [0 .. this.getNumberOfParameters() - 1]
|
||||
|
|
||||
this.getParameterTypeLabelGeneric(p), "," order by p
|
||||
)
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
deprecated private string getLabelNonGeneric() {
|
||||
not this instanceof Generic and
|
||||
result =
|
||||
this.getReturnTypeLabel() + " " + this.getDeclaringTypeLabel() + "." +
|
||||
this.getUndecoratedName() + "(" + this.getMethodParamListNonGeneric() + ")"
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
deprecated private string getLabelGeneric() {
|
||||
result =
|
||||
this.getReturnTypeLabel() + " " + this.getDeclaringTypeLabel() + "." +
|
||||
this.getUndecoratedName() + getGenericsLabel(this) + "(" + this.getMethodParamListGeneric() +
|
||||
")"
|
||||
}
|
||||
|
||||
deprecated final override string getLabel() {
|
||||
result = this.getLabelNonGeneric() or
|
||||
result = this.getLabelGeneric()
|
||||
}
|
||||
|
||||
deprecated private string getReturnTypeLabel() {
|
||||
result = this.getReturnType().getLabel()
|
||||
or
|
||||
not exists(this.getReturnType()) and result = "System.Void"
|
||||
}
|
||||
|
||||
/** Gets the return type of this callable. */
|
||||
Type getReturnType() { none() }
|
||||
|
||||
|
||||
@@ -27,12 +27,6 @@ class Element extends @element {
|
||||
/** Holds if this element is from an assembly. */
|
||||
predicate fromLibrary() { this.getFile().fromLibrary() }
|
||||
|
||||
/**
|
||||
* Gets the "language" of this program element, as defined by the extension of the filename.
|
||||
* For example, C# has language "cs", and Visual Basic has language "vb".
|
||||
*/
|
||||
deprecated final string getLanguage() { result = this.getLocation().getFile().getExtension() }
|
||||
|
||||
/**
|
||||
* Gets a comma-separated list of the names of the primary CodeQL classes to which this element belongs.
|
||||
*
|
||||
@@ -159,29 +153,5 @@ class NamedElement extends Element, @named_element {
|
||||
qualifier = "" and name = this.getName()
|
||||
}
|
||||
|
||||
/** Gets a unique string label for this element. */
|
||||
cached
|
||||
deprecated string getLabel() { none() }
|
||||
|
||||
/** Holds if `other` has the same metadata handle in the same assembly. */
|
||||
deprecated predicate matchesHandle(NamedElement other) {
|
||||
exists(Assembly asm, int handle |
|
||||
metadata_handle(this, asm, handle) and
|
||||
metadata_handle(other, asm, handle)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this element was compiled from source code that is also present in the
|
||||
* database. That is, this element corresponds to another element from source.
|
||||
*/
|
||||
deprecated predicate compiledFromSource() {
|
||||
not this.fromSource() and
|
||||
exists(NamedElement other | other != this |
|
||||
this.matchesHandle(other) and
|
||||
other.fromSource()
|
||||
)
|
||||
}
|
||||
|
||||
override string toString() { result = this.getName() }
|
||||
}
|
||||
|
||||
@@ -103,33 +103,6 @@ class ConstructedGeneric extends Generic {
|
||||
final int getNumberOfTypeArguments() { result = count(int i | exists(this.getTypeArgument(i))) }
|
||||
}
|
||||
|
||||
/**
|
||||
* INTERNAL: Do not use.
|
||||
*
|
||||
* Constructs the label suffix for a generic method or type.
|
||||
*/
|
||||
deprecated string getGenericsLabel(Generic g) {
|
||||
result = "`" + g.(UnboundGeneric).getNumberOfTypeParameters()
|
||||
or
|
||||
result = "<" + typeArgs(g) + ">"
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
deprecated private string getTypeArgumentLabel(ConstructedGeneric generic, int p) {
|
||||
result = generic.getTypeArgument(p).getLabel()
|
||||
}
|
||||
|
||||
language[monotonicAggregates]
|
||||
pragma[nomagic]
|
||||
deprecated private string typeArgs(ConstructedGeneric generic) {
|
||||
result =
|
||||
concat(int p |
|
||||
p in [0 .. generic.getNumberOfTypeArguments() - 1]
|
||||
|
|
||||
getTypeArgumentLabel(generic, p), ","
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets the type arguments as a comma-separated string. */
|
||||
language[monotonicAggregates]
|
||||
private string getTypeArgumentsToString(ConstructedGeneric cg) {
|
||||
@@ -264,8 +237,6 @@ class TypeParameter extends Type, @type_parameter {
|
||||
/** Gets the index of this type parameter. For example the index of `U` in `Func<T,U>` is 1. */
|
||||
override int getIndex() { type_parameters(this, result, _, _) }
|
||||
|
||||
deprecated final override string getLabel() { result = "!" + this.getIndex() }
|
||||
|
||||
override string getUndecoratedName() { result = "!" + this.getIndex() }
|
||||
|
||||
/** Gets the generic that defines this type parameter. */
|
||||
|
||||
@@ -76,30 +76,6 @@ class ValueOrRefType extends Type, Attributable, @value_or_ref_type {
|
||||
/** Gets a nested child type, if any. */
|
||||
NestedType getAChildType() { nested_types(result, this, _) }
|
||||
|
||||
deprecated private string getPrefixWithTypes() {
|
||||
result = this.getDeclaringType().getLabel() + "."
|
||||
or
|
||||
if this.getDeclaringNamespace().isGlobalNamespace()
|
||||
then result = ""
|
||||
else result = this.getDeclaringNamespace().getFullName() + "."
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
deprecated private string getLabelNonGeneric() {
|
||||
not this instanceof Generic and
|
||||
result = this.getPrefixWithTypes() + this.getUndecoratedName()
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
deprecated private string getLabelGeneric() {
|
||||
result = this.getPrefixWithTypes() + this.getUndecoratedName() + getGenericsLabel(this)
|
||||
}
|
||||
|
||||
deprecated override string getLabel() {
|
||||
result = this.getLabelNonGeneric() or
|
||||
result = this.getLabelGeneric()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the source namespace declaration in which this type is declared, if any.
|
||||
* This only holds for non-nested types.
|
||||
@@ -996,8 +972,6 @@ class FunctionPointerType extends Type, Parameterizable, @function_pointer_type
|
||||
AnnotatedType getAnnotatedReturnType() { result.appliesTo(this) }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "FunctionPointerType" }
|
||||
|
||||
deprecated override string getLabel() { result = this.getName() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1116,8 +1090,6 @@ class ArrayType extends RefType, @array_type {
|
||||
array_element_type(this, _, _, getTypeRef(result))
|
||||
}
|
||||
|
||||
deprecated final override string getLabel() { result = this.getElementType().getLabel() + "[]" }
|
||||
|
||||
/** Holds if this array type has the same shape (dimension and rank) as `that` array type. */
|
||||
predicate hasSameShapeAs(ArrayType that) {
|
||||
this.getDimension() = that.getDimension() and
|
||||
@@ -1180,8 +1152,6 @@ class PointerType extends Type, @pointer_type {
|
||||
|
||||
final override string getName() { types(this, _, result) }
|
||||
|
||||
deprecated final override string getLabel() { result = this.getReferentType().getLabel() + "*" }
|
||||
|
||||
final override string getUndecoratedName() {
|
||||
result = this.getReferentType().getUndecoratedName()
|
||||
}
|
||||
@@ -1271,8 +1241,6 @@ class TupleType extends ValueType, @tuple_type {
|
||||
")"
|
||||
}
|
||||
|
||||
deprecated override string getLabel() { result = this.getUnderlyingType().getLabel() }
|
||||
|
||||
override Type getChild(int i) { result = this.getUnderlyingType().getChild(i) }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "TupleType" }
|
||||
|
||||
@@ -1,122 +0,0 @@
|
||||
/**
|
||||
* Provides `Callable` classes, which are things that can be called
|
||||
* such as methods and constructors.
|
||||
*/
|
||||
|
||||
import Declaration
|
||||
import Variable
|
||||
import Expr
|
||||
import Parameterizable
|
||||
|
||||
/** A .Net callable. */
|
||||
deprecated class Callable extends Parameterizable, @dotnet_callable {
|
||||
/** Holds if this callable has a body or an implementation. */
|
||||
predicate hasBody() { none() }
|
||||
|
||||
/** Holds if this callable can return expression `e`. */
|
||||
predicate canReturn(Expr e) { none() }
|
||||
|
||||
pragma[noinline]
|
||||
private string getDeclaringTypeLabel() { result = this.getDeclaringType().getLabel() }
|
||||
|
||||
pragma[noinline]
|
||||
private string getParameterTypeLabelNonGeneric(int p) {
|
||||
not this instanceof Generic and
|
||||
result = this.getParameter(p).getType().getLabel()
|
||||
}
|
||||
|
||||
language[monotonicAggregates]
|
||||
pragma[nomagic]
|
||||
private string getMethodParamListNonGeneric() {
|
||||
result =
|
||||
concat(int p |
|
||||
p in [0 .. this.getNumberOfParameters() - 1]
|
||||
|
|
||||
this.getParameterTypeLabelNonGeneric(p), "," order by p
|
||||
)
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
private string getParameterTypeLabelGeneric(int p) {
|
||||
this instanceof Generic and
|
||||
result = this.getParameter(p).getType().getLabel()
|
||||
}
|
||||
|
||||
language[monotonicAggregates]
|
||||
pragma[nomagic]
|
||||
private string getMethodParamListGeneric() {
|
||||
result =
|
||||
concat(int p |
|
||||
p in [0 .. this.getNumberOfParameters() - 1]
|
||||
|
|
||||
this.getParameterTypeLabelGeneric(p), "," order by p
|
||||
)
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
private string getLabelNonGeneric() {
|
||||
not this instanceof Generic and
|
||||
result =
|
||||
this.getReturnTypeLabel() + " " + this.getDeclaringTypeLabel() + "." +
|
||||
this.getUndecoratedName() + "(" + this.getMethodParamListNonGeneric() + ")"
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
private string getLabelGeneric() {
|
||||
result =
|
||||
this.getReturnTypeLabel() + " " + this.getDeclaringTypeLabel() + "." +
|
||||
this.getUndecoratedName() + getGenericsLabel(this) + "(" + this.getMethodParamListGeneric() +
|
||||
")"
|
||||
}
|
||||
|
||||
final override string getLabel() {
|
||||
result = this.getLabelNonGeneric() or
|
||||
result = this.getLabelGeneric()
|
||||
}
|
||||
|
||||
private string getReturnTypeLabel() {
|
||||
result = this.getReturnType().getLabel()
|
||||
or
|
||||
not exists(this.getReturnType()) and result = "System.Void"
|
||||
}
|
||||
|
||||
/** Gets the return type of this callable. */
|
||||
Type getReturnType() { none() }
|
||||
}
|
||||
|
||||
/** A constructor. */
|
||||
abstract deprecated class Constructor extends Callable { }
|
||||
|
||||
/** A destructor/finalizer. */
|
||||
abstract deprecated class Destructor extends Callable { }
|
||||
|
||||
pragma[nomagic]
|
||||
deprecated private ValueOrRefType getARecordBaseType(ValueOrRefType t) {
|
||||
exists(Callable c |
|
||||
c.hasName("<Clone>$") and
|
||||
c.getNumberOfParameters() = 0 and
|
||||
t = c.getDeclaringType() and
|
||||
result = t
|
||||
)
|
||||
or
|
||||
result = getARecordBaseType(t).getABaseType()
|
||||
}
|
||||
|
||||
/** A clone method on a record. */
|
||||
deprecated class RecordCloneCallable extends Callable {
|
||||
RecordCloneCallable() {
|
||||
this.getDeclaringType() instanceof ValueOrRefType and
|
||||
this.hasName("<Clone>$") and
|
||||
this.getNumberOfParameters() = 0 and
|
||||
this.getReturnType() = getARecordBaseType(this.getDeclaringType()) and
|
||||
this.(Member).isPublic() and
|
||||
not this.(Member).isStatic()
|
||||
}
|
||||
|
||||
/** Gets the constructor that this clone method calls. */
|
||||
Constructor getConstructor() {
|
||||
result.getDeclaringType() = this.getDeclaringType() and
|
||||
result.getNumberOfParameters() = 1 and
|
||||
result.getParameter(0).getType() = this.getDeclaringType()
|
||||
}
|
||||
}
|
||||
@@ -1,123 +0,0 @@
|
||||
/**
|
||||
* Provides classes for .Net declarations.
|
||||
*/
|
||||
|
||||
import Element
|
||||
import Type
|
||||
private import semmle.code.csharp.commons.QualifiedName
|
||||
|
||||
/** A declaration. */
|
||||
deprecated class Declaration extends NamedElement, @dotnet_declaration {
|
||||
/** Gets the name of this declaration, without additional decoration such as `<...>`. */
|
||||
string getUndecoratedName() { none() }
|
||||
|
||||
/** Holds if this element has undecorated name 'name'. */
|
||||
final predicate hasUndecoratedName(string name) { name = this.getUndecoratedName() }
|
||||
|
||||
/** Gets the type containing this declaration, if any. */
|
||||
Type getDeclaringType() { none() }
|
||||
|
||||
/**
|
||||
* Gets the unbound version of this declaration, that is, the declaration where
|
||||
* all type arguments have been removed. For example, in
|
||||
*
|
||||
* ```csharp
|
||||
* class C<T>
|
||||
* {
|
||||
* class Nested
|
||||
* {
|
||||
* }
|
||||
*
|
||||
* void Method<S>() { }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* we have the following
|
||||
*
|
||||
* | Declaration | Unbound declaration |
|
||||
* |-------------------------|---------------------|
|
||||
* | `C<int>` | ``C`1`` |
|
||||
* | ``C`1.Nested`` | ``C`1.Nested`` |
|
||||
* | `C<int>.Nested` | ``C`1.Nested`` |
|
||||
* | ``C`1.Method`1`` | ``C`1.Method`1`` |
|
||||
* | ``C<int>.Method`1`` | ``C`1.Method`1`` |
|
||||
* | `C<int>.Method<string>` | ``C`1.Method`1`` |
|
||||
*/
|
||||
Declaration getUnboundDeclaration() { result = this }
|
||||
|
||||
/** Holds if this declaration is unbound. */
|
||||
final predicate isUnboundDeclaration() { this.getUnboundDeclaration() = this }
|
||||
}
|
||||
|
||||
/** A member of a type. */
|
||||
deprecated class Member extends Declaration, @dotnet_member {
|
||||
/** Holds if this member is declared `public`. */
|
||||
predicate isPublic() { none() }
|
||||
|
||||
/** Holds if this member is declared `protected.` */
|
||||
predicate isProtected() { none() }
|
||||
|
||||
/** Holds if this member is `private`. */
|
||||
predicate isPrivate() { none() }
|
||||
|
||||
/** Holds if this member is `internal`. */
|
||||
predicate isInternal() { none() }
|
||||
|
||||
/** Holds if this member is `sealed`. */
|
||||
predicate isSealed() { none() }
|
||||
|
||||
/** Holds if this member is `abstract`. */
|
||||
predicate isAbstract() { none() }
|
||||
|
||||
/** Holds if this member is `static`. */
|
||||
predicate isStatic() { none() }
|
||||
|
||||
/** Holds if this member is declared `required`. */
|
||||
predicate isRequired() { none() }
|
||||
|
||||
/** Holds if this member is declared `file` local. */
|
||||
predicate isFile() { none() }
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `hasFullyQualifiedName` instead.
|
||||
*
|
||||
* Holds if this member has name `name` and is defined in type `type`
|
||||
* with namespace `namespace`.
|
||||
*/
|
||||
cached
|
||||
deprecated predicate hasQualifiedName(string namespace, string type, string name) {
|
||||
this.getDeclaringType().hasQualifiedName(namespace, type) and
|
||||
name = this.getName()
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this member has name `name` and is defined in type `type`
|
||||
* with namespace `namespace`.
|
||||
*/
|
||||
cached
|
||||
predicate hasFullyQualifiedName(string namespace, string type, string name) {
|
||||
this.getDeclaringType().hasFullyQualifiedName(namespace, type) and
|
||||
name = this.getName()
|
||||
}
|
||||
}
|
||||
|
||||
/** A property. */
|
||||
deprecated class Property extends Member, @dotnet_property {
|
||||
/** Gets the getter of this property, if any. */
|
||||
Callable getGetter() { none() }
|
||||
|
||||
/** Gets the setter of this property, if any. */
|
||||
Callable getSetter() { none() }
|
||||
|
||||
/** Gets the type of this property. */
|
||||
Type getType() { none() }
|
||||
}
|
||||
|
||||
/** An event. */
|
||||
deprecated class Event extends Member, @dotnet_event {
|
||||
/** Gets the adder of this event, if any. */
|
||||
Callable getAdder() { none() }
|
||||
|
||||
/** Gets the remover of this event, if any. */
|
||||
Callable getRemover() { none() }
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
/**
|
||||
* Provides a common model for all .Net languages, including C# and CIL.
|
||||
*/
|
||||
|
||||
import Element
|
||||
import Namespace
|
||||
import Declaration
|
||||
import Generics
|
||||
import Type
|
||||
import Variable
|
||||
import Callable
|
||||
import Expr
|
||||
import Utils
|
||||
@@ -1,162 +0,0 @@
|
||||
/**
|
||||
* Provides the .Net `Element` class.
|
||||
*/
|
||||
|
||||
private import DotNet
|
||||
import semmle.code.csharp.Location
|
||||
|
||||
/**
|
||||
* A .Net program element.
|
||||
*/
|
||||
deprecated class Element extends @dotnet_element {
|
||||
/** Gets a textual representation of this element. */
|
||||
cached
|
||||
string toString() { none() }
|
||||
|
||||
/** Gets the location of this element. */
|
||||
pragma[nomagic]
|
||||
Location getLocation() { none() }
|
||||
|
||||
/**
|
||||
* Gets a location of this element, which can include locations in
|
||||
* both DLLs and source files.
|
||||
*/
|
||||
Location getALocation() { none() }
|
||||
|
||||
/** Gets the file containing this element. */
|
||||
final File getFile() { result = this.getLocation().getFile() }
|
||||
|
||||
/** Holds if this element is from source code. */
|
||||
predicate fromSource() { this.getFile().fromSource() }
|
||||
|
||||
/** Holds if this element is from an assembly. */
|
||||
predicate fromLibrary() { this.getFile().fromLibrary() }
|
||||
|
||||
/**
|
||||
* Gets the "language" of this program element, as defined by the extension of the filename.
|
||||
* For example, C# has language "cs", and Visual Basic has language "vb".
|
||||
*/
|
||||
final string getLanguage() { result = this.getLocation().getFile().getExtension() }
|
||||
|
||||
/** Gets the full textual representation of this element, including type information. */
|
||||
string toStringWithTypes() { result = this.toString() }
|
||||
|
||||
/**
|
||||
* Gets a comma-separated list of the names of the primary CodeQL classes to which this element belongs.
|
||||
*
|
||||
* If no primary class can be determined, the result is `"???"`.
|
||||
*/
|
||||
final string getPrimaryQlClasses() {
|
||||
result = strictconcat(this.getAPrimaryQlClass(), ",")
|
||||
or
|
||||
not exists(this.getAPrimaryQlClass()) and
|
||||
result = "???"
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the name of a primary CodeQL class to which this element belongs.
|
||||
*
|
||||
* For most elements, this is simply the most precise syntactic category to
|
||||
* which they belong; for example, `AddExpr` is a primary class, but
|
||||
* `BinaryOperation` is not.
|
||||
*
|
||||
* If no primary classes match, this predicate has no result. If multiple
|
||||
* primary classes match, this predicate can have multiple results.
|
||||
*
|
||||
* See also `getPrimaryQlClasses`, which is better to use in most cases.
|
||||
*/
|
||||
string getAPrimaryQlClass() { none() }
|
||||
}
|
||||
|
||||
/** An element that has a name. */
|
||||
deprecated class NamedElement extends Element, @dotnet_named_element {
|
||||
/** Gets the name of this element. */
|
||||
cached
|
||||
string getName() { none() }
|
||||
|
||||
/** Holds if this element has name 'name'. */
|
||||
final predicate hasName(string name) { name = this.getName() }
|
||||
|
||||
/**
|
||||
* Gets the fully qualified name of this element, for example the
|
||||
* fully qualified name of `M` on line 3 is `N.C.M` in
|
||||
*
|
||||
* ```csharp
|
||||
* namespace N {
|
||||
* class C {
|
||||
* void M(int i, string s) { }
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
cached
|
||||
deprecated final string getQualifiedName() {
|
||||
exists(string qualifier, string name | this.hasQualifiedName(qualifier, name) |
|
||||
if qualifier = "" then result = name else result = qualifier + "." + name
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the fully qualified name of this element, for example the
|
||||
* fully qualified name of `M` on line 3 is `N.C.M` in
|
||||
*
|
||||
* ```csharp
|
||||
* namespace N {
|
||||
* class C {
|
||||
* void M(int i, string s) { }
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* Unbound generic types, such as `IList<T>`, are represented as
|
||||
* ``System.Collections.Generic.IList`1``.
|
||||
*/
|
||||
cached
|
||||
final string getFullyQualifiedName() {
|
||||
exists(string qualifier, string name | this.hasFullyQualifiedName(qualifier, name) |
|
||||
if qualifier = "" then result = name else result = qualifier + "." + name
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `hasFullyQualifiedName` instead.
|
||||
*
|
||||
* Holds if this element has the qualified name `qualifier`.`name`.
|
||||
*/
|
||||
cached
|
||||
deprecated predicate hasQualifiedName(string qualifier, string name) {
|
||||
qualifier = "" and name = this.getName()
|
||||
}
|
||||
|
||||
/** Holds if this element has the fully qualified name `qualifier`.`name`. */
|
||||
cached
|
||||
predicate hasFullyQualifiedName(string qualifier, string name) {
|
||||
qualifier = "" and name = this.getName()
|
||||
}
|
||||
|
||||
/** Gets a unique string label for this element. */
|
||||
cached
|
||||
string getLabel() { none() }
|
||||
|
||||
/** Holds if `other` has the same metadata handle in the same assembly. */
|
||||
predicate matchesHandle(NamedElement other) {
|
||||
exists(Assembly asm, int handle |
|
||||
metadata_handle(this, asm, handle) and
|
||||
metadata_handle(other, asm, handle)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this element was compiled from source code that is also present in the
|
||||
* database. That is, this element corresponds to another element from source.
|
||||
*/
|
||||
predicate compiledFromSource() {
|
||||
not this.fromSource() and
|
||||
exists(NamedElement other | other != this |
|
||||
this.matchesHandle(other) and
|
||||
other.fromSource()
|
||||
)
|
||||
}
|
||||
|
||||
override string toString() { result = this.getName() }
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
/**
|
||||
* Provides .Net expression classes.
|
||||
*/
|
||||
|
||||
import Expr
|
||||
import Type
|
||||
import Callable
|
||||
|
||||
/** An expression. */
|
||||
deprecated class Expr extends Element, @dotnet_expr {
|
||||
/** Gets the callable containing this expression. */
|
||||
Callable getEnclosingCallable() { none() }
|
||||
|
||||
/** Gets the type of this expression. */
|
||||
Type getType() { none() }
|
||||
|
||||
/** Gets the constant value of this expression, if any. */
|
||||
string getValue() { none() }
|
||||
|
||||
/** Holds if this expression has a value. */
|
||||
final predicate hasValue() { exists(this.getValue()) }
|
||||
|
||||
/**
|
||||
* Gets the parent of this expression. This is for example the element
|
||||
* that uses the result of this expression.
|
||||
*/
|
||||
Element getParent() { none() }
|
||||
}
|
||||
|
||||
/** A call. */
|
||||
deprecated class Call extends Expr, @dotnet_call {
|
||||
/** Gets the target of this call. */
|
||||
Callable getTarget() { none() }
|
||||
|
||||
/** Gets any potential target of this call. */
|
||||
Callable getARuntimeTarget() { none() }
|
||||
|
||||
/**
|
||||
* Gets the `i`th "raw" argument to this call, if any.
|
||||
* For instance methods, argument 0 is the qualifier.
|
||||
*/
|
||||
Expr getRawArgument(int i) { none() }
|
||||
|
||||
/** Gets the `i`th argument to this call, if any. */
|
||||
Expr getArgument(int i) { none() }
|
||||
|
||||
/** Gets an argument to this call. */
|
||||
Expr getAnArgument() { result = this.getArgument(_) }
|
||||
|
||||
/** Gets the expression that is supplied for parameter `p`. */
|
||||
Expr getArgumentForParameter(Parameter p) { none() }
|
||||
}
|
||||
|
||||
/** A literal expression. */
|
||||
deprecated class Literal extends Expr, @dotnet_literal { }
|
||||
|
||||
/** A string literal expression. */
|
||||
deprecated class StringLiteral extends Literal, @dotnet_string_literal { }
|
||||
|
||||
/** An integer literal expression. */
|
||||
deprecated class IntLiteral extends Literal, @dotnet_int_literal { }
|
||||
|
||||
/** A `null` literal expression. */
|
||||
deprecated class NullLiteral extends Literal, @dotnet_null_literal { }
|
||||
@@ -1,72 +0,0 @@
|
||||
/** Provides classes for generic types and methods. */
|
||||
|
||||
import Declaration
|
||||
|
||||
/**
|
||||
* A generic declaration. Either an unbound generic (`UnboundGeneric`) or a
|
||||
* constructed generic (`ConstructedGeneric`).
|
||||
*/
|
||||
abstract deprecated class Generic extends Declaration, @dotnet_generic { }
|
||||
|
||||
/** An unbound generic. */
|
||||
abstract deprecated class UnboundGeneric extends Generic {
|
||||
/** Gets the `i`th type parameter, if any. */
|
||||
abstract TypeParameter getTypeParameter(int i);
|
||||
|
||||
/** Gets a type parameter. */
|
||||
TypeParameter getATypeParameter() { result = this.getTypeParameter(_) }
|
||||
|
||||
/**
|
||||
* Gets one of the constructed versions of this declaration,
|
||||
* which has been bound to a specific set of types.
|
||||
*/
|
||||
ConstructedGeneric getAConstructedGeneric() { result.getUnboundGeneric() = this }
|
||||
|
||||
/** Gets the total number of type parameters. */
|
||||
int getNumberOfTypeParameters() { result = count(int i | exists(this.getTypeParameter(i))) }
|
||||
}
|
||||
|
||||
/** A constructed generic. */
|
||||
abstract deprecated class ConstructedGeneric extends Generic {
|
||||
/** Gets the `i`th type argument, if any. */
|
||||
abstract Type getTypeArgument(int i);
|
||||
|
||||
/** Gets a type argument. */
|
||||
Type getATypeArgument() { result = this.getTypeArgument(_) }
|
||||
|
||||
/**
|
||||
* Gets the unbound generic declaration from which this declaration was
|
||||
* constructed.
|
||||
*/
|
||||
UnboundGeneric getUnboundGeneric() { none() }
|
||||
|
||||
/** Gets the total number of type arguments. */
|
||||
final int getNumberOfTypeArguments() { result = count(int i | exists(this.getTypeArgument(i))) }
|
||||
}
|
||||
|
||||
/**
|
||||
* INTERNAL: Do not use.
|
||||
*
|
||||
* Constructs the label suffix for a generic method or type.
|
||||
*/
|
||||
deprecated string getGenericsLabel(Generic g) {
|
||||
result = "`" + g.(UnboundGeneric).getNumberOfTypeParameters()
|
||||
or
|
||||
result = "<" + typeArgs(g) + ">"
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
deprecated private string getTypeArgumentLabel(ConstructedGeneric generic, int p) {
|
||||
result = generic.getTypeArgument(p).getLabel()
|
||||
}
|
||||
|
||||
language[monotonicAggregates]
|
||||
pragma[nomagic]
|
||||
deprecated private string typeArgs(ConstructedGeneric generic) {
|
||||
result =
|
||||
concat(int p |
|
||||
p in [0 .. generic.getNumberOfTypeArguments() - 1]
|
||||
|
|
||||
getTypeArgumentLabel(generic, p), ","
|
||||
)
|
||||
}
|
||||
@@ -1,69 +0,0 @@
|
||||
/**
|
||||
* Provides the `Namespace` class to represent .Net namespaces.
|
||||
*/
|
||||
|
||||
private import Declaration
|
||||
private import semmle.code.csharp.commons.QualifiedName
|
||||
|
||||
/** A namespace. */
|
||||
deprecated class Namespace extends Declaration, @namespace {
|
||||
/**
|
||||
* Gets the parent namespace, if any. For example the parent namespace of `System.IO`
|
||||
* is `System`. The parent namespace of `System` is the global namespace.
|
||||
*/
|
||||
Namespace getParentNamespace() { none() }
|
||||
|
||||
/**
|
||||
* Gets a child namespace, if any. For example `System.IO` is a child in
|
||||
* the namespace `System`.
|
||||
*/
|
||||
Namespace getAChildNamespace() { result.getParentNamespace() = this }
|
||||
|
||||
/**
|
||||
* Holds if this namespace has the qualified name `qualifier`.`name`.
|
||||
*
|
||||
* For example if the qualified name is `System.Collections.Generic`, then
|
||||
* `qualifier`=`System.Collections` and `name`=`Generic`.
|
||||
*/
|
||||
deprecated override predicate hasQualifiedName(string qualifier, string name) {
|
||||
namespaceHasQualifiedName(this, qualifier, name)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this namespace has the qualified name `qualifier`.`name`.
|
||||
*
|
||||
* For example if the qualified name is `System.Collections.Generic`, then
|
||||
* `qualifier`=`System.Collections` and `name`=`Generic`.
|
||||
*/
|
||||
override predicate hasFullyQualifiedName(string qualifier, string name) {
|
||||
namespaceHasQualifiedName(this, qualifier, name)
|
||||
}
|
||||
|
||||
/** Gets a textual representation of this namespace. */
|
||||
override string toString() { result = this.getFullName() }
|
||||
|
||||
/** Holds if this is the global namespace. */
|
||||
final predicate isGlobalNamespace() { this.getName() = "" }
|
||||
|
||||
/** Gets the simple name of this namespace, for example `IO` in `System.IO`. */
|
||||
final override string getName() { namespaces(this, result) }
|
||||
|
||||
final override string getUndecoratedName() { namespaces(this, result) }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "Namespace" }
|
||||
|
||||
/**
|
||||
* Get the fully qualified name of this namespace.
|
||||
*/
|
||||
string getFullName() {
|
||||
exists(string namespace, string name |
|
||||
namespaceHasQualifiedName(this, namespace, name) and
|
||||
result = getQualifiedName(namespace, name)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/** The global namespace. */
|
||||
deprecated class GlobalNamespace extends Namespace {
|
||||
GlobalNamespace() { this.getName() = "" }
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
/**
|
||||
* Provides a general parameterizable entity to represent constructs that might
|
||||
* have parameters.
|
||||
*/
|
||||
|
||||
import Declaration
|
||||
|
||||
/**
|
||||
* A general parameterizable entity, such as a callable, delegate type, accessor,
|
||||
* indexer, or function pointer type.
|
||||
*/
|
||||
deprecated class Parameterizable extends Declaration, @dotnet_parameterizable {
|
||||
/** Gets raw parameter `i`, including the `this` parameter at index 0. */
|
||||
Parameter getRawParameter(int i) { none() }
|
||||
|
||||
/** Gets the `i`th parameter, excluding the `this` parameter. */
|
||||
Parameter getParameter(int i) { none() }
|
||||
|
||||
/** Gets the number of parameters of this callable. */
|
||||
int getNumberOfParameters() { result = count(this.getAParameter()) }
|
||||
|
||||
/** Holds if this declaration has no parameters. */
|
||||
predicate hasNoParameters() { not exists(this.getAParameter()) }
|
||||
|
||||
/** Gets a parameter, if any. */
|
||||
Parameter getAParameter() { result = this.getParameter(_) }
|
||||
|
||||
/** Gets a raw parameter (including the qualifier), if any. */
|
||||
final Parameter getARawParameter() { result = this.getRawParameter(_) }
|
||||
}
|
||||
@@ -1,94 +0,0 @@
|
||||
/**
|
||||
* Provides classes for .Net types.
|
||||
*/
|
||||
|
||||
import Declaration
|
||||
import Namespace
|
||||
import Callable
|
||||
import Generics
|
||||
|
||||
/**
|
||||
* A type. Either a value or reference type (`ValueOrRefType`), a type parameter (`TypeParameter`),
|
||||
* a pointer type (`PointerType`), or an array type (`ArrayType`).
|
||||
*/
|
||||
deprecated class Type extends Declaration, @dotnet_type {
|
||||
/** Gets the name of this type without additional syntax such as `[]` or `*`. */
|
||||
override string getUndecoratedName() { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
* A value or reference type.
|
||||
*/
|
||||
deprecated class ValueOrRefType extends Type, @dotnet_valueorreftype {
|
||||
/** Gets the namespace declaring this type, if any. */
|
||||
Namespace getDeclaringNamespace() { none() }
|
||||
|
||||
private string getPrefixWithTypes() {
|
||||
result = this.getDeclaringType().getLabel() + "."
|
||||
or
|
||||
if this.getDeclaringNamespace().isGlobalNamespace()
|
||||
then result = ""
|
||||
else result = this.getDeclaringNamespace().getFullName() + "."
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
private string getLabelNonGeneric() {
|
||||
not this instanceof Generic and
|
||||
result = this.getPrefixWithTypes() + this.getUndecoratedName()
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
private string getLabelGeneric() {
|
||||
result = this.getPrefixWithTypes() + this.getUndecoratedName() + getGenericsLabel(this)
|
||||
}
|
||||
|
||||
override string getLabel() {
|
||||
result = this.getLabelNonGeneric() or
|
||||
result = this.getLabelGeneric()
|
||||
}
|
||||
|
||||
/** Gets a base type of this type, if any. */
|
||||
ValueOrRefType getABaseType() { none() }
|
||||
|
||||
/** Holds if this type is a `record`. */
|
||||
predicate isRecord() { exists(RecordCloneCallable c | c.getDeclaringType() = this) }
|
||||
}
|
||||
|
||||
/**
|
||||
* A type parameter, for example `T` in `System.Nullable<T>`.
|
||||
*/
|
||||
deprecated class TypeParameter extends Type, @dotnet_type_parameter {
|
||||
/** Gets the generic type or method declaring this type parameter. */
|
||||
UnboundGeneric getDeclaringGeneric() { this = result.getATypeParameter() }
|
||||
|
||||
/** Gets the index of this type parameter. For example the index of `U` in `Func<T,U>` is 1. */
|
||||
int getIndex() { none() }
|
||||
|
||||
final override string getLabel() { result = "!" + this.getIndex() }
|
||||
|
||||
override string getUndecoratedName() { result = "!" + this.getIndex() }
|
||||
}
|
||||
|
||||
/** A pointer type. */
|
||||
deprecated class PointerType extends Type, @dotnet_pointer_type {
|
||||
/** Gets the type referred by this pointer type, for example `char` in `char*`. */
|
||||
Type getReferentType() { none() }
|
||||
|
||||
override string getName() { result = this.getReferentType().getName() + "*" }
|
||||
|
||||
final override string getLabel() { result = this.getReferentType().getLabel() + "*" }
|
||||
|
||||
override string toStringWithTypes() { result = this.getReferentType().toStringWithTypes() + "*" }
|
||||
}
|
||||
|
||||
/** An array type. */
|
||||
deprecated class ArrayType extends ValueOrRefType, @dotnet_array_type {
|
||||
/** Gets the type of the array element. */
|
||||
Type getElementType() { none() }
|
||||
|
||||
final override string getLabel() { result = this.getElementType().getLabel() + "[]" }
|
||||
|
||||
override string toStringWithTypes() { result = this.getElementType().toStringWithTypes() + "[]" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "ArrayType" }
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
/**
|
||||
* Provides some useful .Net classes.
|
||||
*/
|
||||
|
||||
import Element
|
||||
import Expr
|
||||
|
||||
/** A throw element. */
|
||||
deprecated class Throw extends Element, @dotnet_throw {
|
||||
/** Gets the expression being thrown, if any. */
|
||||
Expr getExpr() { none() }
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
/** Provides classes for .Net variables, such as fields and parameters. */
|
||||
|
||||
import Declaration
|
||||
import Callable
|
||||
|
||||
/** A .Net variable. */
|
||||
deprecated class Variable extends Declaration, @dotnet_variable {
|
||||
/** Gets the type of this variable. */
|
||||
Type getType() { none() }
|
||||
}
|
||||
|
||||
/** A .Net field. */
|
||||
deprecated class Field extends Variable, Member, @dotnet_field { }
|
||||
|
||||
/** A parameter to a .Net callable, property or function pointer type. */
|
||||
deprecated class Parameter extends Variable, @dotnet_parameter {
|
||||
/** Gets the raw position of this parameter, including the `this` parameter at index 0. */
|
||||
final int getRawPosition() { this = this.getDeclaringElement().getRawParameter(result) }
|
||||
|
||||
/** Gets the position of this parameter, excluding the `this` parameter. */
|
||||
int getPosition() { this = this.getDeclaringElement().getParameter(result) }
|
||||
|
||||
/** Gets the callable defining this parameter, if any. */
|
||||
Callable getCallable() { result = this.getDeclaringElement() }
|
||||
|
||||
/** Gets the declaring `Parameterizable`. */
|
||||
Parameterizable getDeclaringElement() { none() }
|
||||
|
||||
/** Holds if this is an `out` parameter. */
|
||||
predicate isOut() { none() }
|
||||
|
||||
/** Holds if this is a `ref` parameter. */
|
||||
predicate isRef() { none() }
|
||||
}
|
||||
@@ -1457,643 +1457,3 @@ asp_tag_name(
|
||||
unique int tag: @asp_open_tag ref,
|
||||
string name: string ref);
|
||||
asp_tag_isempty(int tag: @asp_open_tag ref);
|
||||
|
||||
/* Common Intermediate Language - CIL */
|
||||
|
||||
case @cil_instruction.opcode of
|
||||
0 = @cil_nop
|
||||
| 1 = @cil_break
|
||||
| 2 = @cil_ldarg_0
|
||||
| 3 = @cil_ldarg_1
|
||||
| 4 = @cil_ldarg_2
|
||||
| 5 = @cil_ldarg_3
|
||||
| 6 = @cil_ldloc_0
|
||||
| 7 = @cil_ldloc_1
|
||||
| 8 = @cil_ldloc_2
|
||||
| 9 = @cil_ldloc_3
|
||||
| 10 = @cil_stloc_0
|
||||
| 11 = @cil_stloc_1
|
||||
| 12 = @cil_stloc_2
|
||||
| 13 = @cil_stloc_3
|
||||
| 14 = @cil_ldarg_s
|
||||
| 15 = @cil_ldarga_s
|
||||
| 16 = @cil_starg_s
|
||||
| 17 = @cil_ldloc_s
|
||||
| 18 = @cil_ldloca_s
|
||||
| 19 = @cil_stloc_s
|
||||
| 20 = @cil_ldnull
|
||||
| 21 = @cil_ldc_i4_m1
|
||||
| 22 = @cil_ldc_i4_0
|
||||
| 23 = @cil_ldc_i4_1
|
||||
| 24 = @cil_ldc_i4_2
|
||||
| 25 = @cil_ldc_i4_3
|
||||
| 26 = @cil_ldc_i4_4
|
||||
| 27 = @cil_ldc_i4_5
|
||||
| 28 = @cil_ldc_i4_6
|
||||
| 29 = @cil_ldc_i4_7
|
||||
| 30 = @cil_ldc_i4_8
|
||||
| 31 = @cil_ldc_i4_s
|
||||
| 32 = @cil_ldc_i4
|
||||
| 33 = @cil_ldc_i8
|
||||
| 34 = @cil_ldc_r4
|
||||
| 35 = @cil_ldc_r8
|
||||
| 37 = @cil_dup
|
||||
| 38 = @cil_pop
|
||||
| 39 = @cil_jmp
|
||||
| 40 = @cil_call
|
||||
| 41 = @cil_calli
|
||||
| 42 = @cil_ret
|
||||
| 43 = @cil_br_s
|
||||
| 44 = @cil_brfalse_s
|
||||
| 45 = @cil_brtrue_s
|
||||
| 46 = @cil_beq_s
|
||||
| 47 = @cil_bge_s
|
||||
| 48 = @cil_bgt_s
|
||||
| 49 = @cil_ble_s
|
||||
| 50 = @cil_blt_s
|
||||
| 51 = @cil_bne_un_s
|
||||
| 52 = @cil_bge_un_s
|
||||
| 53 = @cil_bgt_un_s
|
||||
| 54 = @cil_ble_un_s
|
||||
| 55 = @cil_blt_un_s
|
||||
| 56 = @cil_br
|
||||
| 57 = @cil_brfalse
|
||||
| 58 = @cil_brtrue
|
||||
| 59 = @cil_beq
|
||||
| 60 = @cil_bge
|
||||
| 61 = @cil_bgt
|
||||
| 62 = @cil_ble
|
||||
| 63 = @cil_blt
|
||||
| 64 = @cil_bne_un
|
||||
| 65 = @cil_bge_un
|
||||
| 66 = @cil_bgt_un
|
||||
| 67 = @cil_ble_un
|
||||
| 68 = @cil_blt_un
|
||||
| 69 = @cil_switch
|
||||
| 70 = @cil_ldind_i1
|
||||
| 71 = @cil_ldind_u1
|
||||
| 72 = @cil_ldind_i2
|
||||
| 73 = @cil_ldind_u2
|
||||
| 74 = @cil_ldind_i4
|
||||
| 75 = @cil_ldind_u4
|
||||
| 76 = @cil_ldind_i8
|
||||
| 77 = @cil_ldind_i
|
||||
| 78 = @cil_ldind_r4
|
||||
| 79 = @cil_ldind_r8
|
||||
| 80 = @cil_ldind_ref
|
||||
| 81 = @cil_stind_ref
|
||||
| 82 = @cil_stind_i1
|
||||
| 83 = @cil_stind_i2
|
||||
| 84 = @cil_stind_i4
|
||||
| 85 = @cil_stind_i8
|
||||
| 86 = @cil_stind_r4
|
||||
| 87 = @cil_stind_r8
|
||||
| 88 = @cil_add
|
||||
| 89 = @cil_sub
|
||||
| 90 = @cil_mul
|
||||
| 91 = @cil_div
|
||||
| 92 = @cil_div_un
|
||||
| 93 = @cil_rem
|
||||
| 94 = @cil_rem_un
|
||||
| 95 = @cil_and
|
||||
| 96 = @cil_or
|
||||
| 97 = @cil_xor
|
||||
| 98 = @cil_shl
|
||||
| 99 = @cil_shr
|
||||
| 100 = @cil_shr_un
|
||||
| 101 = @cil_neg
|
||||
| 102 = @cil_not
|
||||
| 103 = @cil_conv_i1
|
||||
| 104 = @cil_conv_i2
|
||||
| 105 = @cil_conv_i4
|
||||
| 106 = @cil_conv_i8
|
||||
| 107 = @cil_conv_r4
|
||||
| 108 = @cil_conv_r8
|
||||
| 109 = @cil_conv_u4
|
||||
| 110 = @cil_conv_u8
|
||||
| 111 = @cil_callvirt
|
||||
| 112 = @cil_cpobj
|
||||
| 113 = @cil_ldobj
|
||||
| 114 = @cil_ldstr
|
||||
| 115 = @cil_newobj
|
||||
| 116 = @cil_castclass
|
||||
| 117 = @cil_isinst
|
||||
| 118 = @cil_conv_r_un
|
||||
| 121 = @cil_unbox
|
||||
| 122 = @cil_throw
|
||||
| 123 = @cil_ldfld
|
||||
| 124 = @cil_ldflda
|
||||
| 125 = @cil_stfld
|
||||
| 126 = @cil_ldsfld
|
||||
| 127 = @cil_ldsflda
|
||||
| 128 = @cil_stsfld
|
||||
| 129 = @cil_stobj
|
||||
| 130 = @cil_conv_ovf_i1_un
|
||||
| 131 = @cil_conv_ovf_i2_un
|
||||
| 132 = @cil_conv_ovf_i4_un
|
||||
| 133 = @cil_conv_ovf_i8_un
|
||||
| 134 = @cil_conv_ovf_u1_un
|
||||
| 135 = @cil_conv_ovf_u2_un
|
||||
| 136 = @cil_conv_ovf_u4_un
|
||||
| 137 = @cil_conv_ovf_u8_un
|
||||
| 138 = @cil_conv_ovf_i_un
|
||||
| 139 = @cil_conv_ovf_u_un
|
||||
| 140 = @cil_box
|
||||
| 141 = @cil_newarr
|
||||
| 142 = @cil_ldlen
|
||||
| 143 = @cil_ldelema
|
||||
| 144 = @cil_ldelem_i1
|
||||
| 145 = @cil_ldelem_u1
|
||||
| 146 = @cil_ldelem_i2
|
||||
| 147 = @cil_ldelem_u2
|
||||
| 148 = @cil_ldelem_i4
|
||||
| 149 = @cil_ldelem_u4
|
||||
| 150 = @cil_ldelem_i8
|
||||
| 151 = @cil_ldelem_i
|
||||
| 152 = @cil_ldelem_r4
|
||||
| 153 = @cil_ldelem_r8
|
||||
| 154 = @cil_ldelem_ref
|
||||
| 155 = @cil_stelem_i
|
||||
| 156 = @cil_stelem_i1
|
||||
| 157 = @cil_stelem_i2
|
||||
| 158 = @cil_stelem_i4
|
||||
| 159 = @cil_stelem_i8
|
||||
| 160 = @cil_stelem_r4
|
||||
| 161 = @cil_stelem_r8
|
||||
| 162 = @cil_stelem_ref
|
||||
| 163 = @cil_ldelem
|
||||
| 164 = @cil_stelem
|
||||
| 165 = @cil_unbox_any
|
||||
| 179 = @cil_conv_ovf_i1
|
||||
| 180 = @cil_conv_ovf_u1
|
||||
| 181 = @cil_conv_ovf_i2
|
||||
| 182 = @cil_conv_ovf_u2
|
||||
| 183 = @cil_conv_ovf_i4
|
||||
| 184 = @cil_conv_ovf_u4
|
||||
| 185 = @cil_conv_ovf_i8
|
||||
| 186 = @cil_conv_ovf_u8
|
||||
| 194 = @cil_refanyval
|
||||
| 195 = @cil_ckinfinite
|
||||
| 198 = @cil_mkrefany
|
||||
| 208 = @cil_ldtoken
|
||||
| 209 = @cil_conv_u2
|
||||
| 210 = @cil_conv_u1
|
||||
| 211 = @cil_conv_i
|
||||
| 212 = @cil_conv_ovf_i
|
||||
| 213 = @cil_conv_ovf_u
|
||||
| 214 = @cil_add_ovf
|
||||
| 215 = @cil_add_ovf_un
|
||||
| 216 = @cil_mul_ovf
|
||||
| 217 = @cil_mul_ovf_un
|
||||
| 218 = @cil_sub_ovf
|
||||
| 219 = @cil_sub_ovf_un
|
||||
| 220 = @cil_endfinally
|
||||
| 221 = @cil_leave
|
||||
| 222 = @cil_leave_s
|
||||
| 223 = @cil_stind_i
|
||||
| 224 = @cil_conv_u
|
||||
| 65024 = @cil_arglist
|
||||
| 65025 = @cil_ceq
|
||||
| 65026 = @cil_cgt
|
||||
| 65027 = @cil_cgt_un
|
||||
| 65028 = @cil_clt
|
||||
| 65029 = @cil_clt_un
|
||||
| 65030 = @cil_ldftn
|
||||
| 65031 = @cil_ldvirtftn
|
||||
| 65033 = @cil_ldarg
|
||||
| 65034 = @cil_ldarga
|
||||
| 65035 = @cil_starg
|
||||
| 65036 = @cil_ldloc
|
||||
| 65037 = @cil_ldloca
|
||||
| 65038 = @cil_stloc
|
||||
| 65039 = @cil_localloc
|
||||
| 65041 = @cil_endfilter
|
||||
| 65042 = @cil_unaligned
|
||||
| 65043 = @cil_volatile
|
||||
| 65044 = @cil_tail
|
||||
| 65045 = @cil_initobj
|
||||
| 65046 = @cil_constrained
|
||||
| 65047 = @cil_cpblk
|
||||
| 65048 = @cil_initblk
|
||||
| 65050 = @cil_rethrow
|
||||
| 65052 = @cil_sizeof
|
||||
| 65053 = @cil_refanytype
|
||||
| 65054 = @cil_readonly
|
||||
;
|
||||
|
||||
// CIL ignored instructions
|
||||
|
||||
@cil_ignore = @cil_nop | @cil_break | @cil_volatile | @cil_unaligned;
|
||||
|
||||
// CIL local/parameter/field access
|
||||
|
||||
@cil_ldarg_any = @cil_ldarg_0 | @cil_ldarg_1 | @cil_ldarg_2 | @cil_ldarg_3 | @cil_ldarg_s | @cil_ldarga_s | @cil_ldarg | @cil_ldarga;
|
||||
@cil_starg_any = @cil_starg | @cil_starg_s;
|
||||
|
||||
@cil_ldloc_any = @cil_ldloc_0 | @cil_ldloc_1 | @cil_ldloc_2 | @cil_ldloc_3 | @cil_ldloc_s | @cil_ldloca_s | @cil_ldloc | @cil_ldloca;
|
||||
@cil_stloc_any = @cil_stloc_0 | @cil_stloc_1 | @cil_stloc_2 | @cil_stloc_3 | @cil_stloc_s | @cil_stloc;
|
||||
|
||||
@cil_ldfld_any = @cil_ldfld | @cil_ldsfld | @cil_ldsflda | @cil_ldflda;
|
||||
@cil_stfld_any = @cil_stfld | @cil_stsfld;
|
||||
|
||||
@cil_local_access = @cil_stloc_any | @cil_ldloc_any;
|
||||
@cil_arg_access = @cil_starg_any | @cil_ldarg_any;
|
||||
@cil_read_access = @cil_ldloc_any | @cil_ldarg_any | @cil_ldfld_any;
|
||||
@cil_write_access = @cil_stloc_any | @cil_starg_any | @cil_stfld_any;
|
||||
|
||||
@cil_stack_access = @cil_local_access | @cil_arg_access;
|
||||
@cil_field_access = @cil_ldfld_any | @cil_stfld_any;
|
||||
|
||||
@cil_access = @cil_read_access | @cil_write_access;
|
||||
|
||||
// CIL constant/literal instructions
|
||||
|
||||
@cil_ldc_i = @cil_ldc_i4_any | @cil_ldc_i8;
|
||||
|
||||
@cil_ldc_i4_any = @cil_ldc_i4_m1 | @cil_ldc_i4_0 | @cil_ldc_i4_1 | @cil_ldc_i4_2 | @cil_ldc_i4_3 |
|
||||
@cil_ldc_i4_4 | @cil_ldc_i4_5 | @cil_ldc_i4_6 | @cil_ldc_i4_7 | @cil_ldc_i4_8 | @cil_ldc_i4_s | @cil_ldc_i4;
|
||||
|
||||
@cil_ldc_r = @cil_ldc_r4 | @cil_ldc_r8;
|
||||
|
||||
@cil_literal = @cil_ldnull | @cil_ldc_i | @cil_ldc_r | @cil_ldstr;
|
||||
|
||||
// Control flow
|
||||
|
||||
@cil_conditional_jump = @cil_binary_jump | @cil_unary_jump;
|
||||
@cil_binary_jump = @cil_beq_s | @cil_bge_s | @cil_bgt_s | @cil_ble_s | @cil_blt_s |
|
||||
@cil_bne_un_s | @cil_bge_un_s | @cil_bgt_un_s | @cil_ble_un_s | @cil_blt_un_s |
|
||||
@cil_beq | @cil_bge | @cil_bgt | @cil_ble | @cil_blt |
|
||||
@cil_bne_un | @cil_bge_un | @cil_bgt_un | @cil_ble_un | @cil_blt_un;
|
||||
@cil_unary_jump = @cil_brfalse_s | @cil_brtrue_s | @cil_brfalse | @cil_brtrue | @cil_switch;
|
||||
@cil_unconditional_jump = @cil_br | @cil_br_s | @cil_leave_any;
|
||||
@cil_leave_any = @cil_leave | @cil_leave_s;
|
||||
@cil_jump = @cil_unconditional_jump | @cil_conditional_jump;
|
||||
|
||||
// CIL call instructions
|
||||
|
||||
@cil_call_any = @cil_jmp | @cil_call | @cil_calli | @cil_tail | @cil_callvirt | @cil_newobj;
|
||||
|
||||
// CIL expression instructions
|
||||
|
||||
@cil_expr = @cil_literal | @cil_binary_expr | @cil_unary_expr | @cil_call_any | @cil_read_access |
|
||||
@cil_newarr | @cil_ldtoken | @cil_sizeof |
|
||||
@cil_ldftn | @cil_ldvirtftn | @cil_localloc | @cil_mkrefany | @cil_refanytype | @cil_arglist | @cil_dup;
|
||||
|
||||
@cil_unary_expr =
|
||||
@cil_conversion_operation | @cil_unary_arithmetic_operation | @cil_unary_bitwise_operation|
|
||||
@cil_ldlen | @cil_isinst | @cil_box | @cil_ldobj | @cil_castclass | @cil_unbox_any |
|
||||
@cil_ldind | @cil_unbox;
|
||||
|
||||
@cil_conversion_operation =
|
||||
@cil_conv_i1 | @cil_conv_i2 | @cil_conv_i4 | @cil_conv_i8 |
|
||||
@cil_conv_u1 | @cil_conv_u2 | @cil_conv_u4 | @cil_conv_u8 |
|
||||
@cil_conv_ovf_i | @cil_conv_ovf_i_un | @cil_conv_ovf_i1 | @cil_conv_ovf_i1_un |
|
||||
@cil_conv_ovf_i2 | @cil_conv_ovf_i2_un | @cil_conv_ovf_i4 | @cil_conv_ovf_i4_un |
|
||||
@cil_conv_ovf_i8 | @cil_conv_ovf_i8_un | @cil_conv_ovf_u | @cil_conv_ovf_u_un |
|
||||
@cil_conv_ovf_u1 | @cil_conv_ovf_u1_un | @cil_conv_ovf_u2 | @cil_conv_ovf_u2_un |
|
||||
@cil_conv_ovf_u4 | @cil_conv_ovf_u4_un | @cil_conv_ovf_u8 | @cil_conv_ovf_u8_un |
|
||||
@cil_conv_r4 | @cil_conv_r8 | @cil_conv_ovf_u2 | @cil_conv_ovf_u2_un |
|
||||
@cil_conv_i | @cil_conv_u | @cil_conv_r_un;
|
||||
|
||||
@cil_ldind = @cil_ldind_i | @cil_ldind_i1 | @cil_ldind_i2 | @cil_ldind_i4 | @cil_ldind_i8 |
|
||||
@cil_ldind_r4 | @cil_ldind_r8 | @cil_ldind_ref | @cil_ldind_u1 | @cil_ldind_u2 | @cil_ldind_u4;
|
||||
|
||||
@cil_stind = @cil_stind_i | @cil_stind_i1 | @cil_stind_i2 | @cil_stind_i4 | @cil_stind_i8 |
|
||||
@cil_stind_r4 | @cil_stind_r8 | @cil_stind_ref;
|
||||
|
||||
@cil_bitwise_operation = @cil_binary_bitwise_operation | @cil_unary_bitwise_operation;
|
||||
|
||||
@cil_binary_bitwise_operation = @cil_and | @cil_or | @cil_xor | @cil_shr | @cil_shr | @cil_shr_un | @cil_shl;
|
||||
|
||||
@cil_binary_arithmetic_operation = @cil_add | @cil_sub | @cil_mul | @cil_div | @cil_div_un |
|
||||
@cil_rem | @cil_rem_un | @cil_add_ovf | @cil_add_ovf_un | @cil_mul_ovf | @cil_mul_ovf_un |
|
||||
@cil_sub_ovf | @cil_sub_ovf_un;
|
||||
|
||||
@cil_unary_bitwise_operation = @cil_not;
|
||||
|
||||
@cil_binary_expr = @cil_binary_arithmetic_operation | @cil_binary_bitwise_operation | @cil_read_array | @cil_comparison_operation;
|
||||
|
||||
@cil_unary_arithmetic_operation = @cil_neg;
|
||||
|
||||
@cil_comparison_operation = @cil_cgt_un | @cil_ceq | @cil_cgt | @cil_clt | @cil_clt_un;
|
||||
|
||||
// Elements that retrieve an address of something
|
||||
@cil_read_ref = @cil_ldloca_s | @cil_ldarga_s | @cil_ldflda | @cil_ldsflda | @cil_ldelema;
|
||||
|
||||
// CIL array instructions
|
||||
|
||||
@cil_read_array =
|
||||
@cil_ldelem | @cil_ldelema | @cil_ldelem_i1 | @cil_ldelem_ref | @cil_ldelem_i |
|
||||
@cil_ldelem_i1 | @cil_ldelem_i2 | @cil_ldelem_i4 | @cil_ldelem_i8 | @cil_ldelem_r4 |
|
||||
@cil_ldelem_r8 | @cil_ldelem_u1 | @cil_ldelem_u2 | @cil_ldelem_u4;
|
||||
|
||||
@cil_write_array = @cil_stelem | @cil_stelem_ref |
|
||||
@cil_stelem_i | @cil_stelem_i1 | @cil_stelem_i2 | @cil_stelem_i4 | @cil_stelem_i8 |
|
||||
@cil_stelem_r4 | @cil_stelem_r8;
|
||||
|
||||
@cil_throw_any = @cil_throw | @cil_rethrow;
|
||||
|
||||
#keyset[impl, index]
|
||||
cil_instruction(
|
||||
unique int id: @cil_instruction,
|
||||
int opcode: int ref,
|
||||
int index: int ref,
|
||||
int impl: @cil_method_implementation ref);
|
||||
|
||||
cil_jump(
|
||||
unique int instruction: @cil_jump ref,
|
||||
int target: @cil_instruction ref);
|
||||
|
||||
cil_access(
|
||||
unique int instruction: @cil_instruction ref,
|
||||
int target: @cil_accessible ref);
|
||||
|
||||
cil_value(
|
||||
unique int instruction: @cil_literal ref,
|
||||
string value: string ref);
|
||||
|
||||
#keyset[instruction, index]
|
||||
cil_switch(
|
||||
int instruction: @cil_switch ref,
|
||||
int index: int ref,
|
||||
int target: @cil_instruction ref);
|
||||
|
||||
cil_instruction_location(
|
||||
unique int id: @cil_instruction ref,
|
||||
int loc: @location ref);
|
||||
|
||||
cil_type_location(
|
||||
int id: @cil_type ref,
|
||||
int loc: @location ref);
|
||||
|
||||
cil_method_location(
|
||||
int id: @cil_method ref,
|
||||
int loc: @location ref);
|
||||
|
||||
@cil_namespace = @namespace;
|
||||
|
||||
@cil_type_container = @cil_type | @cil_namespace | @cil_method;
|
||||
|
||||
case @cil_type.kind of
|
||||
0 = @cil_valueorreftype
|
||||
| 1 = @cil_typeparameter
|
||||
| 2 = @cil_array_type
|
||||
| 3 = @cil_pointer_type
|
||||
| 4 = @cil_function_pointer_type
|
||||
;
|
||||
|
||||
cil_type(
|
||||
unique int id: @cil_type,
|
||||
string name: string ref,
|
||||
int kind: int ref,
|
||||
int parent: @cil_type_container ref,
|
||||
int sourceDecl: @cil_type ref);
|
||||
|
||||
cil_pointer_type(
|
||||
unique int id: @cil_pointer_type ref,
|
||||
int pointee: @cil_type ref);
|
||||
|
||||
cil_array_type(
|
||||
unique int id: @cil_array_type ref,
|
||||
int element_type: @cil_type ref,
|
||||
int rank: int ref);
|
||||
|
||||
cil_function_pointer_return_type(
|
||||
unique int id: @cil_function_pointer_type ref,
|
||||
int return_type: @cil_type ref);
|
||||
|
||||
cil_method(
|
||||
unique int id: @cil_method,
|
||||
string name: string ref,
|
||||
int parent: @cil_type ref,
|
||||
int return_type: @cil_type ref);
|
||||
|
||||
cil_method_source_declaration(
|
||||
unique int method: @cil_method ref,
|
||||
int source: @cil_method ref);
|
||||
|
||||
cil_method_implementation(
|
||||
unique int id: @cil_method_implementation,
|
||||
int method: @cil_method ref,
|
||||
int location: @assembly ref);
|
||||
|
||||
cil_implements(
|
||||
int id: @cil_method ref,
|
||||
int decl: @cil_method ref);
|
||||
|
||||
#keyset[parent, name]
|
||||
cil_field(
|
||||
unique int id: @cil_field,
|
||||
int parent: @cil_type ref,
|
||||
string name: string ref,
|
||||
int field_type: @cil_type ref);
|
||||
|
||||
@cil_element = @cil_instruction | @cil_declaration | @cil_handler | @cil_attribute | @cil_namespace;
|
||||
@cil_named_element = @cil_declaration | @cil_namespace;
|
||||
@cil_declaration = @cil_variable | @cil_method | @cil_type | @cil_member;
|
||||
@cil_accessible = @cil_declaration;
|
||||
@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 | @cil_function_pointer_type;
|
||||
@cil_parameterizable = @cil_method | @cil_function_pointer_type;
|
||||
@cil_has_type_annotation = @cil_stack_variable | @cil_property | @cil_field | @cil_method | @cil_function_pointer_type;
|
||||
|
||||
#keyset[parameterizable, index]
|
||||
cil_parameter(
|
||||
unique int id: @cil_parameter,
|
||||
int parameterizable: @cil_parameterizable ref,
|
||||
int index: int ref,
|
||||
int param_type: @cil_type ref);
|
||||
|
||||
cil_parameter_in(unique int id: @cil_parameter ref);
|
||||
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_type_annotation(
|
||||
int id: @cil_has_type_annotation ref,
|
||||
int annotation: int ref);
|
||||
|
||||
cil_getter(unique int prop: @cil_property ref,
|
||||
int method: @cil_method ref);
|
||||
|
||||
cil_adder(unique int event: @cil_event ref,
|
||||
int method: @cil_method ref);
|
||||
|
||||
cil_remover(unique int event: @cil_event ref, int method: @cil_method ref);
|
||||
|
||||
cil_raiser(unique int event: @cil_event ref, int method: @cil_method ref);
|
||||
|
||||
cil_property(
|
||||
unique int id: @cil_property,
|
||||
int parent: @cil_type ref,
|
||||
string name: string ref,
|
||||
int property_type: @cil_type ref);
|
||||
|
||||
#keyset[parent, name]
|
||||
cil_event(unique int id: @cil_event,
|
||||
int parent: @cil_type ref,
|
||||
string name: string ref,
|
||||
int event_type: @cil_type ref);
|
||||
|
||||
#keyset[impl, index]
|
||||
cil_local_variable(
|
||||
unique int id: @cil_local_variable,
|
||||
int impl: @cil_method_implementation ref,
|
||||
int index: int ref,
|
||||
int var_type: @cil_type ref);
|
||||
|
||||
cil_function_pointer_calling_conventions(
|
||||
int id: @cil_function_pointer_type ref,
|
||||
int kind: int ref);
|
||||
|
||||
// CIL handlers (exception handlers etc).
|
||||
|
||||
case @cil_handler.kind of
|
||||
0 = @cil_catch_handler
|
||||
| 1 = @cil_filter_handler
|
||||
| 2 = @cil_finally_handler
|
||||
| 4 = @cil_fault_handler
|
||||
;
|
||||
|
||||
#keyset[impl, index]
|
||||
cil_handler(
|
||||
unique int id: @cil_handler,
|
||||
int impl: @cil_method_implementation ref,
|
||||
int index: int ref,
|
||||
int kind: int ref,
|
||||
int try_start: @cil_instruction ref,
|
||||
int try_end: @cil_instruction ref,
|
||||
int handler_start: @cil_instruction ref);
|
||||
|
||||
cil_handler_filter(
|
||||
unique int id: @cil_handler ref,
|
||||
int filter_start: @cil_instruction ref);
|
||||
|
||||
cil_handler_type(
|
||||
unique int id: @cil_handler ref,
|
||||
int catch_type: @cil_type ref);
|
||||
|
||||
@cil_controlflow_node = @cil_entry_point | @cil_instruction;
|
||||
|
||||
@cil_entry_point = @cil_method_implementation | @cil_handler;
|
||||
|
||||
@cil_dataflow_node = @cil_instruction | @cil_variable | @cil_method;
|
||||
|
||||
cil_method_stack_size(
|
||||
unique int method: @cil_method_implementation ref,
|
||||
int size: int ref);
|
||||
|
||||
// CIL modifiers
|
||||
|
||||
cil_public(int id: @cil_member ref);
|
||||
cil_private(int id: @cil_member ref);
|
||||
cil_protected(int id: @cil_member ref);
|
||||
cil_internal(int id: @cil_member ref);
|
||||
cil_static(int id: @cil_member ref);
|
||||
cil_sealed(int id: @cil_member ref);
|
||||
cil_virtual(int id: @cil_method ref);
|
||||
cil_abstract(int id: @cil_member ref);
|
||||
cil_class(int id: @cil_type ref);
|
||||
cil_interface(int id: @cil_type ref);
|
||||
cil_security(int id: @cil_member ref);
|
||||
cil_requiresecobject(int id: @cil_method ref);
|
||||
cil_specialname(int id: @cil_method ref);
|
||||
cil_newslot(int id: @cil_method ref);
|
||||
|
||||
cil_base_class(unique int id: @cil_type ref, int base: @cil_type ref);
|
||||
cil_base_interface(int id: @cil_type ref, int base: @cil_type ref);
|
||||
cil_enum_underlying_type(unique int id: @cil_type ref, int underlying: @cil_type ref);
|
||||
|
||||
#keyset[unbound, index]
|
||||
cil_type_parameter(
|
||||
int unbound: @cil_member ref,
|
||||
int index: int ref,
|
||||
int param: @cil_typeparameter ref);
|
||||
|
||||
#keyset[bound, index]
|
||||
cil_type_argument(
|
||||
int bound: @cil_member ref,
|
||||
int index: int ref,
|
||||
int t: @cil_type ref);
|
||||
|
||||
// CIL type parameter constraints
|
||||
|
||||
cil_typeparam_covariant(int tp: @cil_typeparameter ref);
|
||||
cil_typeparam_contravariant(int tp: @cil_typeparameter ref);
|
||||
cil_typeparam_class(int tp: @cil_typeparameter ref);
|
||||
cil_typeparam_struct(int tp: @cil_typeparameter ref);
|
||||
cil_typeparam_new(int tp: @cil_typeparameter ref);
|
||||
cil_typeparam_constraint(int tp: @cil_typeparameter ref, int supertype: @cil_type ref);
|
||||
|
||||
// CIL attributes
|
||||
|
||||
cil_attribute(
|
||||
unique int attributeid: @cil_attribute,
|
||||
int element: @cil_declaration ref,
|
||||
int constructor: @cil_method ref);
|
||||
|
||||
#keyset[attribute_id, param]
|
||||
cil_attribute_named_argument(
|
||||
int attribute_id: @cil_attribute ref,
|
||||
string param: string ref,
|
||||
string value: string ref);
|
||||
|
||||
#keyset[attribute_id, index]
|
||||
cil_attribute_positional_argument(
|
||||
int attribute_id: @cil_attribute ref,
|
||||
int index: int ref,
|
||||
string value: string ref);
|
||||
|
||||
|
||||
// Common .Net data model covering both C# and CIL
|
||||
|
||||
// Common elements
|
||||
@dotnet_element = @element | @cil_element;
|
||||
@dotnet_named_element = @named_element | @cil_named_element;
|
||||
@dotnet_callable = @callable | @cil_method;
|
||||
@dotnet_variable = @variable | @cil_variable;
|
||||
@dotnet_field = @field | @cil_field;
|
||||
@dotnet_parameter = @parameter | @cil_parameter;
|
||||
@dotnet_declaration = @declaration | @cil_declaration;
|
||||
@dotnet_member = @member | @cil_member;
|
||||
@dotnet_event = @event | @cil_event;
|
||||
@dotnet_property = @property | @cil_property | @indexer;
|
||||
@dotnet_parameterizable = @parameterizable | @cil_parameterizable;
|
||||
|
||||
// Common types
|
||||
@dotnet_type = @type | @cil_type;
|
||||
@dotnet_call = @call | @cil_call_any;
|
||||
@dotnet_throw = @throw_element | @cil_throw_any;
|
||||
@dotnet_valueorreftype = @cil_valueorreftype | @value_or_ref_type | @cil_array_type | @void_type;
|
||||
@dotnet_typeparameter = @type_parameter | @cil_typeparameter;
|
||||
@dotnet_array_type = @array_type | @cil_array_type;
|
||||
@dotnet_pointer_type = @pointer_type | @cil_pointer_type;
|
||||
@dotnet_type_parameter = @type_parameter | @cil_typeparameter;
|
||||
@dotnet_generic = @dotnet_valueorreftype | @dotnet_callable;
|
||||
|
||||
// Attributes
|
||||
@dotnet_attribute = @attribute | @cil_attribute;
|
||||
|
||||
// Expressions
|
||||
@dotnet_expr = @expr | @cil_expr;
|
||||
|
||||
// Literals
|
||||
@dotnet_literal = @literal_expr | @cil_literal;
|
||||
@dotnet_string_literal = @string_literal_expr | @cil_ldstr;
|
||||
@dotnet_int_literal = @integer_literal_expr | @cil_ldc_i;
|
||||
@dotnet_float_literal = @float_literal_expr | @cil_ldc_r;
|
||||
@dotnet_null_literal = @null_literal_expr | @cil_ldnull;
|
||||
|
||||
@metadata_entity = @cil_method | @cil_type | @cil_field | @cil_property | @field | @property |
|
||||
@callable | @value_or_ref_type | @void_type;
|
||||
|
||||
metadata_handle(int entity : @metadata_entity ref, int location: @assembly ref, int handle: int ref)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,66 @@
|
||||
description: Delete all `cil` and `dotnet` related relations and types.
|
||||
compatibility: breaking
|
||||
cil_instruction.rel: delete
|
||||
cil_jump.rel: delete
|
||||
cil_access.rel: delete
|
||||
cil_value.rel: delete
|
||||
cil_switch.rel: delete
|
||||
cil_instruction_location.rel: delete
|
||||
cil_type_location.rel: delete
|
||||
cil_method_location.rel: delete
|
||||
cil_type.rel: delete
|
||||
cil_pointer_type.rel: delete
|
||||
cil_array_type.rel: delete
|
||||
cil_function_pointer_return_type.rel: delete
|
||||
cil_method.rel: delete
|
||||
cil_method_source_declaration.rel: delete
|
||||
cil_method_implementation.rel: delete
|
||||
cil_implements.rel: delete
|
||||
cil_field.rel: delete
|
||||
cil_parameter.rel: delete
|
||||
cil_parameter_in.rel: delete
|
||||
cil_parameter_out.rel: delete
|
||||
cil_setter.rel: delete
|
||||
cil_custom_modifiers.rel: delete
|
||||
cil_type_annotation.rel: delete
|
||||
cil_getter.rel: delete
|
||||
cil_adder.rel: delete
|
||||
cil_remover.rel: delete
|
||||
cil_raiser.rel: delete
|
||||
cil_property.rel: delete
|
||||
cil_event.rel: delete
|
||||
cil_local_variable.rel: delete
|
||||
cil_function_pointer_calling_conventions.rel: delete
|
||||
cil_handler.rel: delete
|
||||
cil_handler_filter.rel: delete
|
||||
cil_handler_type.rel: delete
|
||||
cil_method_stack_size.rel: delete
|
||||
cil_public.rel: delete
|
||||
cil_private.rel: delete
|
||||
cil_protected.rel: delete
|
||||
cil_internal.rel: delete
|
||||
cil_static.rel: delete
|
||||
cil_sealed.rel: delete
|
||||
cil_virtual.rel: delete
|
||||
cil_abstract.rel: delete
|
||||
cil_class.rel: delete
|
||||
cil_interface.rel: delete
|
||||
cil_security.rel: delete
|
||||
cil_requiresecobject.rel: delete
|
||||
cil_specialname.rel: delete
|
||||
cil_newslot.rel: delete
|
||||
cil_base_class.rel: delete
|
||||
cil_base_interface.rel: delete
|
||||
cil_enum_underlying_type.rel: delete
|
||||
cil_type_parameter.rel: delete
|
||||
cil_type_argument.rel: delete
|
||||
cil_typeparam_covariant.rel: delete
|
||||
cil_typeparam_contravariant.rel: delete
|
||||
cil_typeparam_class.rel: delete
|
||||
cil_typeparam_struct.rel: delete
|
||||
cil_typeparam_new.rel: delete
|
||||
cil_typeparam_constraint.rel: delete
|
||||
cil_attribute.rel: delete
|
||||
cil_attribute_named_argument.rel: delete
|
||||
cil_attribute_positional_argument.rel: delete
|
||||
metadata_handle.rel: delete
|
||||
@@ -1,55 +0,0 @@
|
||||
| Members.cs:3:26:3:37 | EventHandler | Types.EventHandler |
|
||||
| Members.cs:6:11:6:15 | Class | Types.Class |
|
||||
| Members.cs:9:15:9:25 | NestedClass | Types.Class.NestedClass |
|
||||
| Members.cs:12:20:12:28 | Method`1 | System.String Types.Class.NestedClass.Method`1(!0) |
|
||||
| Members.cs:12:27:12:27 | T | !0 |
|
||||
| Members.cs:14:34:14:36 | get_Item | System.String Types.Class.NestedClass.get_Item(System.Int32) |
|
||||
| Members.cs:14:55:14:57 | set_Item | System.Void Types.Class.NestedClass.set_Item(System.Int32,System.String) |
|
||||
| Members.cs:18:27:18:29 | get_Prop | System.String Types.Class.NestedClass.get_Prop() |
|
||||
| Members.cs:18:32:18:34 | set_Prop | System.Void Types.Class.NestedClass.set_Prop(System.String) |
|
||||
| Members.cs:20:32:20:36 | add_Event | System.Void Types.Class.NestedClass.add_Event(Types.EventHandler) |
|
||||
| Members.cs:20:32:20:36 | remove_Event | System.Void Types.Class.NestedClass.remove_Event(Types.EventHandler) |
|
||||
| Members.cs:24:14:24:19 | Method | System.Void Types.Class.Method() |
|
||||
| Members.cs:26:30:26:32 | get_Item | System.String Types.Class.get_Item(System.Int32) |
|
||||
| Members.cs:26:51:26:53 | set_Item | System.Void Types.Class.set_Item(System.Int32,System.String) |
|
||||
| Members.cs:30:23:30:25 | get_Prop | System.String Types.Class.get_Prop() |
|
||||
| Members.cs:30:28:30:30 | set_Prop | System.Void Types.Class.set_Prop(System.String) |
|
||||
| Members.cs:32:28:32:32 | add_Event | System.Void Types.Class.add_Event(Types.EventHandler) |
|
||||
| Members.cs:32:28:32:32 | remove_Event | System.Void Types.Class.remove_Event(Types.EventHandler) |
|
||||
| Members.cs:35:20:35:25 | Class2 | Types.Class2 |
|
||||
| Members.cs:37:23:37:34 | NestedClass2 | Types.Class2.NestedClass2 |
|
||||
| Members.cs:39:28:39:36 | Method`1 | System.String Types.Class2.NestedClass2.Method`1(!0) |
|
||||
| Members.cs:39:35:39:35 | T | !0 |
|
||||
| Members.cs:40:42:40:44 | get_Item | System.String Types.Class2.NestedClass2.get_Item(System.Int32) |
|
||||
| Members.cs:40:63:40:65 | set_Item | System.Void Types.Class2.NestedClass2.set_Item(System.Int32,System.String) |
|
||||
| Members.cs:42:35:42:37 | get_Prop | System.String Types.Class2.NestedClass2.get_Prop() |
|
||||
| Members.cs:42:40:42:42 | set_Prop | System.Void Types.Class2.NestedClass2.set_Prop(System.String) |
|
||||
| Members.cs:43:40:43:44 | add_Event | System.Void Types.Class2.NestedClass2.add_Event(Types.EventHandler) |
|
||||
| Members.cs:43:40:43:44 | remove_Event | System.Void Types.Class2.NestedClass2.remove_Event(Types.EventHandler) |
|
||||
| Members.cs:46:22:46:27 | Method | System.Void Types.Class2.Method() |
|
||||
| Members.cs:47:38:47:40 | get_Item | System.String Types.Class2.get_Item(System.Int32) |
|
||||
| Members.cs:47:59:47:61 | set_Item | System.Void Types.Class2.set_Item(System.Int32,System.String) |
|
||||
| Members.cs:49:31:49:33 | get_Prop | System.String Types.Class2.get_Prop() |
|
||||
| Members.cs:49:36:49:38 | set_Prop | System.Void Types.Class2.set_Prop(System.String) |
|
||||
| Members.cs:50:36:50:40 | add_Event | System.Void Types.Class2.add_Event(Types.EventHandler) |
|
||||
| Members.cs:50:36:50:40 | remove_Event | System.Void Types.Class2.remove_Event(Types.EventHandler) |
|
||||
| Members.cs:54:15:54:23 | Interface | Types.Interface |
|
||||
| Members.cs:56:14:56:19 | Method | System.Void Types.Interface.Method() |
|
||||
| Members.cs:57:30:57:32 | get_Item | System.String Types.Interface.get_Item(System.Int32) |
|
||||
| Members.cs:57:35:57:37 | set_Item | System.Void Types.Interface.set_Item(System.Int32,System.String) |
|
||||
| Members.cs:58:23:58:25 | get_Prop | System.String Types.Interface.get_Prop() |
|
||||
| Members.cs:58:28:58:30 | set_Prop | System.Void Types.Interface.set_Prop(System.String) |
|
||||
| Members.cs:59:28:59:32 | add_Event | System.Void Types.Interface.add_Event(Types.EventHandler) |
|
||||
| Members.cs:59:28:59:32 | remove_Event | System.Void Types.Interface.remove_Event(Types.EventHandler) |
|
||||
| Members.cs:62:24:62:33 | Interface2 | Types.Interface2 |
|
||||
| Members.cs:64:14:64:19 | Method | System.Void Types.Interface2.Method() |
|
||||
| Members.cs:65:30:65:32 | get_Item | System.String Types.Interface2.get_Item(System.Int32) |
|
||||
| Members.cs:65:35:65:37 | set_Item | System.Void Types.Interface2.set_Item(System.Int32,System.String) |
|
||||
| Members.cs:66:23:66:25 | get_Prop | System.String Types.Interface2.get_Prop() |
|
||||
| Members.cs:66:28:66:30 | set_Prop | System.Void Types.Interface2.set_Prop(System.String) |
|
||||
| Members.cs:67:28:67:32 | add_Event | System.Void Types.Interface2.add_Event(Types.EventHandler) |
|
||||
| Members.cs:67:28:67:32 | remove_Event | System.Void Types.Interface2.remove_Event(Types.EventHandler) |
|
||||
| Members.cs:71:10:71:13 | Enum | Types.Enum |
|
||||
| Members.cs:73:10:73:14 | Enum2 | Types.Enum2 |
|
||||
| Members.cs:76:12:76:17 | Struct | Types.Struct |
|
||||
| Members.cs:78:12:78:18 | Struct2 | Types.Struct2 |
|
||||
@@ -1,5 +0,0 @@
|
||||
import csharp
|
||||
|
||||
deprecated query predicate labels(NamedElement ne, string label) {
|
||||
ne.getLabel() = label and ne.fromSource()
|
||||
}
|
||||
Reference in New Issue
Block a user