Merge pull request #15884 from michaelnebel/csharp/cleanupcil

C#: CIL and Dotnet cleanup (removal).
This commit is contained in:
Michael Nebel
2024-09-18 11:43:41 +02:00
committed by GitHub
57 changed files with 7188 additions and 6585 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,2 @@
description: Add `cil` and `dotnet` related relations and types.
compatibility: backwards

View File

@@ -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;
}
}
}
}

View File

@@ -26,7 +26,6 @@ namespace Semmle.Extraction.CSharp.Entities
public override void Populate(TextWriter trapFile)
{
PopulateMetadataHandle(trapFile);
PopulateAttributes();
ContainingType!.PopulateGenerics();
PopulateNullability(trapFile, Symbol.GetAnnotatedType());

View File

@@ -360,7 +360,6 @@ namespace Semmle.Extraction.CSharp.Entities
PopulateParameters();
PopulateMethodBody(trapFile);
PopulateGenerics(trapFile);
PopulateMetadataHandle(trapFile);
PopulateNullability(trapFile, Symbol.GetAnnotatedReturnType());
}

View File

@@ -34,7 +34,6 @@ namespace Semmle.Extraction.CSharp.Entities
public override void Populate(TextWriter trapFile)
{
PopulateMetadataHandle(trapFile);
PopulateAttributes();
PopulateModifiers(trapFile);
BindComments();

View File

@@ -77,7 +77,6 @@ namespace Semmle.Extraction.CSharp.Entities
protected void PopulateType(TextWriter trapFile, bool constructUnderlyingTupleType = false)
{
PopulateMetadataHandle(trapFile);
PopulateAttributes();
trapFile.Write("types(");

View File

@@ -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);

View File

@@ -0,0 +1,4 @@
---
category: breaking
---
* C#: Remove all CIL tables and related QL library functionality.

View File

@@ -1,5 +0,0 @@
/**
* The default QL library for modeling the Common Intermediate Language (CIL).
*/
import semmle.code.cil.CIL as CIL

View File

@@ -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

View File

@@ -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 { }

View File

@@ -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(_) }
}

View File

@@ -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))
}
}

View File

@@ -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

View File

@@ -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())
)
}

View File

@@ -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" }
}

View File

@@ -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" }
}

View File

@@ -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) }
}

View File

@@ -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) }
}

View File

@@ -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()
}
}

View File

@@ -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())
}

View File

@@ -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() }
}

View File

@@ -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 {...}" }
}

View File

@@ -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() }
}

View File

@@ -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

View File

@@ -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() }
}

View File

@@ -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, _) }
}

View File

@@ -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) }
}
}

View File

@@ -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) }
}

View File

@@ -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) }
}

View File

@@ -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() }
}

View File

@@ -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) }
}

View File

@@ -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

View File

@@ -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() }

View File

@@ -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() }
}

View File

@@ -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. */

View File

@@ -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" }

View File

@@ -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()
}
}

View File

@@ -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() }
}

View File

@@ -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

View File

@@ -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() }
}

View File

@@ -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 { }

View File

@@ -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), ","
)
}

View File

@@ -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() = "" }
}

View File

@@ -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(_) }
}

View File

@@ -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" }
}

View File

@@ -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() }
}

View File

@@ -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() }
}

View File

@@ -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

View File

@@ -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

View File

@@ -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 |

View File

@@ -1,5 +0,0 @@
import csharp
deprecated query predicate labels(NamedElement ne, string label) {
ne.getLabel() = label and ne.fromSource()
}