mirror of
https://github.com/github/codeql.git
synced 2026-05-05 05:35:13 +02:00
Merge branch 'main' into atorralba/fix-local-and-remote-flow-tests
This commit is contained in:
@@ -367,6 +367,7 @@
|
||||
],
|
||||
"Inline Test Expectations": [
|
||||
"cpp/ql/test/TestUtilities/InlineExpectationsTest.qll",
|
||||
"csharp/ql/test/TestUtilities/InlineExpectationsTest.qll",
|
||||
"java/ql/test/TestUtilities/InlineExpectationsTest.qll",
|
||||
"python/ql/test/TestUtilities/InlineExpectationsTest.qll"
|
||||
],
|
||||
@@ -461,5 +462,12 @@
|
||||
"ReDoS Polynomial Python/JS": [
|
||||
"javascript/ql/lib/semmle/javascript/security/performance/SuperlinearBackTracking.qll",
|
||||
"python/ql/lib/semmle/python/security/performance/SuperlinearBackTracking.qll"
|
||||
],
|
||||
"CodeQL Tutorial": [
|
||||
"cpp/ql/lib/tutorial.qll",
|
||||
"csharp/ql/lib/tutorial.qll",
|
||||
"java/ql/lib/tutorial.qll",
|
||||
"javascript/ql/lib/tutorial.qll",
|
||||
"python/ql/lib/tutorial.qll"
|
||||
]
|
||||
}
|
||||
2
cpp/change-notes/2021-10-01-improper-null-termination.md
Normal file
2
cpp/change-notes/2021-10-01-improper-null-termination.md
Normal file
@@ -0,0 +1,2 @@
|
||||
lgtm,codescanning
|
||||
* Several improvements made to the `NullTermination.qll` library and the 'Potential improper null termination' (cpp/improper-null-termination). These changes reduce the number of false positive results for this query and related query 'User-controlled data may not be null terminated' (cpp/user-controlled-null-termination-tainted).
|
||||
3
cpp/change-notes/2021-10-07-extraction-errors.md
Normal file
3
cpp/change-notes/2021-10-07-extraction-errors.md
Normal file
@@ -0,0 +1,3 @@
|
||||
codescanning
|
||||
* Problems with extraction that in most cases won't break the analysis in a significant way are now reported as warnings rather than errors.
|
||||
* The failed extractor invocations query now has severity `error`.
|
||||
@@ -275,9 +275,8 @@ class Declaration extends Locatable, @declaration {
|
||||
* `getTemplateArgumentKind(0)`.
|
||||
*/
|
||||
final Locatable getTemplateArgumentKind(int index) {
|
||||
if exists(getTemplateArgumentValue(index))
|
||||
then result = getTemplateArgumentType(index)
|
||||
else none()
|
||||
exists(getTemplateArgumentValue(index)) and
|
||||
result = getTemplateArgumentType(index)
|
||||
}
|
||||
|
||||
/** Gets the number of template arguments for this declaration. */
|
||||
|
||||
@@ -1650,7 +1650,6 @@ class RoutineType extends Type, @routinetype {
|
||||
i = 0 and result = "" and not exists(this.getAParameterType())
|
||||
or
|
||||
(
|
||||
exists(this.getParameterType(i)) and
|
||||
if i < max(int j | exists(this.getParameterType(j)))
|
||||
then
|
||||
// Not the last one
|
||||
|
||||
@@ -108,7 +108,7 @@ class XMLParent extends @xmlparent {
|
||||
}
|
||||
|
||||
/** Gets the text value contained in this XML parent. */
|
||||
string getTextValue() { result = allCharactersString() }
|
||||
string getTextValue() { result = this.allCharactersString() }
|
||||
|
||||
/** Gets a printable representation of this XML parent. */
|
||||
string toString() { result = this.getName() }
|
||||
@@ -119,7 +119,7 @@ class XMLFile extends XMLParent, File {
|
||||
XMLFile() { xmlEncoding(this, _) }
|
||||
|
||||
/** Gets a printable representation of this XML file. */
|
||||
override string toString() { result = getName() }
|
||||
override string toString() { result = this.getName() }
|
||||
|
||||
/** Gets the name of this XML file. */
|
||||
override string getName() { result = File.super.getAbsolutePath() }
|
||||
@@ -129,14 +129,14 @@ class XMLFile extends XMLParent, File {
|
||||
*
|
||||
* Gets the path of this XML file.
|
||||
*/
|
||||
deprecated string getPath() { result = getAbsolutePath() }
|
||||
deprecated string getPath() { result = this.getAbsolutePath() }
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `getParentContainer().getAbsolutePath()` instead.
|
||||
*
|
||||
* Gets the path of the folder that contains this XML file.
|
||||
*/
|
||||
deprecated string getFolder() { result = getParentContainer().getAbsolutePath() }
|
||||
deprecated string getFolder() { result = this.getParentContainer().getAbsolutePath() }
|
||||
|
||||
/** Gets the encoding of this XML file. */
|
||||
string getEncoding() { xmlEncoding(this, result) }
|
||||
@@ -200,7 +200,7 @@ class XMLDTD extends XMLLocatable, @xmldtd {
|
||||
*/
|
||||
class XMLElement extends @xmlelement, XMLParent, XMLLocatable {
|
||||
/** Holds if this XML element has the given `name`. */
|
||||
predicate hasName(string name) { name = getName() }
|
||||
predicate hasName(string name) { name = this.getName() }
|
||||
|
||||
/** Gets the name of this XML element. */
|
||||
override string getName() { xmlElements(this, result, _, _, _) }
|
||||
@@ -239,7 +239,7 @@ class XMLElement extends @xmlelement, XMLParent, XMLLocatable {
|
||||
string getAttributeValue(string name) { result = this.getAttribute(name).getValue() }
|
||||
|
||||
/** Gets a printable representation of this XML element. */
|
||||
override string toString() { result = getName() }
|
||||
override string toString() { result = this.getName() }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import cpp
|
||||
private import semmle.code.cpp.models.interfaces.ArrayFunction
|
||||
private import semmle.code.cpp.models.implementations.Strcat
|
||||
import semmle.code.cpp.dataflow.DataFlow
|
||||
|
||||
private predicate mayAddNullTerminatorHelper(Expr e, VariableAccess va, Expr e0) {
|
||||
exists(StackVariable v0, Expr val |
|
||||
@@ -45,22 +46,28 @@ predicate mayAddNullTerminator(Expr e, VariableAccess va) {
|
||||
ae.getRValue().getAChild*() = va
|
||||
)
|
||||
or
|
||||
// Function call: library function, varargs function, function
|
||||
// containing assembler code, or function where the relevant
|
||||
// parameter is potentially added a null terminator.
|
||||
// Function calls...
|
||||
exists(Call c, Function f, int i |
|
||||
e = c and
|
||||
f = c.getTarget() and
|
||||
not functionArgumentMustBeNullTerminated(f, i) and
|
||||
c.getAnArgumentSubExpr(i) = va
|
||||
|
|
||||
not f.hasEntryPoint() and not functionArgumentMustBeNullTerminated(f, i)
|
||||
// library function
|
||||
not f.hasEntryPoint()
|
||||
or
|
||||
// function where the relevant parameter is potentially added a null terminator
|
||||
mayAddNullTerminator(_, f.getParameter(i).getAnAccess())
|
||||
or
|
||||
// varargs function
|
||||
f.isVarargs() and i >= f.getNumberOfParameters()
|
||||
or
|
||||
// function containing assembler code
|
||||
exists(AsmStmt s | s.getEnclosingFunction() = f)
|
||||
or
|
||||
// function where the relevant parameter is returned (leaking it to be potentially null terminated elsewhere)
|
||||
DataFlow::localFlow(DataFlow::parameterNode(f.getParameter(i)),
|
||||
DataFlow::exprNode(any(ReturnStmt rs).getExpr()))
|
||||
)
|
||||
or
|
||||
// Call without target (e.g., function pointer call)
|
||||
|
||||
@@ -344,14 +344,13 @@ private int convertIntToType(int val, IntegralType t) {
|
||||
then if val = 0 then result = 0 else result = 1
|
||||
else
|
||||
if t.isUnsigned()
|
||||
then if val >= 0 and val.bitShiftRight(t.getSize() * 8) = 0 then result = val else none()
|
||||
then val >= 0 and val.bitShiftRight(t.getSize() * 8) = 0 and result = val
|
||||
else
|
||||
if val >= 0 and val.bitShiftRight(t.getSize() * 8 - 1) = 0
|
||||
then result = val
|
||||
else
|
||||
if (-(val + 1)).bitShiftRight(t.getSize() * 8 - 1) = 0
|
||||
then result = val
|
||||
else none()
|
||||
else (
|
||||
(-(val + 1)).bitShiftRight(t.getSize() * 8 - 1) = 0 and result = val
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -937,7 +937,7 @@ class CallContextSpecificCall extends CallContextCall, TSpecificCall {
|
||||
}
|
||||
|
||||
override predicate relevantFor(DataFlowCallable callable) {
|
||||
recordDataFlowCallSite(getCall(), callable)
|
||||
recordDataFlowCallSite(this.getCall(), callable)
|
||||
}
|
||||
|
||||
override predicate matchesCall(DataFlowCall call) { call = this.getCall() }
|
||||
@@ -1257,7 +1257,7 @@ abstract class AccessPathFront extends TAccessPathFront {
|
||||
|
||||
TypedContent getHead() { this = TFrontHead(result) }
|
||||
|
||||
predicate isClearedAt(Node n) { clearsContentCached(n, getHead().getContent()) }
|
||||
predicate isClearedAt(Node n) { clearsContentCached(n, this.getHead().getContent()) }
|
||||
}
|
||||
|
||||
class AccessPathFrontNil extends AccessPathFront, TFrontNil {
|
||||
|
||||
@@ -219,15 +219,13 @@ class DataFlowExpr = Expr;
|
||||
class DataFlowType = Type;
|
||||
|
||||
/** A function call relevant for data flow. */
|
||||
class DataFlowCall extends Expr {
|
||||
DataFlowCall() { this instanceof Call }
|
||||
|
||||
class DataFlowCall extends Expr instanceof Call {
|
||||
/**
|
||||
* Gets the nth argument for this call.
|
||||
*
|
||||
* The range of `n` is from `0` to `getNumberOfArguments() - 1`.
|
||||
*/
|
||||
Expr getArgument(int n) { result = this.(Call).getArgument(n) }
|
||||
Expr getArgument(int n) { result = super.getArgument(n) }
|
||||
|
||||
/** Gets the data flow node corresponding to this call. */
|
||||
ExprNode getNode() { result.getExpr() = this }
|
||||
|
||||
@@ -75,24 +75,26 @@ abstract class Configuration extends DataFlow::Configuration {
|
||||
predicate isSanitizer(DataFlow::Node node) { none() }
|
||||
|
||||
final override predicate isBarrier(DataFlow::Node node) {
|
||||
isSanitizer(node) or
|
||||
this.isSanitizer(node) or
|
||||
defaultTaintSanitizer(node)
|
||||
}
|
||||
|
||||
/** Holds if taint propagation into `node` is prohibited. */
|
||||
predicate isSanitizerIn(DataFlow::Node node) { none() }
|
||||
|
||||
final override predicate isBarrierIn(DataFlow::Node node) { isSanitizerIn(node) }
|
||||
final override predicate isBarrierIn(DataFlow::Node node) { this.isSanitizerIn(node) }
|
||||
|
||||
/** Holds if taint propagation out of `node` is prohibited. */
|
||||
predicate isSanitizerOut(DataFlow::Node node) { none() }
|
||||
|
||||
final override predicate isBarrierOut(DataFlow::Node node) { isSanitizerOut(node) }
|
||||
final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) }
|
||||
|
||||
/** Holds if taint propagation through nodes guarded by `guard` is prohibited. */
|
||||
predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
|
||||
|
||||
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) { isSanitizerGuard(guard) }
|
||||
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) {
|
||||
this.isSanitizerGuard(guard)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the additional taint propagation step from `node1` to `node2`
|
||||
@@ -101,7 +103,7 @@ abstract class Configuration extends DataFlow::Configuration {
|
||||
predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) { none() }
|
||||
|
||||
final override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
isAdditionalTaintStep(node1, node2) or
|
||||
this.isAdditionalTaintStep(node1, node2) or
|
||||
defaultAdditionalTaintStep(node1, node2)
|
||||
}
|
||||
|
||||
|
||||
@@ -75,24 +75,26 @@ abstract class Configuration extends DataFlow::Configuration {
|
||||
predicate isSanitizer(DataFlow::Node node) { none() }
|
||||
|
||||
final override predicate isBarrier(DataFlow::Node node) {
|
||||
isSanitizer(node) or
|
||||
this.isSanitizer(node) or
|
||||
defaultTaintSanitizer(node)
|
||||
}
|
||||
|
||||
/** Holds if taint propagation into `node` is prohibited. */
|
||||
predicate isSanitizerIn(DataFlow::Node node) { none() }
|
||||
|
||||
final override predicate isBarrierIn(DataFlow::Node node) { isSanitizerIn(node) }
|
||||
final override predicate isBarrierIn(DataFlow::Node node) { this.isSanitizerIn(node) }
|
||||
|
||||
/** Holds if taint propagation out of `node` is prohibited. */
|
||||
predicate isSanitizerOut(DataFlow::Node node) { none() }
|
||||
|
||||
final override predicate isBarrierOut(DataFlow::Node node) { isSanitizerOut(node) }
|
||||
final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) }
|
||||
|
||||
/** Holds if taint propagation through nodes guarded by `guard` is prohibited. */
|
||||
predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
|
||||
|
||||
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) { isSanitizerGuard(guard) }
|
||||
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) {
|
||||
this.isSanitizerGuard(guard)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the additional taint propagation step from `node1` to `node2`
|
||||
@@ -101,7 +103,7 @@ abstract class Configuration extends DataFlow::Configuration {
|
||||
predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) { none() }
|
||||
|
||||
final override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
isAdditionalTaintStep(node1, node2) or
|
||||
this.isAdditionalTaintStep(node1, node2) or
|
||||
defaultAdditionalTaintStep(node1, node2)
|
||||
}
|
||||
|
||||
|
||||
@@ -937,7 +937,7 @@ class CallContextSpecificCall extends CallContextCall, TSpecificCall {
|
||||
}
|
||||
|
||||
override predicate relevantFor(DataFlowCallable callable) {
|
||||
recordDataFlowCallSite(getCall(), callable)
|
||||
recordDataFlowCallSite(this.getCall(), callable)
|
||||
}
|
||||
|
||||
override predicate matchesCall(DataFlowCall call) { call = this.getCall() }
|
||||
@@ -1257,7 +1257,7 @@ abstract class AccessPathFront extends TAccessPathFront {
|
||||
|
||||
TypedContent getHead() { this = TFrontHead(result) }
|
||||
|
||||
predicate isClearedAt(Node n) { clearsContentCached(n, getHead().getContent()) }
|
||||
predicate isClearedAt(Node n) { clearsContentCached(n, this.getHead().getContent()) }
|
||||
}
|
||||
|
||||
class AccessPathFrontNil extends AccessPathFront, TFrontNil {
|
||||
|
||||
@@ -75,24 +75,26 @@ abstract class Configuration extends DataFlow::Configuration {
|
||||
predicate isSanitizer(DataFlow::Node node) { none() }
|
||||
|
||||
final override predicate isBarrier(DataFlow::Node node) {
|
||||
isSanitizer(node) or
|
||||
this.isSanitizer(node) or
|
||||
defaultTaintSanitizer(node)
|
||||
}
|
||||
|
||||
/** Holds if taint propagation into `node` is prohibited. */
|
||||
predicate isSanitizerIn(DataFlow::Node node) { none() }
|
||||
|
||||
final override predicate isBarrierIn(DataFlow::Node node) { isSanitizerIn(node) }
|
||||
final override predicate isBarrierIn(DataFlow::Node node) { this.isSanitizerIn(node) }
|
||||
|
||||
/** Holds if taint propagation out of `node` is prohibited. */
|
||||
predicate isSanitizerOut(DataFlow::Node node) { none() }
|
||||
|
||||
final override predicate isBarrierOut(DataFlow::Node node) { isSanitizerOut(node) }
|
||||
final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) }
|
||||
|
||||
/** Holds if taint propagation through nodes guarded by `guard` is prohibited. */
|
||||
predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
|
||||
|
||||
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) { isSanitizerGuard(guard) }
|
||||
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) {
|
||||
this.isSanitizerGuard(guard)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the additional taint propagation step from `node1` to `node2`
|
||||
@@ -101,7 +103,7 @@ abstract class Configuration extends DataFlow::Configuration {
|
||||
predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) { none() }
|
||||
|
||||
final override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
isAdditionalTaintStep(node1, node2) or
|
||||
this.isAdditionalTaintStep(node1, node2) or
|
||||
defaultAdditionalTaintStep(node1, node2)
|
||||
}
|
||||
|
||||
|
||||
@@ -75,24 +75,26 @@ abstract class Configuration extends DataFlow::Configuration {
|
||||
predicate isSanitizer(DataFlow::Node node) { none() }
|
||||
|
||||
final override predicate isBarrier(DataFlow::Node node) {
|
||||
isSanitizer(node) or
|
||||
this.isSanitizer(node) or
|
||||
defaultTaintSanitizer(node)
|
||||
}
|
||||
|
||||
/** Holds if taint propagation into `node` is prohibited. */
|
||||
predicate isSanitizerIn(DataFlow::Node node) { none() }
|
||||
|
||||
final override predicate isBarrierIn(DataFlow::Node node) { isSanitizerIn(node) }
|
||||
final override predicate isBarrierIn(DataFlow::Node node) { this.isSanitizerIn(node) }
|
||||
|
||||
/** Holds if taint propagation out of `node` is prohibited. */
|
||||
predicate isSanitizerOut(DataFlow::Node node) { none() }
|
||||
|
||||
final override predicate isBarrierOut(DataFlow::Node node) { isSanitizerOut(node) }
|
||||
final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) }
|
||||
|
||||
/** Holds if taint propagation through nodes guarded by `guard` is prohibited. */
|
||||
predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
|
||||
|
||||
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) { isSanitizerGuard(guard) }
|
||||
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) {
|
||||
this.isSanitizerGuard(guard)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the additional taint propagation step from `node1` to `node2`
|
||||
@@ -101,7 +103,7 @@ abstract class Configuration extends DataFlow::Configuration {
|
||||
predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) { none() }
|
||||
|
||||
final override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
isAdditionalTaintStep(node1, node2) or
|
||||
this.isAdditionalTaintStep(node1, node2) or
|
||||
defaultAdditionalTaintStep(node1, node2)
|
||||
}
|
||||
|
||||
|
||||
@@ -75,24 +75,26 @@ abstract class Configuration extends DataFlow::Configuration {
|
||||
predicate isSanitizer(DataFlow::Node node) { none() }
|
||||
|
||||
final override predicate isBarrier(DataFlow::Node node) {
|
||||
isSanitizer(node) or
|
||||
this.isSanitizer(node) or
|
||||
defaultTaintSanitizer(node)
|
||||
}
|
||||
|
||||
/** Holds if taint propagation into `node` is prohibited. */
|
||||
predicate isSanitizerIn(DataFlow::Node node) { none() }
|
||||
|
||||
final override predicate isBarrierIn(DataFlow::Node node) { isSanitizerIn(node) }
|
||||
final override predicate isBarrierIn(DataFlow::Node node) { this.isSanitizerIn(node) }
|
||||
|
||||
/** Holds if taint propagation out of `node` is prohibited. */
|
||||
predicate isSanitizerOut(DataFlow::Node node) { none() }
|
||||
|
||||
final override predicate isBarrierOut(DataFlow::Node node) { isSanitizerOut(node) }
|
||||
final override predicate isBarrierOut(DataFlow::Node node) { this.isSanitizerOut(node) }
|
||||
|
||||
/** Holds if taint propagation through nodes guarded by `guard` is prohibited. */
|
||||
predicate isSanitizerGuard(DataFlow::BarrierGuard guard) { none() }
|
||||
|
||||
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) { isSanitizerGuard(guard) }
|
||||
final override predicate isBarrierGuard(DataFlow::BarrierGuard guard) {
|
||||
this.isSanitizerGuard(guard)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the additional taint propagation step from `node1` to `node2`
|
||||
@@ -101,7 +103,7 @@ abstract class Configuration extends DataFlow::Configuration {
|
||||
predicate isAdditionalTaintStep(DataFlow::Node node1, DataFlow::Node node2) { none() }
|
||||
|
||||
final override predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
isAdditionalTaintStep(node1, node2) or
|
||||
this.isAdditionalTaintStep(node1, node2) or
|
||||
defaultAdditionalTaintStep(node1, node2)
|
||||
}
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ class IRBlockBase extends TIRBlock {
|
||||
final string toString() { result = getFirstInstruction(this).toString() }
|
||||
|
||||
/** Gets the source location of the first non-`Phi` instruction in this block. */
|
||||
final Language::Location getLocation() { result = getFirstInstruction().getLocation() }
|
||||
final Language::Location getLocation() { result = this.getFirstInstruction().getLocation() }
|
||||
|
||||
/**
|
||||
* INTERNAL: Do not use.
|
||||
@@ -39,7 +39,7 @@ class IRBlockBase extends TIRBlock {
|
||||
) and
|
||||
this =
|
||||
rank[result + 1](IRBlock funcBlock, int sortOverride, int sortKey1, int sortKey2 |
|
||||
funcBlock.getEnclosingFunction() = getEnclosingFunction() and
|
||||
funcBlock.getEnclosingFunction() = this.getEnclosingFunction() and
|
||||
funcBlock.getFirstInstruction().hasSortKeys(sortKey1, sortKey2) and
|
||||
// Ensure that the block containing `EnterFunction` always comes first.
|
||||
if funcBlock.getFirstInstruction() instanceof EnterFunctionInstruction
|
||||
@@ -59,15 +59,15 @@ class IRBlockBase extends TIRBlock {
|
||||
* Get the `Phi` instructions that appear at the start of this block.
|
||||
*/
|
||||
final PhiInstruction getAPhiInstruction() {
|
||||
Construction::getPhiInstructionBlockStart(result) = getFirstInstruction()
|
||||
Construction::getPhiInstructionBlockStart(result) = this.getFirstInstruction()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an instruction in this block. This includes `Phi` instructions.
|
||||
*/
|
||||
final Instruction getAnInstruction() {
|
||||
result = getInstruction(_) or
|
||||
result = getAPhiInstruction()
|
||||
result = this.getInstruction(_) or
|
||||
result = this.getAPhiInstruction()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -78,7 +78,9 @@ class IRBlockBase extends TIRBlock {
|
||||
/**
|
||||
* Gets the last instruction in this block.
|
||||
*/
|
||||
final Instruction getLastInstruction() { result = getInstruction(getInstructionCount() - 1) }
|
||||
final Instruction getLastInstruction() {
|
||||
result = this.getInstruction(this.getInstructionCount() - 1)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the number of non-`Phi` instructions in this block.
|
||||
@@ -149,7 +151,7 @@ class IRBlock extends IRBlockBase {
|
||||
* Block `A` dominates block `B` if any control flow path from the entry block of the function to
|
||||
* block `B` must pass through block `A`. A block always dominates itself.
|
||||
*/
|
||||
final predicate dominates(IRBlock block) { strictlyDominates(block) or this = block }
|
||||
final predicate dominates(IRBlock block) { this.strictlyDominates(block) or this = block }
|
||||
|
||||
/**
|
||||
* Gets a block on the dominance frontier of this block.
|
||||
@@ -159,8 +161,8 @@ class IRBlock extends IRBlockBase {
|
||||
*/
|
||||
pragma[noinline]
|
||||
final IRBlock dominanceFrontier() {
|
||||
dominates(result.getAPredecessor()) and
|
||||
not strictlyDominates(result)
|
||||
this.dominates(result.getAPredecessor()) and
|
||||
not this.strictlyDominates(result)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -189,7 +191,7 @@ class IRBlock extends IRBlockBase {
|
||||
* Block `A` post-dominates block `B` if any control flow path from `B` to the exit block of the
|
||||
* function must pass through block `A`. A block always post-dominates itself.
|
||||
*/
|
||||
final predicate postDominates(IRBlock block) { strictlyPostDominates(block) or this = block }
|
||||
final predicate postDominates(IRBlock block) { this.strictlyPostDominates(block) or this = block }
|
||||
|
||||
/**
|
||||
* Gets a block on the post-dominance frontier of this block.
|
||||
@@ -199,16 +201,16 @@ class IRBlock extends IRBlockBase {
|
||||
*/
|
||||
pragma[noinline]
|
||||
final IRBlock postPominanceFrontier() {
|
||||
postDominates(result.getASuccessor()) and
|
||||
not strictlyPostDominates(result)
|
||||
this.postDominates(result.getASuccessor()) and
|
||||
not this.strictlyPostDominates(result)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this block is reachable from the entry block of its function.
|
||||
*/
|
||||
final predicate isReachableFromFunctionEntry() {
|
||||
this = getEnclosingIRFunction().getEntryBlock() or
|
||||
getAPredecessor().isReachableFromFunctionEntry()
|
||||
this = this.getEnclosingIRFunction().getEntryBlock() or
|
||||
this.getAPredecessor().isReachableFromFunctionEntry()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -46,12 +46,12 @@ class Operand extends TStageOperand {
|
||||
/**
|
||||
* Gets the location of the source code for this operand.
|
||||
*/
|
||||
final Language::Location getLocation() { result = getUse().getLocation() }
|
||||
final Language::Location getLocation() { result = this.getUse().getLocation() }
|
||||
|
||||
/**
|
||||
* Gets the function that contains this operand.
|
||||
*/
|
||||
final IRFunction getEnclosingIRFunction() { result = getUse().getEnclosingIRFunction() }
|
||||
final IRFunction getEnclosingIRFunction() { result = this.getUse().getEnclosingIRFunction() }
|
||||
|
||||
/**
|
||||
* Gets the `Instruction` that consumes this operand.
|
||||
@@ -74,7 +74,7 @@ class Operand extends TStageOperand {
|
||||
*/
|
||||
final Instruction getDef() {
|
||||
result = this.getAnyDef() and
|
||||
getDefinitionOverlap() instanceof MustExactlyOverlap
|
||||
this.getDefinitionOverlap() instanceof MustExactlyOverlap
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -82,7 +82,7 @@ class Operand extends TStageOperand {
|
||||
*
|
||||
* Gets the `Instruction` that consumes this operand.
|
||||
*/
|
||||
deprecated final Instruction getUseInstruction() { result = getUse() }
|
||||
deprecated final Instruction getUseInstruction() { result = this.getUse() }
|
||||
|
||||
/**
|
||||
* DEPRECATED: use `getAnyDef` or `getDef`. The exact replacement for this
|
||||
@@ -91,7 +91,7 @@ class Operand extends TStageOperand {
|
||||
*
|
||||
* Gets the `Instruction` whose result is the value of the operand.
|
||||
*/
|
||||
deprecated final Instruction getDefinitionInstruction() { result = getAnyDef() }
|
||||
deprecated final Instruction getDefinitionInstruction() { result = this.getAnyDef() }
|
||||
|
||||
/**
|
||||
* Gets the overlap relationship between the operand's definition and its use.
|
||||
@@ -101,7 +101,9 @@ class Operand extends TStageOperand {
|
||||
/**
|
||||
* Holds if the result of the definition instruction does not exactly overlap this use.
|
||||
*/
|
||||
final predicate isDefinitionInexact() { not getDefinitionOverlap() instanceof MustExactlyOverlap }
|
||||
final predicate isDefinitionInexact() {
|
||||
not this.getDefinitionOverlap() instanceof MustExactlyOverlap
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a prefix to use when dumping the operand in an operand list.
|
||||
@@ -121,7 +123,7 @@ class Operand extends TStageOperand {
|
||||
* For example: `this:r3_5`
|
||||
*/
|
||||
final string getDumpString() {
|
||||
result = getDumpLabel() + getInexactSpecifier() + getDefinitionId()
|
||||
result = this.getDumpLabel() + this.getInexactSpecifier() + this.getDefinitionId()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -129,9 +131,9 @@ class Operand extends TStageOperand {
|
||||
* definition is not modeled in SSA.
|
||||
*/
|
||||
private string getDefinitionId() {
|
||||
result = getAnyDef().getResultId()
|
||||
result = this.getAnyDef().getResultId()
|
||||
or
|
||||
not exists(getAnyDef()) and result = "m?"
|
||||
not exists(this.getAnyDef()) and result = "m?"
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -140,7 +142,7 @@ class Operand extends TStageOperand {
|
||||
* the empty string.
|
||||
*/
|
||||
private string getInexactSpecifier() {
|
||||
if isDefinitionInexact() then result = "~" else result = ""
|
||||
if this.isDefinitionInexact() then result = "~" else result = ""
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -155,7 +157,7 @@ class Operand extends TStageOperand {
|
||||
* the definition type, such as in the case of a partial read or a read from a pointer that
|
||||
* has been cast to a different type.
|
||||
*/
|
||||
Language::LanguageType getLanguageType() { result = getAnyDef().getResultLanguageType() }
|
||||
Language::LanguageType getLanguageType() { result = this.getAnyDef().getResultLanguageType() }
|
||||
|
||||
/**
|
||||
* Gets the language-neutral type of the value consumed by this operand. This is usually the same
|
||||
@@ -164,7 +166,7 @@ class Operand extends TStageOperand {
|
||||
* from the definition type, such as in the case of a partial read or a read from a pointer that
|
||||
* has been cast to a different type.
|
||||
*/
|
||||
final IRType getIRType() { result = getLanguageType().getIRType() }
|
||||
final IRType getIRType() { result = this.getLanguageType().getIRType() }
|
||||
|
||||
/**
|
||||
* Gets the type of the value consumed by this operand. This is usually the same as the
|
||||
@@ -173,7 +175,7 @@ class Operand extends TStageOperand {
|
||||
* the definition type, such as in the case of a partial read or a read from a pointer that
|
||||
* has been cast to a different type.
|
||||
*/
|
||||
final Language::Type getType() { getLanguageType().hasType(result, _) }
|
||||
final Language::Type getType() { this.getLanguageType().hasType(result, _) }
|
||||
|
||||
/**
|
||||
* Holds if the value consumed by this operand is a glvalue. If this
|
||||
@@ -182,13 +184,13 @@ class Operand extends TStageOperand {
|
||||
* not hold, the value of the operand represents a value whose type is
|
||||
* given by `getType()`.
|
||||
*/
|
||||
final predicate isGLValue() { getLanguageType().hasType(_, true) }
|
||||
final predicate isGLValue() { this.getLanguageType().hasType(_, true) }
|
||||
|
||||
/**
|
||||
* Gets the size of the value consumed by this operand, in bytes. If the operand does not have
|
||||
* a known constant size, this predicate does not hold.
|
||||
*/
|
||||
final int getSize() { result = getLanguageType().getByteSize() }
|
||||
final int getSize() { result = this.getLanguageType().getByteSize() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -205,7 +207,7 @@ class MemoryOperand extends Operand {
|
||||
/**
|
||||
* Gets the kind of memory access performed by the operand.
|
||||
*/
|
||||
MemoryAccessKind getMemoryAccess() { result = getUse().getOpcode().getReadMemoryAccess() }
|
||||
MemoryAccessKind getMemoryAccess() { result = this.getUse().getOpcode().getReadMemoryAccess() }
|
||||
|
||||
/**
|
||||
* Holds if the memory access performed by this operand will not always read from every bit in the
|
||||
@@ -215,7 +217,7 @@ class MemoryOperand extends Operand {
|
||||
* conservative estimate of the memory that might actually be accessed at runtime (for example,
|
||||
* the global side effects of a function call).
|
||||
*/
|
||||
predicate hasMayReadMemoryAccess() { getUse().getOpcode().hasMayReadMemoryAccess() }
|
||||
predicate hasMayReadMemoryAccess() { this.getUse().getOpcode().hasMayReadMemoryAccess() }
|
||||
|
||||
/**
|
||||
* Returns the operand that holds the memory address from which the current operand loads its
|
||||
@@ -223,8 +225,8 @@ class MemoryOperand extends Operand {
|
||||
* is `r1`.
|
||||
*/
|
||||
final AddressOperand getAddressOperand() {
|
||||
getMemoryAccess().usesAddressOperand() and
|
||||
result.getUse() = getUse()
|
||||
this.getMemoryAccess().usesAddressOperand() and
|
||||
result.getUse() = this.getUse()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -294,7 +296,7 @@ class NonPhiMemoryOperand extends NonPhiOperand, MemoryOperand, TNonPhiMemoryOpe
|
||||
result = unique(Instruction defInstr | hasDefinition(defInstr, _))
|
||||
}
|
||||
|
||||
final override Overlap getDefinitionOverlap() { hasDefinition(_, result) }
|
||||
final override Overlap getDefinitionOverlap() { this.hasDefinition(_, result) }
|
||||
|
||||
pragma[noinline]
|
||||
private predicate hasDefinition(Instruction defInstr, Overlap overlap) {
|
||||
@@ -449,13 +451,17 @@ class PhiInputOperand extends MemoryOperand, TPhiOperand {
|
||||
|
||||
final override Overlap getDefinitionOverlap() { result = overlap }
|
||||
|
||||
final override int getDumpSortOrder() { result = 11 + getPredecessorBlock().getDisplayIndex() }
|
||||
|
||||
final override string getDumpLabel() {
|
||||
result = "from " + getPredecessorBlock().getDisplayIndex().toString() + ":"
|
||||
final override int getDumpSortOrder() {
|
||||
result = 11 + this.getPredecessorBlock().getDisplayIndex()
|
||||
}
|
||||
|
||||
final override string getDumpId() { result = getPredecessorBlock().getDisplayIndex().toString() }
|
||||
final override string getDumpLabel() {
|
||||
result = "from " + this.getPredecessorBlock().getDisplayIndex().toString() + ":"
|
||||
}
|
||||
|
||||
final override string getDumpId() {
|
||||
result = this.getPredecessorBlock().getDisplayIndex().toString()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the predecessor block from which this value comes.
|
||||
|
||||
@@ -24,7 +24,7 @@ class IRBlockBase extends TIRBlock {
|
||||
final string toString() { result = getFirstInstruction(this).toString() }
|
||||
|
||||
/** Gets the source location of the first non-`Phi` instruction in this block. */
|
||||
final Language::Location getLocation() { result = getFirstInstruction().getLocation() }
|
||||
final Language::Location getLocation() { result = this.getFirstInstruction().getLocation() }
|
||||
|
||||
/**
|
||||
* INTERNAL: Do not use.
|
||||
@@ -39,7 +39,7 @@ class IRBlockBase extends TIRBlock {
|
||||
) and
|
||||
this =
|
||||
rank[result + 1](IRBlock funcBlock, int sortOverride, int sortKey1, int sortKey2 |
|
||||
funcBlock.getEnclosingFunction() = getEnclosingFunction() and
|
||||
funcBlock.getEnclosingFunction() = this.getEnclosingFunction() and
|
||||
funcBlock.getFirstInstruction().hasSortKeys(sortKey1, sortKey2) and
|
||||
// Ensure that the block containing `EnterFunction` always comes first.
|
||||
if funcBlock.getFirstInstruction() instanceof EnterFunctionInstruction
|
||||
@@ -59,15 +59,15 @@ class IRBlockBase extends TIRBlock {
|
||||
* Get the `Phi` instructions that appear at the start of this block.
|
||||
*/
|
||||
final PhiInstruction getAPhiInstruction() {
|
||||
Construction::getPhiInstructionBlockStart(result) = getFirstInstruction()
|
||||
Construction::getPhiInstructionBlockStart(result) = this.getFirstInstruction()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an instruction in this block. This includes `Phi` instructions.
|
||||
*/
|
||||
final Instruction getAnInstruction() {
|
||||
result = getInstruction(_) or
|
||||
result = getAPhiInstruction()
|
||||
result = this.getInstruction(_) or
|
||||
result = this.getAPhiInstruction()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -78,7 +78,9 @@ class IRBlockBase extends TIRBlock {
|
||||
/**
|
||||
* Gets the last instruction in this block.
|
||||
*/
|
||||
final Instruction getLastInstruction() { result = getInstruction(getInstructionCount() - 1) }
|
||||
final Instruction getLastInstruction() {
|
||||
result = this.getInstruction(this.getInstructionCount() - 1)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the number of non-`Phi` instructions in this block.
|
||||
@@ -149,7 +151,7 @@ class IRBlock extends IRBlockBase {
|
||||
* Block `A` dominates block `B` if any control flow path from the entry block of the function to
|
||||
* block `B` must pass through block `A`. A block always dominates itself.
|
||||
*/
|
||||
final predicate dominates(IRBlock block) { strictlyDominates(block) or this = block }
|
||||
final predicate dominates(IRBlock block) { this.strictlyDominates(block) or this = block }
|
||||
|
||||
/**
|
||||
* Gets a block on the dominance frontier of this block.
|
||||
@@ -159,8 +161,8 @@ class IRBlock extends IRBlockBase {
|
||||
*/
|
||||
pragma[noinline]
|
||||
final IRBlock dominanceFrontier() {
|
||||
dominates(result.getAPredecessor()) and
|
||||
not strictlyDominates(result)
|
||||
this.dominates(result.getAPredecessor()) and
|
||||
not this.strictlyDominates(result)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -189,7 +191,7 @@ class IRBlock extends IRBlockBase {
|
||||
* Block `A` post-dominates block `B` if any control flow path from `B` to the exit block of the
|
||||
* function must pass through block `A`. A block always post-dominates itself.
|
||||
*/
|
||||
final predicate postDominates(IRBlock block) { strictlyPostDominates(block) or this = block }
|
||||
final predicate postDominates(IRBlock block) { this.strictlyPostDominates(block) or this = block }
|
||||
|
||||
/**
|
||||
* Gets a block on the post-dominance frontier of this block.
|
||||
@@ -199,16 +201,16 @@ class IRBlock extends IRBlockBase {
|
||||
*/
|
||||
pragma[noinline]
|
||||
final IRBlock postPominanceFrontier() {
|
||||
postDominates(result.getASuccessor()) and
|
||||
not strictlyPostDominates(result)
|
||||
this.postDominates(result.getASuccessor()) and
|
||||
not this.strictlyPostDominates(result)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this block is reachable from the entry block of its function.
|
||||
*/
|
||||
final predicate isReachableFromFunctionEntry() {
|
||||
this = getEnclosingIRFunction().getEntryBlock() or
|
||||
getAPredecessor().isReachableFromFunctionEntry()
|
||||
this = this.getEnclosingIRFunction().getEntryBlock() or
|
||||
this.getAPredecessor().isReachableFromFunctionEntry()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -46,12 +46,12 @@ class Operand extends TStageOperand {
|
||||
/**
|
||||
* Gets the location of the source code for this operand.
|
||||
*/
|
||||
final Language::Location getLocation() { result = getUse().getLocation() }
|
||||
final Language::Location getLocation() { result = this.getUse().getLocation() }
|
||||
|
||||
/**
|
||||
* Gets the function that contains this operand.
|
||||
*/
|
||||
final IRFunction getEnclosingIRFunction() { result = getUse().getEnclosingIRFunction() }
|
||||
final IRFunction getEnclosingIRFunction() { result = this.getUse().getEnclosingIRFunction() }
|
||||
|
||||
/**
|
||||
* Gets the `Instruction` that consumes this operand.
|
||||
@@ -74,7 +74,7 @@ class Operand extends TStageOperand {
|
||||
*/
|
||||
final Instruction getDef() {
|
||||
result = this.getAnyDef() and
|
||||
getDefinitionOverlap() instanceof MustExactlyOverlap
|
||||
this.getDefinitionOverlap() instanceof MustExactlyOverlap
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -82,7 +82,7 @@ class Operand extends TStageOperand {
|
||||
*
|
||||
* Gets the `Instruction` that consumes this operand.
|
||||
*/
|
||||
deprecated final Instruction getUseInstruction() { result = getUse() }
|
||||
deprecated final Instruction getUseInstruction() { result = this.getUse() }
|
||||
|
||||
/**
|
||||
* DEPRECATED: use `getAnyDef` or `getDef`. The exact replacement for this
|
||||
@@ -91,7 +91,7 @@ class Operand extends TStageOperand {
|
||||
*
|
||||
* Gets the `Instruction` whose result is the value of the operand.
|
||||
*/
|
||||
deprecated final Instruction getDefinitionInstruction() { result = getAnyDef() }
|
||||
deprecated final Instruction getDefinitionInstruction() { result = this.getAnyDef() }
|
||||
|
||||
/**
|
||||
* Gets the overlap relationship between the operand's definition and its use.
|
||||
@@ -101,7 +101,9 @@ class Operand extends TStageOperand {
|
||||
/**
|
||||
* Holds if the result of the definition instruction does not exactly overlap this use.
|
||||
*/
|
||||
final predicate isDefinitionInexact() { not getDefinitionOverlap() instanceof MustExactlyOverlap }
|
||||
final predicate isDefinitionInexact() {
|
||||
not this.getDefinitionOverlap() instanceof MustExactlyOverlap
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a prefix to use when dumping the operand in an operand list.
|
||||
@@ -121,7 +123,7 @@ class Operand extends TStageOperand {
|
||||
* For example: `this:r3_5`
|
||||
*/
|
||||
final string getDumpString() {
|
||||
result = getDumpLabel() + getInexactSpecifier() + getDefinitionId()
|
||||
result = this.getDumpLabel() + this.getInexactSpecifier() + this.getDefinitionId()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -129,9 +131,9 @@ class Operand extends TStageOperand {
|
||||
* definition is not modeled in SSA.
|
||||
*/
|
||||
private string getDefinitionId() {
|
||||
result = getAnyDef().getResultId()
|
||||
result = this.getAnyDef().getResultId()
|
||||
or
|
||||
not exists(getAnyDef()) and result = "m?"
|
||||
not exists(this.getAnyDef()) and result = "m?"
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -140,7 +142,7 @@ class Operand extends TStageOperand {
|
||||
* the empty string.
|
||||
*/
|
||||
private string getInexactSpecifier() {
|
||||
if isDefinitionInexact() then result = "~" else result = ""
|
||||
if this.isDefinitionInexact() then result = "~" else result = ""
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -155,7 +157,7 @@ class Operand extends TStageOperand {
|
||||
* the definition type, such as in the case of a partial read or a read from a pointer that
|
||||
* has been cast to a different type.
|
||||
*/
|
||||
Language::LanguageType getLanguageType() { result = getAnyDef().getResultLanguageType() }
|
||||
Language::LanguageType getLanguageType() { result = this.getAnyDef().getResultLanguageType() }
|
||||
|
||||
/**
|
||||
* Gets the language-neutral type of the value consumed by this operand. This is usually the same
|
||||
@@ -164,7 +166,7 @@ class Operand extends TStageOperand {
|
||||
* from the definition type, such as in the case of a partial read or a read from a pointer that
|
||||
* has been cast to a different type.
|
||||
*/
|
||||
final IRType getIRType() { result = getLanguageType().getIRType() }
|
||||
final IRType getIRType() { result = this.getLanguageType().getIRType() }
|
||||
|
||||
/**
|
||||
* Gets the type of the value consumed by this operand. This is usually the same as the
|
||||
@@ -173,7 +175,7 @@ class Operand extends TStageOperand {
|
||||
* the definition type, such as in the case of a partial read or a read from a pointer that
|
||||
* has been cast to a different type.
|
||||
*/
|
||||
final Language::Type getType() { getLanguageType().hasType(result, _) }
|
||||
final Language::Type getType() { this.getLanguageType().hasType(result, _) }
|
||||
|
||||
/**
|
||||
* Holds if the value consumed by this operand is a glvalue. If this
|
||||
@@ -182,13 +184,13 @@ class Operand extends TStageOperand {
|
||||
* not hold, the value of the operand represents a value whose type is
|
||||
* given by `getType()`.
|
||||
*/
|
||||
final predicate isGLValue() { getLanguageType().hasType(_, true) }
|
||||
final predicate isGLValue() { this.getLanguageType().hasType(_, true) }
|
||||
|
||||
/**
|
||||
* Gets the size of the value consumed by this operand, in bytes. If the operand does not have
|
||||
* a known constant size, this predicate does not hold.
|
||||
*/
|
||||
final int getSize() { result = getLanguageType().getByteSize() }
|
||||
final int getSize() { result = this.getLanguageType().getByteSize() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -205,7 +207,7 @@ class MemoryOperand extends Operand {
|
||||
/**
|
||||
* Gets the kind of memory access performed by the operand.
|
||||
*/
|
||||
MemoryAccessKind getMemoryAccess() { result = getUse().getOpcode().getReadMemoryAccess() }
|
||||
MemoryAccessKind getMemoryAccess() { result = this.getUse().getOpcode().getReadMemoryAccess() }
|
||||
|
||||
/**
|
||||
* Holds if the memory access performed by this operand will not always read from every bit in the
|
||||
@@ -215,7 +217,7 @@ class MemoryOperand extends Operand {
|
||||
* conservative estimate of the memory that might actually be accessed at runtime (for example,
|
||||
* the global side effects of a function call).
|
||||
*/
|
||||
predicate hasMayReadMemoryAccess() { getUse().getOpcode().hasMayReadMemoryAccess() }
|
||||
predicate hasMayReadMemoryAccess() { this.getUse().getOpcode().hasMayReadMemoryAccess() }
|
||||
|
||||
/**
|
||||
* Returns the operand that holds the memory address from which the current operand loads its
|
||||
@@ -223,8 +225,8 @@ class MemoryOperand extends Operand {
|
||||
* is `r1`.
|
||||
*/
|
||||
final AddressOperand getAddressOperand() {
|
||||
getMemoryAccess().usesAddressOperand() and
|
||||
result.getUse() = getUse()
|
||||
this.getMemoryAccess().usesAddressOperand() and
|
||||
result.getUse() = this.getUse()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -294,7 +296,7 @@ class NonPhiMemoryOperand extends NonPhiOperand, MemoryOperand, TNonPhiMemoryOpe
|
||||
result = unique(Instruction defInstr | hasDefinition(defInstr, _))
|
||||
}
|
||||
|
||||
final override Overlap getDefinitionOverlap() { hasDefinition(_, result) }
|
||||
final override Overlap getDefinitionOverlap() { this.hasDefinition(_, result) }
|
||||
|
||||
pragma[noinline]
|
||||
private predicate hasDefinition(Instruction defInstr, Overlap overlap) {
|
||||
@@ -449,13 +451,17 @@ class PhiInputOperand extends MemoryOperand, TPhiOperand {
|
||||
|
||||
final override Overlap getDefinitionOverlap() { result = overlap }
|
||||
|
||||
final override int getDumpSortOrder() { result = 11 + getPredecessorBlock().getDisplayIndex() }
|
||||
|
||||
final override string getDumpLabel() {
|
||||
result = "from " + getPredecessorBlock().getDisplayIndex().toString() + ":"
|
||||
final override int getDumpSortOrder() {
|
||||
result = 11 + this.getPredecessorBlock().getDisplayIndex()
|
||||
}
|
||||
|
||||
final override string getDumpId() { result = getPredecessorBlock().getDisplayIndex().toString() }
|
||||
final override string getDumpLabel() {
|
||||
result = "from " + this.getPredecessorBlock().getDisplayIndex().toString() + ":"
|
||||
}
|
||||
|
||||
final override string getDumpId() {
|
||||
result = this.getPredecessorBlock().getDisplayIndex().toString()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the predecessor block from which this value comes.
|
||||
|
||||
@@ -24,7 +24,7 @@ class IRBlockBase extends TIRBlock {
|
||||
final string toString() { result = getFirstInstruction(this).toString() }
|
||||
|
||||
/** Gets the source location of the first non-`Phi` instruction in this block. */
|
||||
final Language::Location getLocation() { result = getFirstInstruction().getLocation() }
|
||||
final Language::Location getLocation() { result = this.getFirstInstruction().getLocation() }
|
||||
|
||||
/**
|
||||
* INTERNAL: Do not use.
|
||||
@@ -39,7 +39,7 @@ class IRBlockBase extends TIRBlock {
|
||||
) and
|
||||
this =
|
||||
rank[result + 1](IRBlock funcBlock, int sortOverride, int sortKey1, int sortKey2 |
|
||||
funcBlock.getEnclosingFunction() = getEnclosingFunction() and
|
||||
funcBlock.getEnclosingFunction() = this.getEnclosingFunction() and
|
||||
funcBlock.getFirstInstruction().hasSortKeys(sortKey1, sortKey2) and
|
||||
// Ensure that the block containing `EnterFunction` always comes first.
|
||||
if funcBlock.getFirstInstruction() instanceof EnterFunctionInstruction
|
||||
@@ -59,15 +59,15 @@ class IRBlockBase extends TIRBlock {
|
||||
* Get the `Phi` instructions that appear at the start of this block.
|
||||
*/
|
||||
final PhiInstruction getAPhiInstruction() {
|
||||
Construction::getPhiInstructionBlockStart(result) = getFirstInstruction()
|
||||
Construction::getPhiInstructionBlockStart(result) = this.getFirstInstruction()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an instruction in this block. This includes `Phi` instructions.
|
||||
*/
|
||||
final Instruction getAnInstruction() {
|
||||
result = getInstruction(_) or
|
||||
result = getAPhiInstruction()
|
||||
result = this.getInstruction(_) or
|
||||
result = this.getAPhiInstruction()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -78,7 +78,9 @@ class IRBlockBase extends TIRBlock {
|
||||
/**
|
||||
* Gets the last instruction in this block.
|
||||
*/
|
||||
final Instruction getLastInstruction() { result = getInstruction(getInstructionCount() - 1) }
|
||||
final Instruction getLastInstruction() {
|
||||
result = this.getInstruction(this.getInstructionCount() - 1)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the number of non-`Phi` instructions in this block.
|
||||
@@ -149,7 +151,7 @@ class IRBlock extends IRBlockBase {
|
||||
* Block `A` dominates block `B` if any control flow path from the entry block of the function to
|
||||
* block `B` must pass through block `A`. A block always dominates itself.
|
||||
*/
|
||||
final predicate dominates(IRBlock block) { strictlyDominates(block) or this = block }
|
||||
final predicate dominates(IRBlock block) { this.strictlyDominates(block) or this = block }
|
||||
|
||||
/**
|
||||
* Gets a block on the dominance frontier of this block.
|
||||
@@ -159,8 +161,8 @@ class IRBlock extends IRBlockBase {
|
||||
*/
|
||||
pragma[noinline]
|
||||
final IRBlock dominanceFrontier() {
|
||||
dominates(result.getAPredecessor()) and
|
||||
not strictlyDominates(result)
|
||||
this.dominates(result.getAPredecessor()) and
|
||||
not this.strictlyDominates(result)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -189,7 +191,7 @@ class IRBlock extends IRBlockBase {
|
||||
* Block `A` post-dominates block `B` if any control flow path from `B` to the exit block of the
|
||||
* function must pass through block `A`. A block always post-dominates itself.
|
||||
*/
|
||||
final predicate postDominates(IRBlock block) { strictlyPostDominates(block) or this = block }
|
||||
final predicate postDominates(IRBlock block) { this.strictlyPostDominates(block) or this = block }
|
||||
|
||||
/**
|
||||
* Gets a block on the post-dominance frontier of this block.
|
||||
@@ -199,16 +201,16 @@ class IRBlock extends IRBlockBase {
|
||||
*/
|
||||
pragma[noinline]
|
||||
final IRBlock postPominanceFrontier() {
|
||||
postDominates(result.getASuccessor()) and
|
||||
not strictlyPostDominates(result)
|
||||
this.postDominates(result.getASuccessor()) and
|
||||
not this.strictlyPostDominates(result)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this block is reachable from the entry block of its function.
|
||||
*/
|
||||
final predicate isReachableFromFunctionEntry() {
|
||||
this = getEnclosingIRFunction().getEntryBlock() or
|
||||
getAPredecessor().isReachableFromFunctionEntry()
|
||||
this = this.getEnclosingIRFunction().getEntryBlock() or
|
||||
this.getAPredecessor().isReachableFromFunctionEntry()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -46,12 +46,12 @@ class Operand extends TStageOperand {
|
||||
/**
|
||||
* Gets the location of the source code for this operand.
|
||||
*/
|
||||
final Language::Location getLocation() { result = getUse().getLocation() }
|
||||
final Language::Location getLocation() { result = this.getUse().getLocation() }
|
||||
|
||||
/**
|
||||
* Gets the function that contains this operand.
|
||||
*/
|
||||
final IRFunction getEnclosingIRFunction() { result = getUse().getEnclosingIRFunction() }
|
||||
final IRFunction getEnclosingIRFunction() { result = this.getUse().getEnclosingIRFunction() }
|
||||
|
||||
/**
|
||||
* Gets the `Instruction` that consumes this operand.
|
||||
@@ -74,7 +74,7 @@ class Operand extends TStageOperand {
|
||||
*/
|
||||
final Instruction getDef() {
|
||||
result = this.getAnyDef() and
|
||||
getDefinitionOverlap() instanceof MustExactlyOverlap
|
||||
this.getDefinitionOverlap() instanceof MustExactlyOverlap
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -82,7 +82,7 @@ class Operand extends TStageOperand {
|
||||
*
|
||||
* Gets the `Instruction` that consumes this operand.
|
||||
*/
|
||||
deprecated final Instruction getUseInstruction() { result = getUse() }
|
||||
deprecated final Instruction getUseInstruction() { result = this.getUse() }
|
||||
|
||||
/**
|
||||
* DEPRECATED: use `getAnyDef` or `getDef`. The exact replacement for this
|
||||
@@ -91,7 +91,7 @@ class Operand extends TStageOperand {
|
||||
*
|
||||
* Gets the `Instruction` whose result is the value of the operand.
|
||||
*/
|
||||
deprecated final Instruction getDefinitionInstruction() { result = getAnyDef() }
|
||||
deprecated final Instruction getDefinitionInstruction() { result = this.getAnyDef() }
|
||||
|
||||
/**
|
||||
* Gets the overlap relationship between the operand's definition and its use.
|
||||
@@ -101,7 +101,9 @@ class Operand extends TStageOperand {
|
||||
/**
|
||||
* Holds if the result of the definition instruction does not exactly overlap this use.
|
||||
*/
|
||||
final predicate isDefinitionInexact() { not getDefinitionOverlap() instanceof MustExactlyOverlap }
|
||||
final predicate isDefinitionInexact() {
|
||||
not this.getDefinitionOverlap() instanceof MustExactlyOverlap
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a prefix to use when dumping the operand in an operand list.
|
||||
@@ -121,7 +123,7 @@ class Operand extends TStageOperand {
|
||||
* For example: `this:r3_5`
|
||||
*/
|
||||
final string getDumpString() {
|
||||
result = getDumpLabel() + getInexactSpecifier() + getDefinitionId()
|
||||
result = this.getDumpLabel() + this.getInexactSpecifier() + this.getDefinitionId()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -129,9 +131,9 @@ class Operand extends TStageOperand {
|
||||
* definition is not modeled in SSA.
|
||||
*/
|
||||
private string getDefinitionId() {
|
||||
result = getAnyDef().getResultId()
|
||||
result = this.getAnyDef().getResultId()
|
||||
or
|
||||
not exists(getAnyDef()) and result = "m?"
|
||||
not exists(this.getAnyDef()) and result = "m?"
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -140,7 +142,7 @@ class Operand extends TStageOperand {
|
||||
* the empty string.
|
||||
*/
|
||||
private string getInexactSpecifier() {
|
||||
if isDefinitionInexact() then result = "~" else result = ""
|
||||
if this.isDefinitionInexact() then result = "~" else result = ""
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -155,7 +157,7 @@ class Operand extends TStageOperand {
|
||||
* the definition type, such as in the case of a partial read or a read from a pointer that
|
||||
* has been cast to a different type.
|
||||
*/
|
||||
Language::LanguageType getLanguageType() { result = getAnyDef().getResultLanguageType() }
|
||||
Language::LanguageType getLanguageType() { result = this.getAnyDef().getResultLanguageType() }
|
||||
|
||||
/**
|
||||
* Gets the language-neutral type of the value consumed by this operand. This is usually the same
|
||||
@@ -164,7 +166,7 @@ class Operand extends TStageOperand {
|
||||
* from the definition type, such as in the case of a partial read or a read from a pointer that
|
||||
* has been cast to a different type.
|
||||
*/
|
||||
final IRType getIRType() { result = getLanguageType().getIRType() }
|
||||
final IRType getIRType() { result = this.getLanguageType().getIRType() }
|
||||
|
||||
/**
|
||||
* Gets the type of the value consumed by this operand. This is usually the same as the
|
||||
@@ -173,7 +175,7 @@ class Operand extends TStageOperand {
|
||||
* the definition type, such as in the case of a partial read or a read from a pointer that
|
||||
* has been cast to a different type.
|
||||
*/
|
||||
final Language::Type getType() { getLanguageType().hasType(result, _) }
|
||||
final Language::Type getType() { this.getLanguageType().hasType(result, _) }
|
||||
|
||||
/**
|
||||
* Holds if the value consumed by this operand is a glvalue. If this
|
||||
@@ -182,13 +184,13 @@ class Operand extends TStageOperand {
|
||||
* not hold, the value of the operand represents a value whose type is
|
||||
* given by `getType()`.
|
||||
*/
|
||||
final predicate isGLValue() { getLanguageType().hasType(_, true) }
|
||||
final predicate isGLValue() { this.getLanguageType().hasType(_, true) }
|
||||
|
||||
/**
|
||||
* Gets the size of the value consumed by this operand, in bytes. If the operand does not have
|
||||
* a known constant size, this predicate does not hold.
|
||||
*/
|
||||
final int getSize() { result = getLanguageType().getByteSize() }
|
||||
final int getSize() { result = this.getLanguageType().getByteSize() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -205,7 +207,7 @@ class MemoryOperand extends Operand {
|
||||
/**
|
||||
* Gets the kind of memory access performed by the operand.
|
||||
*/
|
||||
MemoryAccessKind getMemoryAccess() { result = getUse().getOpcode().getReadMemoryAccess() }
|
||||
MemoryAccessKind getMemoryAccess() { result = this.getUse().getOpcode().getReadMemoryAccess() }
|
||||
|
||||
/**
|
||||
* Holds if the memory access performed by this operand will not always read from every bit in the
|
||||
@@ -215,7 +217,7 @@ class MemoryOperand extends Operand {
|
||||
* conservative estimate of the memory that might actually be accessed at runtime (for example,
|
||||
* the global side effects of a function call).
|
||||
*/
|
||||
predicate hasMayReadMemoryAccess() { getUse().getOpcode().hasMayReadMemoryAccess() }
|
||||
predicate hasMayReadMemoryAccess() { this.getUse().getOpcode().hasMayReadMemoryAccess() }
|
||||
|
||||
/**
|
||||
* Returns the operand that holds the memory address from which the current operand loads its
|
||||
@@ -223,8 +225,8 @@ class MemoryOperand extends Operand {
|
||||
* is `r1`.
|
||||
*/
|
||||
final AddressOperand getAddressOperand() {
|
||||
getMemoryAccess().usesAddressOperand() and
|
||||
result.getUse() = getUse()
|
||||
this.getMemoryAccess().usesAddressOperand() and
|
||||
result.getUse() = this.getUse()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -294,7 +296,7 @@ class NonPhiMemoryOperand extends NonPhiOperand, MemoryOperand, TNonPhiMemoryOpe
|
||||
result = unique(Instruction defInstr | hasDefinition(defInstr, _))
|
||||
}
|
||||
|
||||
final override Overlap getDefinitionOverlap() { hasDefinition(_, result) }
|
||||
final override Overlap getDefinitionOverlap() { this.hasDefinition(_, result) }
|
||||
|
||||
pragma[noinline]
|
||||
private predicate hasDefinition(Instruction defInstr, Overlap overlap) {
|
||||
@@ -449,13 +451,17 @@ class PhiInputOperand extends MemoryOperand, TPhiOperand {
|
||||
|
||||
final override Overlap getDefinitionOverlap() { result = overlap }
|
||||
|
||||
final override int getDumpSortOrder() { result = 11 + getPredecessorBlock().getDisplayIndex() }
|
||||
|
||||
final override string getDumpLabel() {
|
||||
result = "from " + getPredecessorBlock().getDisplayIndex().toString() + ":"
|
||||
final override int getDumpSortOrder() {
|
||||
result = 11 + this.getPredecessorBlock().getDisplayIndex()
|
||||
}
|
||||
|
||||
final override string getDumpId() { result = getPredecessorBlock().getDisplayIndex().toString() }
|
||||
final override string getDumpLabel() {
|
||||
result = "from " + this.getPredecessorBlock().getDisplayIndex().toString() + ":"
|
||||
}
|
||||
|
||||
final override string getDumpId() {
|
||||
result = this.getPredecessorBlock().getDisplayIndex().toString()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the predecessor block from which this value comes.
|
||||
|
||||
@@ -18,10 +18,11 @@ Overlap getOverlap(IntValue defStart, IntValue defEnd, IntValue useStart, IntVal
|
||||
else
|
||||
if isLE(defStart, useStart) and isGE(defEnd, useEnd)
|
||||
then result instanceof MustTotallyOverlap
|
||||
else
|
||||
if isLE(defEnd, useStart) or isGE(defStart, useEnd)
|
||||
then none()
|
||||
else result instanceof MayPartiallyOverlap
|
||||
else (
|
||||
not isLE(defEnd, useStart) and
|
||||
not isGE(defStart, useEnd) and
|
||||
result instanceof MayPartiallyOverlap
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -56,7 +56,7 @@ private class MallocAllocationFunction extends AllocationFunction {
|
||||
]) and
|
||||
sizeArg = 1
|
||||
or
|
||||
hasGlobalName(["HeapAlloc"]) and // HeapAlloc(heap, flags, size)
|
||||
hasGlobalName("HeapAlloc") and // HeapAlloc(heap, flags, size)
|
||||
sizeArg = 2
|
||||
or
|
||||
hasGlobalName([
|
||||
|
||||
@@ -365,7 +365,7 @@ class GetsBW extends BufferWriteCall {
|
||||
/**
|
||||
* Gets the index of the parameter that is the maximum number of characters to be read.
|
||||
*/
|
||||
int getParamSize() { if exists(getArgument(1)) then result = 1 else none() }
|
||||
int getParamSize() { exists(getArgument(1)) and result = 1 }
|
||||
|
||||
override Type getBufferType() { result = this.getTarget().getParameter(0).getUnspecifiedType() }
|
||||
|
||||
|
||||
1207
cpp/ql/lib/tutorial.qll
Normal file
1207
cpp/ql/lib/tutorial.qll
Normal file
File diff suppressed because it is too large
Load Diff
@@ -60,9 +60,7 @@ class SuppressionComment extends Comment {
|
||||
/**
|
||||
* The scope of an alert suppression comment.
|
||||
*/
|
||||
class SuppressionScope extends ElementBase {
|
||||
SuppressionScope() { this instanceof SuppressionComment }
|
||||
|
||||
class SuppressionScope extends ElementBase instanceof SuppressionComment {
|
||||
/**
|
||||
* Holds if this element is at the specified location.
|
||||
* The location spans column `startcolumn` of line `startline` to
|
||||
@@ -73,7 +71,7 @@ class SuppressionScope extends ElementBase {
|
||||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) {
|
||||
this.(SuppressionComment).covers(filepath, startline, startcolumn, endline, endcolumn)
|
||||
super.covers(filepath, startline, startcolumn, endline, endcolumn)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
/**
|
||||
* @name Extraction errors
|
||||
* @description List all extraction errors for files in the source code directory.
|
||||
* @kind diagnostic
|
||||
* @id cpp/diagnostics/extraction-errors
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import ExtractionErrors
|
||||
|
||||
from ExtractionError error
|
||||
where
|
||||
error instanceof ExtractionUnknownError or
|
||||
exists(error.getFile().getRelativePath())
|
||||
select error, "Extraction failed in " + error.getFile() + " with error " + error.getErrorMessage(),
|
||||
error.getSeverity()
|
||||
@@ -1,12 +1,12 @@
|
||||
/**
|
||||
* Provides a common hierarchy of all types of errors that can occur during extraction.
|
||||
* Provides a common hierarchy of all types of problems that can occur during extraction.
|
||||
*/
|
||||
|
||||
import cpp
|
||||
|
||||
/*
|
||||
* A note about how the C/C++ extractor emits diagnostics:
|
||||
* When the extractor frontend encounters an error, it emits a diagnostic message,
|
||||
* When the extractor frontend encounters a problem, it emits a diagnostic message,
|
||||
* that includes a message, location and severity.
|
||||
* However, that process is best-effort and may fail (e.g. due to lack of memory).
|
||||
* Thus, if the extractor emitted at least one diagnostic of severity discretionary
|
||||
@@ -15,17 +15,17 @@ import cpp
|
||||
* In the common case, this means that a compilation during which one or more errors happened also gets
|
||||
* the catch-all diagnostic.
|
||||
* This diagnostic has the empty string as file path.
|
||||
* We filter out these useless diagnostics if there is at least one error-level diagnostic
|
||||
* We filter out these useless diagnostics if there is at least one warning-level diagnostic
|
||||
* for the affected compilation in the database.
|
||||
* Otherwise, we show it to indicate that something went wrong and that we
|
||||
* don't know what exactly happened.
|
||||
*/
|
||||
|
||||
/**
|
||||
* An error that, if present, leads to a file being marked as non-successfully extracted.
|
||||
* A problem with a file that, if present, leads to a file being marked as non-successfully extracted.
|
||||
*/
|
||||
class ReportableError extends Diagnostic {
|
||||
ReportableError() {
|
||||
class ReportableWarning extends Diagnostic {
|
||||
ReportableWarning() {
|
||||
(
|
||||
this instanceof CompilerDiscretionaryError or
|
||||
this instanceof CompilerError or
|
||||
@@ -36,39 +36,35 @@ class ReportableError extends Diagnostic {
|
||||
}
|
||||
}
|
||||
|
||||
private newtype TExtractionError =
|
||||
TReportableError(ReportableError err) or
|
||||
private newtype TExtractionProblem =
|
||||
TReportableWarning(ReportableWarning err) or
|
||||
TCompilationFailed(Compilation c, File f) {
|
||||
f = c.getAFileCompiled() and not c.normalTermination()
|
||||
} or
|
||||
// Show the catch-all diagnostic (see note above) only if we haven't seen any other error-level diagnostic
|
||||
// for that compilation
|
||||
TUnknownError(CompilerError err) {
|
||||
not exists(ReportableError e | e.getCompilation() = err.getCompilation())
|
||||
TUnknownProblem(CompilerError err) {
|
||||
not exists(ReportableWarning e | e.getCompilation() = err.getCompilation())
|
||||
}
|
||||
|
||||
/**
|
||||
* Superclass for the extraction error hierarchy.
|
||||
* Superclass for the extraction problem hierarchy.
|
||||
*/
|
||||
class ExtractionError extends TExtractionError {
|
||||
/** Gets the string representation of the error. */
|
||||
class ExtractionProblem extends TExtractionProblem {
|
||||
/** Gets the string representation of the problem. */
|
||||
string toString() { none() }
|
||||
|
||||
/** Gets the error message for this error. */
|
||||
string getErrorMessage() { none() }
|
||||
/** Gets the problem message for this problem. */
|
||||
string getProblemMessage() { none() }
|
||||
|
||||
/** Gets the file this error occured in. */
|
||||
/** Gets the file this problem occured in. */
|
||||
File getFile() { none() }
|
||||
|
||||
/** Gets the location this error occured in. */
|
||||
/** Gets the location this problem occured in. */
|
||||
Location getLocation() { none() }
|
||||
|
||||
/** Gets the SARIF severity of this error. */
|
||||
int getSeverity() {
|
||||
// Unfortunately, we can't distinguish between errors and fatal errors in SARIF,
|
||||
// so all errors have severity 2.
|
||||
result = 2
|
||||
}
|
||||
/** Gets the SARIF severity of this problem. */
|
||||
int getSeverity() { none() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -79,7 +75,7 @@ class ExtractionError extends TExtractionError {
|
||||
* - stack overflow
|
||||
* - out of memory
|
||||
*/
|
||||
class ExtractionUnrecoverableError extends ExtractionError, TCompilationFailed {
|
||||
class ExtractionUnrecoverableError extends ExtractionProblem, TCompilationFailed {
|
||||
Compilation c;
|
||||
File f;
|
||||
|
||||
@@ -89,49 +85,67 @@ class ExtractionUnrecoverableError extends ExtractionError, TCompilationFailed {
|
||||
result = "Unrecoverable extraction error while compiling " + f.toString()
|
||||
}
|
||||
|
||||
override string getErrorMessage() { result = "unrecoverable compilation failure." }
|
||||
override string getProblemMessage() { result = "unrecoverable compilation failure." }
|
||||
|
||||
override File getFile() { result = f }
|
||||
|
||||
override Location getLocation() { result = f.getLocation() }
|
||||
|
||||
override int getSeverity() {
|
||||
// These extractor errors break the analysis, so we mark them in SARIF as
|
||||
// [errors](https://docs.oasis-open.org/sarif/sarif/v2.1.0/csprd01/sarif-v2.1.0-csprd01.html#_Toc10541338).
|
||||
result = 2
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A recoverable extraction error.
|
||||
* A recoverable extraction warning.
|
||||
* These are compiler errors from the frontend.
|
||||
* Upon encountering one of these, we still continue extraction, but the
|
||||
* database will be incomplete for that file.
|
||||
*/
|
||||
class ExtractionRecoverableError extends ExtractionError, TReportableError {
|
||||
ReportableError err;
|
||||
class ExtractionRecoverableWarning extends ExtractionProblem, TReportableWarning {
|
||||
ReportableWarning err;
|
||||
|
||||
ExtractionRecoverableError() { this = TReportableError(err) }
|
||||
ExtractionRecoverableWarning() { this = TReportableWarning(err) }
|
||||
|
||||
override string toString() { result = "Recoverable extraction error: " + err }
|
||||
|
||||
override string getErrorMessage() { result = err.getFullMessage() }
|
||||
override string getProblemMessage() { result = err.getFullMessage() }
|
||||
|
||||
override File getFile() { result = err.getFile() }
|
||||
|
||||
override Location getLocation() { result = err.getLocation() }
|
||||
|
||||
override int getSeverity() {
|
||||
// Recoverable extraction problems don't tend to break the analysis, so we mark them in SARIF as
|
||||
// [warnings](https://docs.oasis-open.org/sarif/sarif/v2.1.0/csprd01/sarif-v2.1.0-csprd01.html#_Toc10541338).
|
||||
result = 1
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An unknown error happened during extraction.
|
||||
* These are only displayed if we know that we encountered an error during extraction,
|
||||
* An unknown problem happened during extraction.
|
||||
* These are only displayed if we know that we encountered an problem during extraction,
|
||||
* but, for some reason, failed to emit a proper diagnostic with location information
|
||||
* and error message.
|
||||
* and problem message.
|
||||
*/
|
||||
class ExtractionUnknownError extends ExtractionError, TUnknownError {
|
||||
class ExtractionUnknownProblem extends ExtractionProblem, TUnknownProblem {
|
||||
CompilerError err;
|
||||
|
||||
ExtractionUnknownError() { this = TUnknownError(err) }
|
||||
ExtractionUnknownProblem() { this = TUnknownProblem(err) }
|
||||
|
||||
override string toString() { result = "Unknown extraction error: " + err }
|
||||
override string toString() { result = "Unknown extraction problem: " + err }
|
||||
|
||||
override string getErrorMessage() { result = err.getFullMessage() }
|
||||
override string getProblemMessage() { result = err.getFullMessage() }
|
||||
|
||||
override File getFile() { result = err.getFile() }
|
||||
|
||||
override Location getLocation() { result = err.getLocation() }
|
||||
|
||||
override int getSeverity() {
|
||||
// Unknown extraction problems don't tend to break the analysis, so we mark them in SARIF as
|
||||
// [warnings](https://docs.oasis-open.org/sarif/sarif/v2.1.0/csprd01/sarif-v2.1.0-csprd01.html#_Toc10541338).
|
||||
result = 1
|
||||
}
|
||||
}
|
||||
18
cpp/ql/src/Diagnostics/ExtractionWarnings.ql
Normal file
18
cpp/ql/src/Diagnostics/ExtractionWarnings.ql
Normal file
@@ -0,0 +1,18 @@
|
||||
/**
|
||||
* @name Extraction warnings
|
||||
* @description List all extraction warnings for files in the source code directory.
|
||||
* @kind diagnostic
|
||||
* @id cpp/diagnostics/extraction-warnings
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import ExtractionProblems
|
||||
|
||||
from ExtractionProblem warning
|
||||
where
|
||||
warning instanceof ExtractionRecoverableWarning and exists(warning.getFile().getRelativePath())
|
||||
or
|
||||
warning instanceof ExtractionUnknownProblem
|
||||
select warning,
|
||||
"Extraction failed in " + warning.getFile() + " with warning " + warning.getProblemMessage(),
|
||||
warning.getSeverity()
|
||||
@@ -13,6 +13,9 @@ string describe(Compilation c) {
|
||||
else result = "extractor invocation " + concat(int i | | c.getArgument(i), " " order by i)
|
||||
}
|
||||
|
||||
/** Gets the SARIF severity level that indicates an error. */
|
||||
private int getErrorSeverity() { result = 2 }
|
||||
|
||||
from Compilation c
|
||||
where not c.normalTermination()
|
||||
select "Extraction aborted for " + describe(c)
|
||||
select "Extraction aborted for " + describe(c), getErrorSeverity()
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
/**
|
||||
* @name Successfully extracted files
|
||||
* @description Lists all files in the source code directory that were extracted without encountering an error in the file.
|
||||
* @description Lists all files in the source code directory that were extracted without encountering a problem in the file.
|
||||
* @kind diagnostic
|
||||
* @id cpp/diagnostics/successfully-extracted-files
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import ExtractionErrors
|
||||
import ExtractionProblems
|
||||
|
||||
from File f
|
||||
where
|
||||
not exists(ExtractionError e | e.getFile() = f) and
|
||||
not exists(ExtractionProblem e | e.getFile() = f) and
|
||||
exists(f.getRelativePath())
|
||||
select f, ""
|
||||
select f, "File successfully extracted"
|
||||
|
||||
@@ -166,6 +166,7 @@ class VarAnalyzableExpr extends AnalyzableExpr, VariableAccess {
|
||||
* Holds if `t` is not an instance of `IntegralType`,
|
||||
* or if `me` cannot be proven to not overflow
|
||||
*/
|
||||
pragma[inline]
|
||||
predicate overflows(MulExpr me, Type t) {
|
||||
t instanceof IntegralType
|
||||
implies
|
||||
|
||||
@@ -50,10 +50,7 @@ where
|
||||
// If either of the operands is constant, then don't include it.
|
||||
(
|
||||
if cmp.getLeftOperand().isConstant()
|
||||
then
|
||||
if cmp.getRightOperand().isConstant()
|
||||
then none() // Both operands are constant so don't create a message.
|
||||
else reason = rightReason
|
||||
then not cmp.getRightOperand().isConstant() and reason = rightReason
|
||||
else
|
||||
if cmp.getRightOperand().isConstant()
|
||||
then reason = leftReason
|
||||
|
||||
@@ -53,6 +53,7 @@ class ImproperNullTerminationReachability extends StackVariableReachabilityWithR
|
||||
override predicate isBarrier(ControlFlowNode node, StackVariable v) {
|
||||
exprDefinition(v, node, _) or
|
||||
mayAddNullTerminator(node, v.getAnAccess()) or
|
||||
node.(AddressOfExpr).getOperand() = v.getAnAccess() or // address taken
|
||||
isSinkActual(node, v) // only report first use
|
||||
}
|
||||
}
|
||||
|
||||
@@ -121,16 +121,14 @@ predicate exprSourceType(Expr use, Type sourceType, Location sourceLoc) {
|
||||
else
|
||||
if use instanceof CrementOperation
|
||||
then exprSourceType(use.(CrementOperation).getOperand(), sourceType, sourceLoc)
|
||||
else
|
||||
else (
|
||||
// Conversions are not in the AST, so ignore them.
|
||||
if use instanceof Conversion
|
||||
then none()
|
||||
else (
|
||||
// Source expressions
|
||||
sourceType = use.getUnspecifiedType() and
|
||||
isPointerType(sourceType) and
|
||||
sourceLoc = use.getLocation()
|
||||
)
|
||||
not use instanceof Conversion and
|
||||
// Source expressions
|
||||
sourceType = use.getUnspecifiedType() and
|
||||
isPointerType(sourceType) and
|
||||
sourceLoc = use.getLocation()
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
...
|
||||
int myFclose(FILE * fmy)
|
||||
{
|
||||
if(!fclose(fmy)) {
|
||||
fmy = NULL;
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
...
|
||||
fe = fopen("myFile.txt", "wt");
|
||||
...
|
||||
fclose(fe); // BAD
|
||||
...
|
||||
fe = fopen("myFile.txt", "wt");
|
||||
...
|
||||
myFclose(fe); // GOOD
|
||||
...
|
||||
@@ -0,0 +1,23 @@
|
||||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
<overview>
|
||||
<p>The presence of a shell function with additional check indicates the possible risks of the call. Use this check everywhere.</p>
|
||||
|
||||
</overview>
|
||||
|
||||
<example>
|
||||
<p>The following example demonstrates fallacious and fixed methods of using wrapper functions.</p>
|
||||
<sample src="FindWrapperFunctions.cpp" />
|
||||
|
||||
</example>
|
||||
<references>
|
||||
|
||||
<li>
|
||||
CERT C Coding Standard:
|
||||
<a href="https://wiki.sei.cmu.edu/confluence/display/java/JNI00-J.+Define+wrappers+around+native+methods">JNI00-J. Define wrappers around native methods</a>.
|
||||
</li>
|
||||
|
||||
</references>
|
||||
</qhelp>
|
||||
@@ -0,0 +1,141 @@
|
||||
/**
|
||||
* @name Missed opportunity to call wrapper function
|
||||
* @description If a wrapper function is defined for a given function, any call to the given function should be via the wrapper function.
|
||||
* @kind problem
|
||||
* @id cpp/call-to-function-without-wrapper
|
||||
* @problem.severity warning
|
||||
* @precision medium
|
||||
* @tags correctness
|
||||
* maintainability
|
||||
* security
|
||||
* external/cwe/cwe-1041
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import semmle.code.cpp.valuenumbering.GlobalValueNumbering
|
||||
import semmle.code.cpp.commons.Assertions
|
||||
|
||||
/**
|
||||
* A function call that is used in error situations (logging, throwing an exception, abnormal termination).
|
||||
*/
|
||||
class CallUsedToHandleErrors extends FunctionCall {
|
||||
CallUsedToHandleErrors() {
|
||||
// call that is known to not return
|
||||
not exists(this.(ControlFlowNode).getASuccessor())
|
||||
or
|
||||
// call throwing an exception
|
||||
exists(ThrowExpr tex | tex = this.(ControlFlowNode).getASuccessor())
|
||||
or
|
||||
// call logging a message, possibly an error
|
||||
exists(FormattingFunction ff | ff = this.(ControlFlowNode).getASuccessor())
|
||||
or
|
||||
// enabling recursive search
|
||||
exists(CallUsedToHandleErrors fr | getTarget() = fr.getEnclosingFunction())
|
||||
}
|
||||
}
|
||||
|
||||
/** Holds if the conditions for a call outside the wrapper function are met. */
|
||||
predicate conditionsOutsideWrapper(FunctionCall fcp) {
|
||||
fcp.getNumberOfArguments() > 0 and
|
||||
not exists(ConditionalStmt cdtmp | fcp.getEnclosingStmt().getParentStmt*() = cdtmp) and
|
||||
not exists(Loop lptmp | fcp.getEnclosingStmt().getParentStmt*() = lptmp) and
|
||||
not exists(ReturnStmt rttmp | fcp.getEnclosingStmt().getParentStmt*() = rttmp) and
|
||||
not exists(FunctionCall fctmp2 | fcp = fctmp2.getAnArgument().getAChild*()) and
|
||||
not exists(Assignment astmp | fcp = astmp.getRValue().getAChild*()) and
|
||||
not exists(Initializer intmp | fcp = intmp.getExpr().getAChild*()) and
|
||||
not exists(Assertion astmp | fcp = astmp.getAsserted().getAChild*()) and
|
||||
not exists(Operation optmp | fcp = optmp.getAChild*()) and
|
||||
not exists(ArrayExpr aetmp | fcp = aetmp.getAChild*()) and
|
||||
not exists(ExprCall ectmp | fcp = ectmp.getAnArgument().getAChild*())
|
||||
}
|
||||
|
||||
/** Holds if the conditions for calling `fcp` inside the `fnp` wrapper function are met. */
|
||||
pragma[inline]
|
||||
predicate conditionsInsideWrapper(FunctionCall fcp, Function fnp) {
|
||||
not exists(FunctionCall fctmp2 |
|
||||
fctmp2.getEnclosingFunction() = fnp and fcp = fctmp2.getAnArgument().getAChild*()
|
||||
) and
|
||||
not fcp instanceof CallUsedToHandleErrors and
|
||||
not fcp.getAnArgument().isConstant() and
|
||||
fcp.getEnclosingFunction() = fnp and
|
||||
fnp.getNumberOfParameters() > 0 and
|
||||
// the call arguments must be passed through the arguments of the wrapper function
|
||||
forall(int i | i in [0 .. fcp.getNumberOfArguments() - 1] |
|
||||
globalValueNumber(fcp.getArgument(i)) = globalValueNumber(fnp.getAParameter().getAnAccess())
|
||||
) and
|
||||
// there should be no more than one required call inside the wrapper function
|
||||
not exists(FunctionCall fctmp |
|
||||
fctmp.getTarget() = fcp.getTarget() and
|
||||
fctmp.getFile() = fcp.getFile() and
|
||||
fctmp != fcp and
|
||||
fctmp.getEnclosingFunction() = fnp
|
||||
) and
|
||||
// inside the wrapper function there should be no calls without paths to the desired function
|
||||
not exists(FunctionCall fctmp |
|
||||
fctmp.getEnclosingFunction() = fnp and
|
||||
fctmp.getFile() = fcp.getFile() and
|
||||
fctmp != fcp and
|
||||
(
|
||||
fctmp = fcp.getAPredecessor+()
|
||||
or
|
||||
not exists(FunctionCall fctmp1 |
|
||||
fctmp1 = fcp and
|
||||
(
|
||||
fctmp.getASuccessor+() = fctmp1 or
|
||||
fctmp.getAPredecessor+() = fctmp1
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if the conditions for the wrapper function are met. */
|
||||
pragma[inline]
|
||||
predicate conditionsForWrapper(FunctionCall fcp, Function fnp) {
|
||||
not exists(ExprCall ectmp | fnp = ectmp.getEnclosingFunction()) and
|
||||
not exists(Loop lp | lp.getEnclosingFunction() = fnp) and
|
||||
not exists(SwitchStmt sw | sw.getEnclosingFunction() = fnp) and
|
||||
not fnp instanceof Operator and
|
||||
// inside the wrapper function there should be checks of arguments or the result,
|
||||
// perhaps by means of passing the latter as an argument to some function
|
||||
(
|
||||
exists(IfStmt ifs |
|
||||
ifs.getEnclosingFunction() = fnp and
|
||||
(
|
||||
globalValueNumber(ifs.getCondition().getAChild*()) = globalValueNumber(fcp.getAnArgument()) and
|
||||
ifs.getASuccessor*() = fcp
|
||||
or
|
||||
ifs.getCondition().getAChild() = fcp
|
||||
)
|
||||
)
|
||||
or
|
||||
exists(FunctionCall fctmp |
|
||||
fctmp.getEnclosingFunction() = fnp and
|
||||
globalValueNumber(fctmp.getAnArgument().getAChild*()) = globalValueNumber(fcp)
|
||||
)
|
||||
) and
|
||||
// inside the wrapper function there must be a function call to handle the error
|
||||
exists(CallUsedToHandleErrors fctmp |
|
||||
fctmp.getEnclosingFunction() = fnp and
|
||||
forall(int i | i in [0 .. fnp.getNumberOfParameters() - 1] |
|
||||
fnp.getParameter(i).getAnAccess().getTarget() =
|
||||
fcp.getAnArgument().(VariableAccess).getTarget() or
|
||||
fnp.getParameter(i).getUnspecifiedType() instanceof Class or
|
||||
fnp.getParameter(i).getUnspecifiedType().(ReferenceType).getBaseType() instanceof Class or
|
||||
fnp.getParameter(i).getAnAccess().getTarget() =
|
||||
fctmp.getAnArgument().(VariableAccess).getTarget()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
from FunctionCall fc, Function fn
|
||||
where
|
||||
exists(FunctionCall fctmp |
|
||||
conditionsInsideWrapper(fctmp, fn) and
|
||||
conditionsForWrapper(fctmp, fn) and
|
||||
conditionsOutsideWrapper(fc) and
|
||||
fctmp.getTarget() = fc.getTarget() and
|
||||
fc.getEnclosingFunction() != fn and
|
||||
fc.getEnclosingFunction().getMetrics().getNumberOfCalls() > fn.getMetrics().getNumberOfCalls()
|
||||
)
|
||||
select fc, "Consider changing the call to $@", fn, fn.getName()
|
||||
@@ -230,13 +230,13 @@ predicate leakedInSameMethod(Resource r, Expr acquire) {
|
||||
)
|
||||
)
|
||||
)
|
||||
or
|
||||
exists(FunctionAccess fa, string kind |
|
||||
// the address of a function that releases `r` is taken (and likely
|
||||
// used to release `r` at some point).
|
||||
r.acquisitionWithRequiredKind(acquire, kind) and
|
||||
fa.getTarget() = r.getAReleaseExpr(kind).getEnclosingFunction()
|
||||
)
|
||||
)
|
||||
or
|
||||
exists(FunctionAccess fa, string kind |
|
||||
// the address of a function that releases `r` is taken (and likely
|
||||
// used to release `r` at some point).
|
||||
r.acquisitionWithRequiredKind(acquire, kind) and
|
||||
fa.getTarget() = r.getAReleaseExpr(kind).getEnclosingFunction()
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
* (in that the `.expected` file should always be empty).
|
||||
*
|
||||
* To add this framework to a new language:
|
||||
* - Add a file `InlineExpectationsTestPrivate.qll` that defines a `LineComment` class. This class
|
||||
* - Add a file `InlineExpectationsTestPrivate.qll` that defines a `ExpectationComment` class. This class
|
||||
* must support a `getContents` method that returns the contents of the given comment, _excluding_
|
||||
* the comment indicator itself. It should also define `toString` and `getLocation` as usual.
|
||||
*
|
||||
@@ -60,8 +60,8 @@
|
||||
*
|
||||
* Example:
|
||||
* ```cpp
|
||||
* int i = x + 5; // $const=5
|
||||
* int j = y + (7 - 3) // $const=7 const=3 const=4 // The result of the subtraction is a constant.
|
||||
* int i = x + 5; // $ const=5
|
||||
* int j = y + (7 - 3) // $ const=7 const=3 const=4 // The result of the subtraction is a constant.
|
||||
* ```
|
||||
*
|
||||
* For tests that contain known missing and spurious results, it is possible to further
|
||||
@@ -194,7 +194,7 @@ private int getEndOfColumnPosition(int start, string content) {
|
||||
}
|
||||
|
||||
private predicate getAnExpectation(
|
||||
LineComment comment, TColumn column, string expectation, string tags, string value
|
||||
ExpectationComment comment, TColumn column, string expectation, string tags, string value
|
||||
) {
|
||||
exists(string content |
|
||||
content = comment.getContents().regexpCapture(expectationCommentPattern(), 1) and
|
||||
@@ -247,14 +247,14 @@ private newtype TFailureLocatable =
|
||||
) {
|
||||
test.hasActualResult(location, element, tag, value)
|
||||
} or
|
||||
TValidExpectation(LineComment comment, string tag, string value, string knownFailure) {
|
||||
TValidExpectation(ExpectationComment comment, string tag, string value, string knownFailure) {
|
||||
exists(TColumn column, string tags |
|
||||
getAnExpectation(comment, column, _, tags, value) and
|
||||
tag = tags.splitAt(",") and
|
||||
knownFailure = getColumnString(column)
|
||||
)
|
||||
} or
|
||||
TInvalidExpectation(LineComment comment, string expectation) {
|
||||
TInvalidExpectation(ExpectationComment comment, string expectation) {
|
||||
getAnExpectation(comment, _, expectation, _, _) and
|
||||
not expectation.regexpMatch(expectationPattern())
|
||||
}
|
||||
@@ -292,7 +292,7 @@ class ActualResult extends FailureLocatable, TActualResult {
|
||||
}
|
||||
|
||||
abstract private class Expectation extends FailureLocatable {
|
||||
LineComment comment;
|
||||
ExpectationComment comment;
|
||||
|
||||
override string toString() { result = comment.toString() }
|
||||
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
import cpp
|
||||
|
||||
private newtype TLineComment = MkLineComment(CppStyleComment c)
|
||||
private newtype TExpectationComment = MkExpectationComment(CppStyleComment c)
|
||||
|
||||
/**
|
||||
* Represents a line comment in the CPP style.
|
||||
* Unlike the `CppStyleComment` class, however, the string returned by `getContents` does _not_
|
||||
* include the preceding comment marker (`//`).
|
||||
*/
|
||||
class LineComment extends TLineComment {
|
||||
class ExpectationComment extends TExpectationComment {
|
||||
CppStyleComment comment;
|
||||
|
||||
LineComment() { this = MkLineComment(comment) }
|
||||
ExpectationComment() { this = MkExpectationComment(comment) }
|
||||
|
||||
/** Returns the contents of the given comment, _without_ the preceding comment marker (`//`). */
|
||||
string getContents() { result = comment.getContents().suffix(2) }
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
| test.cpp:23:3:23:8 | call to fclose | Consider changing the call to $@ | test.cpp:9:6:9:13 | myFclose | myFclose |
|
||||
@@ -0,0 +1 @@
|
||||
experimental/Security/CWE/CWE-1041/FindWrapperFunctions.ql
|
||||
@@ -0,0 +1,27 @@
|
||||
#define NULL (0)
|
||||
typedef int FILE;
|
||||
FILE *fopen(const char *filename, const char *mode);
|
||||
int fclose(FILE *stream);
|
||||
extern FILE * fe;
|
||||
extern int printf(const char *fmt, ...);
|
||||
void exit(int status);
|
||||
|
||||
void myFclose(FILE * fmy)
|
||||
{
|
||||
int i;
|
||||
if(fmy) {
|
||||
i = fclose(fmy);
|
||||
fmy = NULL;
|
||||
printf("close end is code %d",i);
|
||||
if(i!=0) exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
fe = fopen("myFile.txt", "wt");
|
||||
fclose(fe); // BAD
|
||||
fe = fopen("myFile.txt", "wt");
|
||||
myFclose(fe); // GOOD
|
||||
return 0;
|
||||
}
|
||||
@@ -1,27 +1,29 @@
|
||||
| test.cpp:25:10:25:16 | buffer1 | Variable $@ may not be null terminated. | test.cpp:22:8:22:14 | buffer1 | buffer1 |
|
||||
| test.cpp:26:10:26:16 | buffer2 | Variable $@ may not be null terminated. | test.cpp:23:8:23:14 | buffer2 | buffer2 |
|
||||
| test.cpp:39:10:39:16 | buffer2 | Variable $@ may not be null terminated. | test.cpp:35:8:35:14 | buffer2 | buffer2 |
|
||||
| test.cpp:59:10:59:13 | ptr1 | Variable $@ may not be null terminated. | test.cpp:56:9:56:12 | ptr1 | ptr1 |
|
||||
| test.cpp:69:10:69:16 | buffer1 | Variable $@ may not be null terminated. | test.cpp:64:8:64:14 | buffer1 | buffer1 |
|
||||
| test.cpp:70:10:70:12 | ptr | Variable $@ may not be null terminated. | test.cpp:64:8:64:14 | buffer1 | buffer1 |
|
||||
| test.cpp:81:10:81:16 | buffer2 | Variable $@ may not be null terminated. | test.cpp:65:8:65:14 | buffer2 | buffer2 |
|
||||
| test.cpp:82:10:82:12 | ptr | Variable $@ may not be null terminated. | test.cpp:65:8:65:14 | buffer2 | buffer2 |
|
||||
| test.cpp:93:10:93:15 | buffer | Variable $@ may not be null terminated. | test.cpp:86:8:86:13 | buffer | buffer |
|
||||
| test.cpp:116:10:116:15 | buffer | Variable $@ may not be null terminated. | test.cpp:109:8:109:13 | buffer | buffer |
|
||||
| test.cpp:130:14:130:19 | buffer | Variable $@ may not be null terminated. | test.cpp:127:7:127:12 | buffer | buffer |
|
||||
| test.cpp:139:10:139:15 | buffer | Variable $@ may not be null terminated. | test.cpp:136:8:136:13 | buffer | buffer |
|
||||
| test.cpp:147:14:147:19 | buffer | Variable $@ may not be null terminated. | test.cpp:143:8:143:13 | buffer | buffer |
|
||||
| test.cpp:182:10:182:15 | buffer | Variable $@ may not be null terminated. | test.cpp:178:8:178:13 | buffer | buffer |
|
||||
| test.cpp:234:10:234:15 | buffer | Variable $@ may not be null terminated. | test.cpp:232:8:232:13 | buffer | buffer |
|
||||
| test.cpp:262:10:262:15 | buffer | Variable $@ may not be null terminated. | test.cpp:259:8:259:13 | buffer | buffer |
|
||||
| test.cpp:283:10:283:15 | buffer | Variable $@ may not be null terminated. | test.cpp:280:8:280:13 | buffer | buffer |
|
||||
| test.cpp:300:10:300:16 | buffer2 | Variable $@ may not be null terminated. | test.cpp:295:8:295:14 | buffer2 | buffer2 |
|
||||
| test.cpp:312:10:312:15 | buffer | Variable $@ may not be null terminated. | test.cpp:308:8:308:13 | buffer | buffer |
|
||||
| test.cpp:327:18:327:23 | buffer | Variable $@ may not be null terminated. | test.cpp:326:8:326:13 | buffer | buffer |
|
||||
| test.cpp:346:11:346:16 | buffer | Variable $@ may not be null terminated. | test.cpp:341:8:341:13 | buffer | buffer |
|
||||
| test.cpp:26:10:26:16 | buffer1 | Variable $@ may not be null terminated. | test.cpp:23:8:23:14 | buffer1 | buffer1 |
|
||||
| test.cpp:27:10:27:16 | buffer2 | Variable $@ may not be null terminated. | test.cpp:24:8:24:14 | buffer2 | buffer2 |
|
||||
| test.cpp:40:10:40:16 | buffer2 | Variable $@ may not be null terminated. | test.cpp:36:8:36:14 | buffer2 | buffer2 |
|
||||
| test.cpp:60:10:60:13 | ptr1 | Variable $@ may not be null terminated. | test.cpp:57:9:57:12 | ptr1 | ptr1 |
|
||||
| test.cpp:70:10:70:16 | buffer1 | Variable $@ may not be null terminated. | test.cpp:65:8:65:14 | buffer1 | buffer1 |
|
||||
| test.cpp:71:10:71:12 | ptr | Variable $@ may not be null terminated. | test.cpp:65:8:65:14 | buffer1 | buffer1 |
|
||||
| test.cpp:82:10:82:16 | buffer2 | Variable $@ may not be null terminated. | test.cpp:66:8:66:14 | buffer2 | buffer2 |
|
||||
| test.cpp:83:10:83:12 | ptr | Variable $@ may not be null terminated. | test.cpp:66:8:66:14 | buffer2 | buffer2 |
|
||||
| test.cpp:94:10:94:15 | buffer | Variable $@ may not be null terminated. | test.cpp:87:8:87:13 | buffer | buffer |
|
||||
| test.cpp:117:10:117:15 | buffer | Variable $@ may not be null terminated. | test.cpp:110:8:110:13 | buffer | buffer |
|
||||
| test.cpp:131:14:131:19 | buffer | Variable $@ may not be null terminated. | test.cpp:128:7:128:12 | buffer | buffer |
|
||||
| test.cpp:140:10:140:15 | buffer | Variable $@ may not be null terminated. | test.cpp:137:8:137:13 | buffer | buffer |
|
||||
| test.cpp:148:14:148:19 | buffer | Variable $@ may not be null terminated. | test.cpp:144:8:144:13 | buffer | buffer |
|
||||
| test.cpp:183:10:183:15 | buffer | Variable $@ may not be null terminated. | test.cpp:179:8:179:13 | buffer | buffer |
|
||||
| test.cpp:236:10:236:15 | buffer | Variable $@ may not be null terminated. | test.cpp:234:8:234:13 | buffer | buffer |
|
||||
| test.cpp:264:10:264:15 | buffer | Variable $@ may not be null terminated. | test.cpp:261:8:261:13 | buffer | buffer |
|
||||
| test.cpp:285:10:285:15 | buffer | Variable $@ may not be null terminated. | test.cpp:282:8:282:13 | buffer | buffer |
|
||||
| test.cpp:302:10:302:16 | buffer2 | Variable $@ may not be null terminated. | test.cpp:297:8:297:14 | buffer2 | buffer2 |
|
||||
| test.cpp:314:10:314:15 | buffer | Variable $@ may not be null terminated. | test.cpp:310:8:310:13 | buffer | buffer |
|
||||
| test.cpp:336:18:336:23 | buffer | Variable $@ may not be null terminated. | test.cpp:335:8:335:13 | buffer | buffer |
|
||||
| test.cpp:355:11:355:16 | buffer | Variable $@ may not be null terminated. | test.cpp:350:8:350:13 | buffer | buffer |
|
||||
| test.cpp:365:19:365:25 | buffer2 | Variable $@ may not be null terminated. | test.cpp:363:8:363:14 | buffer2 | buffer2 |
|
||||
| test.cpp:392:17:392:22 | buffer | Variable $@ may not be null terminated. | test.cpp:390:8:390:13 | buffer | buffer |
|
||||
| test.cpp:398:18:398:23 | buffer | Variable $@ may not be null terminated. | test.cpp:396:8:396:13 | buffer | buffer |
|
||||
| test.cpp:444:10:444:15 | buffer | Variable $@ may not be null terminated. | test.cpp:442:8:442:13 | buffer | buffer |
|
||||
| test.cpp:450:16:450:21 | buffer | Variable $@ may not be null terminated. | test.cpp:448:8:448:13 | buffer | buffer |
|
||||
| test.cpp:364:11:364:16 | buffer | Variable $@ may not be null terminated. | test.cpp:359:8:359:13 | buffer | buffer |
|
||||
| test.cpp:392:11:392:16 | buffer | Variable $@ may not be null terminated. | test.cpp:381:8:381:13 | buffer | buffer |
|
||||
| test.cpp:410:11:410:16 | buffer | Variable $@ may not be null terminated. | test.cpp:397:8:397:13 | buffer | buffer |
|
||||
| test.cpp:421:19:421:25 | buffer2 | Variable $@ may not be null terminated. | test.cpp:419:8:419:14 | buffer2 | buffer2 |
|
||||
| test.cpp:448:17:448:22 | buffer | Variable $@ may not be null terminated. | test.cpp:446:8:446:13 | buffer | buffer |
|
||||
| test.cpp:454:18:454:23 | buffer | Variable $@ may not be null terminated. | test.cpp:452:8:452:13 | buffer | buffer |
|
||||
| test.cpp:513:10:513:15 | buffer | Variable $@ may not be null terminated. | test.cpp:511:8:511:13 | buffer | buffer |
|
||||
| test.cpp:519:16:519:21 | buffer | Variable $@ may not be null terminated. | test.cpp:517:8:517:13 | buffer | buffer |
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
| test.cpp:410:10:410:15 | buffer | $@ flows to here and may not be null terminated. | test.cpp:409:18:409:23 | buffer | User-provided value |
|
||||
| test.cpp:425:10:425:15 | buffer | $@ flows to here and may not be null terminated. | test.cpp:424:9:424:14 | buffer | User-provided value |
|
||||
| test.cpp:466:10:466:15 | buffer | $@ flows to here and may not be null terminated. | test.cpp:465:18:465:23 | buffer | User-provided value |
|
||||
| test.cpp:481:10:481:15 | buffer | $@ flows to here and may not be null terminated. | test.cpp:480:9:480:14 | buffer | User-provided value |
|
||||
|
||||
@@ -6,6 +6,7 @@ size_t strlen(const char *s);
|
||||
char *strcpy(char *s1, const char *s2);
|
||||
char *strcat(char *s1, const char *s2);
|
||||
char *strdup(const char *s1);
|
||||
long int strtol(const char* nptr, char** endptr, int base);
|
||||
void *malloc(size_t size);
|
||||
void *memset(void *s, int c, size_t n);
|
||||
void *memcpy(void *s1, const void *s2, size_t n);
|
||||
@@ -225,6 +226,7 @@ void test_readlink(int fd, const char *path, size_t sz)
|
||||
void doNothing(char *data) { };
|
||||
void doNothing2(const char *data);
|
||||
void clearBuffer(char *data, size_t size);
|
||||
char *id(char *data) { return data; }
|
||||
|
||||
void test_strcat()
|
||||
{
|
||||
@@ -318,6 +320,13 @@ void test_strcat()
|
||||
clearBuffer(buffer, 1024);
|
||||
strcat(buffer, "content"); // GOOD
|
||||
}
|
||||
|
||||
{
|
||||
char buffer[1024];
|
||||
|
||||
clearBuffer(id(buffer), 1024);
|
||||
strcat(buffer, "content"); // GOOD
|
||||
}
|
||||
}
|
||||
|
||||
void test_strlen(bool cond1, bool cond2)
|
||||
@@ -354,6 +363,53 @@ void test_strlen(bool cond1, bool cond2)
|
||||
if (cond2)
|
||||
strlen(buffer); // BAD
|
||||
}
|
||||
|
||||
{
|
||||
char buffer[1024];
|
||||
|
||||
if (cond1)
|
||||
{
|
||||
buffer[0] = 0;
|
||||
} else {
|
||||
buffer[0] = 0;
|
||||
}
|
||||
|
||||
strlen(buffer); // GOOD
|
||||
}
|
||||
|
||||
{
|
||||
char buffer[1024];
|
||||
int init = 0;
|
||||
|
||||
if (cond1)
|
||||
{
|
||||
buffer[0] = 0;
|
||||
init = 1;
|
||||
}
|
||||
|
||||
if (init != 0)
|
||||
{
|
||||
strlen(buffer); // GOOD [FALSE POSITIVE]
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
char buffer[1024];
|
||||
int init = 0;
|
||||
|
||||
if (cond1)
|
||||
{
|
||||
buffer[0] = 0;
|
||||
init = 1;
|
||||
}
|
||||
|
||||
if (init == 0)
|
||||
{
|
||||
// ...
|
||||
} else {
|
||||
strlen(buffer); // GOOD [FALSE POSITIVE]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void test_strcpy()
|
||||
@@ -434,6 +490,19 @@ void test_read_fread(int read_src, FILE *s)
|
||||
}
|
||||
}
|
||||
|
||||
void test_strtol()
|
||||
{
|
||||
{
|
||||
char buffer[100];
|
||||
char *after_ptr;
|
||||
long int num;
|
||||
|
||||
strcpy(buffer, "123abc");
|
||||
num = strtol("123abc", &after_ptr, 10);
|
||||
strlen(after_ptr); // GOOD
|
||||
}
|
||||
}
|
||||
|
||||
int printf(const char *format, ...);
|
||||
|
||||
void test_printf(char *str)
|
||||
@@ -466,3 +535,4 @@ void test_printf(char *str)
|
||||
printf("%s", copied_str); // GOOD
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -5,9 +5,13 @@
|
||||
| test2.cpp:130:7:130:11 | call to fopen | The $@ being operated upon was previously $@, but the underlying file may have been changed since then. | test2.cpp:130:13:130:16 | path | filename | test2.cpp:128:21:128:27 | buf_ptr | checked |
|
||||
| test2.cpp:157:7:157:10 | call to open | The $@ being operated upon was previously $@, but the underlying file may have been changed since then. | test2.cpp:157:12:157:15 | path | filename | test2.cpp:155:6:155:9 | call to stat | checked |
|
||||
| test2.cpp:170:7:170:10 | call to open | The $@ being operated upon was previously $@, but the underlying file may have been changed since then. | test2.cpp:170:12:170:15 | path | filename | test2.cpp:168:6:168:10 | call to lstat | checked |
|
||||
| test2.cpp:245:3:245:7 | call to chmod | The $@ being operated upon was previously $@, but the underlying file may have been changed since then. | test2.cpp:245:9:245:12 | path | filename | test2.cpp:238:6:238:10 | call to fopen | checked |
|
||||
| test2.cpp:277:7:277:11 | call to fopen | The $@ being operated upon was previously $@, but the underlying file may have been changed since then. | test2.cpp:277:13:277:16 | path | filename | test2.cpp:275:6:275:11 | call to access | checked |
|
||||
| test2.cpp:303:7:303:11 | call to fopen | The $@ being operated upon was previously $@, but the underlying file may have been changed since then. | test2.cpp:303:13:303:16 | path | filename | test2.cpp:301:7:301:12 | call to access | checked |
|
||||
| test2.cpp:317:7:317:11 | call to fopen | The $@ being operated upon was previously $@, but the underlying file may have been changed since then. | test2.cpp:317:13:317:16 | path | filename | test2.cpp:313:6:313:11 | call to access | checked |
|
||||
| test2.cpp:348:3:348:7 | call to chmod | The $@ being operated upon was previously $@, but the underlying file may have been changed since then. | test2.cpp:348:9:348:12 | path | filename | test2.cpp:341:6:341:10 | call to fopen | checked |
|
||||
| test2.cpp:356:3:356:7 | call to chmod | The $@ being operated upon was previously $@, but the underlying file may have been changed since then. | test2.cpp:356:9:356:13 | path2 | filename | test2.cpp:354:7:354:12 | call to rename | checked |
|
||||
| test2.cpp:209:7:209:10 | call to open | The $@ being operated upon was previously $@, but the underlying file may have been changed since then. | test2.cpp:209:12:209:15 | path | filename | test2.cpp:207:6:207:9 | call to stat | checked |
|
||||
| test2.cpp:228:8:228:11 | call to open | The $@ being operated upon was previously $@, but the underlying file may have been changed since then. | test2.cpp:228:13:228:16 | path | filename | test2.cpp:224:6:224:9 | call to stat | checked |
|
||||
| test2.cpp:228:8:228:11 | call to open | The $@ being operated upon was previously $@, but the underlying file may have been changed since then. | test2.cpp:228:13:228:16 | path | filename | test2.cpp:226:7:226:9 | buf | checked |
|
||||
| test2.cpp:249:6:249:10 | call to fopen | The $@ being operated upon was previously $@, but the underlying file may have been changed since then. | test2.cpp:249:12:249:15 | path | filename | test2.cpp:244:6:244:9 | call to stat | checked |
|
||||
| test2.cpp:297:3:297:7 | call to chmod | The $@ being operated upon was previously $@, but the underlying file may have been changed since then. | test2.cpp:297:9:297:12 | path | filename | test2.cpp:290:6:290:10 | call to fopen | checked |
|
||||
| test2.cpp:329:7:329:11 | call to fopen | The $@ being operated upon was previously $@, but the underlying file may have been changed since then. | test2.cpp:329:13:329:16 | path | filename | test2.cpp:327:6:327:11 | call to access | checked |
|
||||
| test2.cpp:355:7:355:11 | call to fopen | The $@ being operated upon was previously $@, but the underlying file may have been changed since then. | test2.cpp:355:13:355:16 | path | filename | test2.cpp:353:7:353:12 | call to access | checked |
|
||||
| test2.cpp:369:7:369:11 | call to fopen | The $@ being operated upon was previously $@, but the underlying file may have been changed since then. | test2.cpp:369:13:369:16 | path | filename | test2.cpp:365:6:365:11 | call to access | checked |
|
||||
| test2.cpp:400:3:400:7 | call to chmod | The $@ being operated upon was previously $@, but the underlying file may have been changed since then. | test2.cpp:400:9:400:12 | path | filename | test2.cpp:393:6:393:10 | call to fopen | checked |
|
||||
| test2.cpp:408:3:408:7 | call to chmod | The $@ being operated upon was previously $@, but the underlying file may have been changed since then. | test2.cpp:408:9:408:13 | path2 | filename | test2.cpp:406:7:406:12 | call to rename | checked |
|
||||
|
||||
@@ -199,6 +199,58 @@ void test2_10(int dir, const char *path, int arg)
|
||||
// ...
|
||||
}
|
||||
|
||||
void test2_11(const char *path, int arg)
|
||||
{
|
||||
stat_data buf;
|
||||
int f;
|
||||
|
||||
if (stat(path, &buf))
|
||||
{
|
||||
f = open(path, arg); // GOOD (here stat is just a redundant check that the file exists / path is valid, confirmed by the return value of open) [FALSE POSITIVE]
|
||||
if (f == -1)
|
||||
{
|
||||
// handle error
|
||||
}
|
||||
|
||||
// ...
|
||||
}
|
||||
}
|
||||
|
||||
void test2_12(const char *path, int arg)
|
||||
{
|
||||
stat_data buf;
|
||||
int f;
|
||||
|
||||
if (stat(path, &buf))
|
||||
{
|
||||
if (buf.foo == 11) // check a property of the file
|
||||
{
|
||||
f = open(path, arg); // BAD
|
||||
if (f == -1)
|
||||
{
|
||||
// handle error
|
||||
}
|
||||
}
|
||||
|
||||
// ...
|
||||
}
|
||||
}
|
||||
|
||||
void test2_13(const char *path, int arg)
|
||||
{
|
||||
stat_data buf;
|
||||
FILE *f;
|
||||
|
||||
if (stat(path, &buf)) // check the file does *not* exist
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
f = fopen(path, "wt"); // BAD
|
||||
|
||||
// ...
|
||||
}
|
||||
|
||||
// --- open -> stat ---
|
||||
|
||||
void test3_1(const char *path, int arg)
|
||||
|
||||
@@ -492,8 +492,18 @@ namespace Semmle.Extraction.CSharp
|
||||
/// <summary>
|
||||
/// Gets a list of all `csharp.{hash}.txt` files currently written to the log directory.
|
||||
/// </summary>
|
||||
public static IEnumerable<string> GetCSharpArgsLogs() =>
|
||||
Directory.EnumerateFiles(GetCSharpLogDirectory(), "csharp.*.txt");
|
||||
public static IEnumerable<string> GetCSharpArgsLogs()
|
||||
{
|
||||
try
|
||||
{
|
||||
return Directory.EnumerateFiles(GetCSharpLogDirectory(), "csharp.*.txt");
|
||||
}
|
||||
catch (DirectoryNotFoundException)
|
||||
{
|
||||
// If the directory does not exist, there are no log files
|
||||
return Enumerable.Empty<string>();
|
||||
}
|
||||
}
|
||||
|
||||
private static string GetCSharpLogDirectory()
|
||||
{
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
name: codeql-csharp-examples
|
||||
name: codeql/csharp-examples
|
||||
version: 0.0.2
|
||||
dependencies:
|
||||
codeql/csharp-all: "*"
|
||||
|
||||
@@ -8,7 +8,7 @@ import csharp
|
||||
* A `Web.config` file.
|
||||
*/
|
||||
class WebConfigXML extends XMLFile {
|
||||
WebConfigXML() { getName().matches("%Web.config") }
|
||||
WebConfigXML() { this.getName().matches("%Web.config") }
|
||||
}
|
||||
|
||||
/** A `<configuration>` tag in an ASP.NET configuration file. */
|
||||
@@ -73,12 +73,14 @@ class FormsElement extends XMLElement {
|
||||
/**
|
||||
* Gets attribute's `requireSSL` value.
|
||||
*/
|
||||
string getRequireSSL() { result = getAttribute("requireSSL").getValue().trim().toLowerCase() }
|
||||
string getRequireSSL() {
|
||||
result = this.getAttribute("requireSSL").getValue().trim().toLowerCase()
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `requireSSL` value is true.
|
||||
*/
|
||||
predicate isRequireSSL() { getRequireSSL() = "true" }
|
||||
predicate isRequireSSL() { this.getRequireSSL() = "true" }
|
||||
}
|
||||
|
||||
/** A `<httpCookies>` tag in an ASP.NET configuration file. */
|
||||
@@ -89,26 +91,28 @@ class HttpCookiesElement extends XMLElement {
|
||||
* Gets attribute's `httpOnlyCookies` value.
|
||||
*/
|
||||
string getHttpOnlyCookies() {
|
||||
result = getAttribute("httpOnlyCookies").getValue().trim().toLowerCase()
|
||||
result = this.getAttribute("httpOnlyCookies").getValue().trim().toLowerCase()
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if there is any chance that `httpOnlyCookies` is set to `true`.
|
||||
*/
|
||||
predicate isHttpOnlyCookies() { getHttpOnlyCookies() = "true" }
|
||||
predicate isHttpOnlyCookies() { this.getHttpOnlyCookies() = "true" }
|
||||
|
||||
/**
|
||||
* Gets attribute's `requireSSL` value.
|
||||
*/
|
||||
string getRequireSSL() { result = getAttribute("requireSSL").getValue().trim().toLowerCase() }
|
||||
string getRequireSSL() {
|
||||
result = this.getAttribute("requireSSL").getValue().trim().toLowerCase()
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if there is any chance that `requireSSL` is set to `true` either globally or for Forms.
|
||||
*/
|
||||
predicate isRequireSSL() {
|
||||
getRequireSSL() = "true"
|
||||
this.getRequireSSL() = "true"
|
||||
or
|
||||
not getRequireSSL() = "false" and // not set all, i.e. default
|
||||
exists(FormsElement forms | forms.getFile() = getFile() | forms.isRequireSSL())
|
||||
not this.getRequireSSL() = "false" and // not set all, i.e. default
|
||||
exists(FormsElement forms | forms.getFile() = this.getFile() | forms.isRequireSSL())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ class VariableAccess extends Access, @cil_access { }
|
||||
|
||||
/** An instruction that reads a variable. */
|
||||
class ReadAccess extends VariableAccess, Expr, @cil_read_access {
|
||||
override Type getType() { result = getTarget().getType() }
|
||||
override Type getType() { result = this.getTarget().getType() }
|
||||
}
|
||||
|
||||
/** An instruction yielding an address. */
|
||||
@@ -49,7 +49,7 @@ class ParameterReadAccess extends ParameterAccess, ReadAccess {
|
||||
class ParameterWriteAccess extends ParameterAccess, WriteAccess {
|
||||
override int getPopCount() { result = 1 }
|
||||
|
||||
override Expr getExpr() { result = getOperand(0) }
|
||||
override Expr getExpr() { result = this.getOperand(0) }
|
||||
}
|
||||
|
||||
/** An access to the `this` parameter. */
|
||||
@@ -71,9 +71,9 @@ class LocalVariableAccess extends StackVariableAccess, @cil_local_access {
|
||||
class LocalVariableWriteAccess extends LocalVariableAccess, WriteAccess {
|
||||
override int getPopCount() { result = 1 }
|
||||
|
||||
override Expr getExpr() { result = getOperand(0) }
|
||||
override Expr getExpr() { result = this.getOperand(0) }
|
||||
|
||||
override string getExtra() { result = "L" + getTarget().getIndex() }
|
||||
override string getExtra() { result = "L" + this.getTarget().getIndex() }
|
||||
}
|
||||
|
||||
/** An instruction that reads a local variable. */
|
||||
@@ -85,7 +85,7 @@ class LocalVariableReadAccess extends LocalVariableAccess, ReadAccess {
|
||||
class FieldAccess extends VariableAccess, @cil_field_access {
|
||||
override Field getTarget() { result = VariableAccess.super.getTarget() }
|
||||
|
||||
override string getExtra() { result = getTarget().getName() }
|
||||
override string getExtra() { result = this.getTarget().getName() }
|
||||
|
||||
/** Gets the qualifier of the access, if any. */
|
||||
abstract Expr getQualifier();
|
||||
|
||||
@@ -10,7 +10,7 @@ private import CIL
|
||||
*/
|
||||
class BasicBlock extends Cached::TBasicBlockStart {
|
||||
/** Gets an immediate successor of this basic block, if any. */
|
||||
BasicBlock getASuccessor() { result.getFirstNode() = getLastNode().getASuccessor() }
|
||||
BasicBlock getASuccessor() { result.getFirstNode() = this.getLastNode().getASuccessor() }
|
||||
|
||||
/** Gets an immediate predecessor of this basic block, if any. */
|
||||
BasicBlock getAPredecessor() { result.getASuccessor() = this }
|
||||
@@ -31,7 +31,7 @@ class BasicBlock extends Cached::TBasicBlockStart {
|
||||
* The basic block on line 2 is an immediate `true` successor of the
|
||||
* basic block on line 1.
|
||||
*/
|
||||
BasicBlock getATrueSuccessor() { result.getFirstNode() = getLastNode().getTrueSuccessor() }
|
||||
BasicBlock getATrueSuccessor() { result.getFirstNode() = this.getLastNode().getTrueSuccessor() }
|
||||
|
||||
/**
|
||||
* Gets an immediate `false` successor, if any.
|
||||
@@ -49,22 +49,22 @@ class BasicBlock extends Cached::TBasicBlockStart {
|
||||
* The basic block on line 2 is an immediate `false` successor of the
|
||||
* basic block on line 1.
|
||||
*/
|
||||
BasicBlock getAFalseSuccessor() { result.getFirstNode() = getLastNode().getFalseSuccessor() }
|
||||
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(getFirstNode(), result, pos) }
|
||||
ControlFlowNode getNode(int pos) { Cached::bbIndex(this.getFirstNode(), result, pos) }
|
||||
|
||||
/** Gets a control flow node in this basic block. */
|
||||
ControlFlowNode getANode() { result = getNode(_) }
|
||||
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 = getNode(length() - 1) }
|
||||
ControlFlowNode getLastNode() { result = this.getNode(this.length() - 1) }
|
||||
|
||||
/** Gets the length of this basic block. */
|
||||
int length() { result = strictcount(getANode()) }
|
||||
int length() { result = strictcount(this.getANode()) }
|
||||
|
||||
/**
|
||||
* Holds if this basic block strictly dominates basic block `bb`.
|
||||
@@ -114,7 +114,7 @@ class BasicBlock extends Cached::TBasicBlockStart {
|
||||
*/
|
||||
predicate dominates(BasicBlock bb) {
|
||||
bb = this or
|
||||
strictlyDominates(bb)
|
||||
this.strictlyDominates(bb)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -140,14 +140,14 @@ class BasicBlock extends Cached::TBasicBlockStart {
|
||||
* does not dominate the basic block on line 6.
|
||||
*/
|
||||
predicate inDominanceFrontier(BasicBlock df) {
|
||||
dominatesPredecessor(df) and
|
||||
not strictlyDominates(df)
|
||||
this.dominatesPredecessor(df) and
|
||||
not this.strictlyDominates(df)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this basic block dominates a predecessor of `df`.
|
||||
*/
|
||||
private predicate dominatesPredecessor(BasicBlock df) { dominates(df.getAPredecessor()) }
|
||||
private predicate dominatesPredecessor(BasicBlock df) { this.dominates(df.getAPredecessor()) }
|
||||
|
||||
/**
|
||||
* Gets the basic block that immediately dominates this basic block, if any.
|
||||
@@ -226,7 +226,7 @@ class BasicBlock extends Cached::TBasicBlockStart {
|
||||
* post-dominates itself.
|
||||
*/
|
||||
predicate postDominates(BasicBlock bb) {
|
||||
strictlyPostDominates(bb) or
|
||||
this.strictlyPostDominates(bb) or
|
||||
this = bb
|
||||
}
|
||||
|
||||
@@ -239,7 +239,7 @@ class BasicBlock extends Cached::TBasicBlockStart {
|
||||
predicate inLoop() { this.getASuccessor+() = this }
|
||||
|
||||
/** Gets a textual representation of this basic block. */
|
||||
string toString() { result = getFirstNode().toString() }
|
||||
string toString() { result = this.getFirstNode().toString() }
|
||||
|
||||
/** Gets the location of this basic block. */
|
||||
Location getLocation() { result = this.getFirstNode().getLocation() }
|
||||
@@ -325,16 +325,16 @@ private predicate exitBB(BasicBlock bb) { not exists(bb.getLastNode().getASucces
|
||||
* A basic block with more than one predecessor.
|
||||
*/
|
||||
class JoinBlock extends BasicBlock {
|
||||
JoinBlock() { getFirstNode().isJoin() }
|
||||
JoinBlock() { this.getFirstNode().isJoin() }
|
||||
}
|
||||
|
||||
/** A basic block that terminates in a condition, splitting the subsequent control flow. */
|
||||
class ConditionBlock extends BasicBlock {
|
||||
ConditionBlock() {
|
||||
exists(BasicBlock succ |
|
||||
succ = getATrueSuccessor()
|
||||
succ = this.getATrueSuccessor()
|
||||
or
|
||||
succ = getAFalseSuccessor()
|
||||
succ = this.getAFalseSuccessor()
|
||||
)
|
||||
}
|
||||
|
||||
@@ -380,16 +380,16 @@ class ConditionBlock extends BasicBlock {
|
||||
*/
|
||||
|
||||
exists(BasicBlock succ |
|
||||
isCandidateSuccessor(succ, testIsTrue) and
|
||||
this.isCandidateSuccessor(succ, testIsTrue) and
|
||||
succ.dominates(controlled)
|
||||
)
|
||||
}
|
||||
|
||||
private predicate isCandidateSuccessor(BasicBlock succ, boolean testIsTrue) {
|
||||
(
|
||||
testIsTrue = true and succ = getATrueSuccessor()
|
||||
testIsTrue = true and succ = this.getATrueSuccessor()
|
||||
or
|
||||
testIsTrue = false and succ = getAFalseSuccessor()
|
||||
testIsTrue = false and succ = this.getAFalseSuccessor()
|
||||
) and
|
||||
forall(BasicBlock pred | pred = succ.getAPredecessor() and pred != this | succ.dominates(pred))
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ abstract class InstructionViolation extends CfgViolation, CfgCheck {
|
||||
override string toString() {
|
||||
result =
|
||||
instruction.getImplementation().getMethod().toStringWithTypes() + ": " +
|
||||
instruction.toString() + ", " + getInstructionsUpTo()
|
||||
instruction.toString() + ", " + this.getInstructionsUpTo()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -126,7 +126,7 @@ class MissingOperand extends InstructionViolation {
|
||||
}
|
||||
|
||||
override string getMessage() {
|
||||
result = "This instruction is missing operand " + getMissingOperand()
|
||||
result = "This instruction is missing operand " + this.getMissingOperand()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -364,7 +364,7 @@ class TypeViolation extends ConsistencyViolation, TypeCheck {
|
||||
/** Gets the type containing the violation. */
|
||||
Type getType() { this = TypeCheck(result) }
|
||||
|
||||
override string toString() { result = getType().toString() }
|
||||
override string toString() { result = this.getType().toString() }
|
||||
|
||||
abstract override string getMessage();
|
||||
}
|
||||
@@ -374,7 +374,7 @@ class TypeViolation extends ConsistencyViolation, TypeCheck {
|
||||
*/
|
||||
class TypeIsBothConstructedAndUnbound extends TypeViolation {
|
||||
TypeIsBothConstructedAndUnbound() {
|
||||
getType() instanceof ConstructedGeneric and getType() instanceof UnboundGeneric
|
||||
this.getType() instanceof ConstructedGeneric and this.getType() instanceof UnboundGeneric
|
||||
}
|
||||
|
||||
override string getMessage() { result = "Type is both constructed and unbound" }
|
||||
@@ -397,16 +397,16 @@ class InconsistentTypeLocation extends TypeViolation {
|
||||
*/
|
||||
class TypeParameterMismatch extends TypeViolation {
|
||||
TypeParameterMismatch() {
|
||||
getType().(ConstructedGeneric).getNumberOfTypeArguments() !=
|
||||
getType().getUnboundType().(UnboundGeneric).getNumberOfTypeParameters()
|
||||
this.getType().(ConstructedGeneric).getNumberOfTypeArguments() !=
|
||||
this.getType().getUnboundType().(UnboundGeneric).getNumberOfTypeParameters()
|
||||
}
|
||||
|
||||
override string getMessage() {
|
||||
result =
|
||||
"Constructed type (" + getType().toStringWithTypes() + ") has " +
|
||||
getType().(ConstructedGeneric).getNumberOfTypeArguments() +
|
||||
" type arguments and unbound type (" + getType().getUnboundType().toStringWithTypes() +
|
||||
") has " + getType().getUnboundType().(UnboundGeneric).getNumberOfTypeParameters() +
|
||||
"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"
|
||||
}
|
||||
}
|
||||
@@ -418,7 +418,7 @@ class MethodViolation extends ConsistencyViolation, DeclarationCheck {
|
||||
/** Gets the method containing the violation. */
|
||||
Method getMethod() { this = DeclarationCheck(result) }
|
||||
|
||||
override string toString() { result = getMethod().toString() }
|
||||
override string toString() { result = this.getMethod().toString() }
|
||||
|
||||
override string getMessage() { none() }
|
||||
}
|
||||
@@ -440,14 +440,15 @@ class InconsistentMethodLocation extends MethodViolation {
|
||||
*/
|
||||
class ConstructedMethodTypeParams extends MethodViolation {
|
||||
ConstructedMethodTypeParams() {
|
||||
getMethod().(ConstructedGeneric).getNumberOfTypeArguments() !=
|
||||
getMethod().getUnboundDeclaration().(UnboundGeneric).getNumberOfTypeParameters()
|
||||
this.getMethod().(ConstructedGeneric).getNumberOfTypeArguments() !=
|
||||
this.getMethod().getUnboundDeclaration().(UnboundGeneric).getNumberOfTypeParameters()
|
||||
}
|
||||
|
||||
override string getMessage() {
|
||||
result =
|
||||
"The constructed method " + getMethod().toStringWithTypes() +
|
||||
" does not match unbound method " + getMethod().getUnboundDeclaration().toStringWithTypes()
|
||||
"The constructed method " + this.getMethod().toStringWithTypes() +
|
||||
" does not match unbound method " +
|
||||
this.getMethod().getUnboundDeclaration().toStringWithTypes()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -477,8 +478,8 @@ class InvalidOverride extends MethodViolation {
|
||||
private Method base;
|
||||
|
||||
InvalidOverride() {
|
||||
base = getMethod().getOverriddenMethod() and
|
||||
not getMethod().getDeclaringType().getABaseType+() = base.getDeclaringType() and
|
||||
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.
|
||||
}
|
||||
|
||||
@@ -493,7 +494,9 @@ class InvalidOverride extends MethodViolation {
|
||||
* A pointer type that does not have a pointee type.
|
||||
*/
|
||||
class InvalidPointerType extends TypeViolation {
|
||||
InvalidPointerType() { exists(PointerType p | p = getType() | count(p.getReferentType()) != 1) }
|
||||
InvalidPointerType() {
|
||||
exists(PointerType p | p = this.getType() | count(p.getReferentType()) != 1)
|
||||
}
|
||||
|
||||
override string getMessage() { result = "Invalid Pointertype.getPointeeType()" }
|
||||
}
|
||||
@@ -502,7 +505,9 @@ class InvalidPointerType extends TypeViolation {
|
||||
* An array with an invalid `getElementType`.
|
||||
*/
|
||||
class ArrayTypeMissingElement extends TypeViolation {
|
||||
ArrayTypeMissingElement() { exists(ArrayType t | t = getType() | count(t.getElementType()) != 1) }
|
||||
ArrayTypeMissingElement() {
|
||||
exists(ArrayType t | t = this.getType() | count(t.getElementType()) != 1)
|
||||
}
|
||||
|
||||
override string getMessage() { result = "Invalid ArrayType.getElementType()" }
|
||||
}
|
||||
@@ -511,7 +516,7 @@ class ArrayTypeMissingElement extends TypeViolation {
|
||||
* An array with an invalid `getRank`.
|
||||
*/
|
||||
class ArrayTypeInvalidRank extends TypeViolation {
|
||||
ArrayTypeInvalidRank() { exists(ArrayType t | t = getType() | not t.getRank() > 0) }
|
||||
ArrayTypeInvalidRank() { exists(ArrayType t | t = this.getType() | not t.getRank() > 0) }
|
||||
|
||||
override string getMessage() { result = "Invalid ArrayType.getRank()" }
|
||||
}
|
||||
@@ -564,7 +569,7 @@ abstract class DeclarationViolation extends ConsistencyViolation, DeclarationChe
|
||||
/** Gets the member containing the potential violation. */
|
||||
Declaration getDeclaration() { this = DeclarationCheck(result) }
|
||||
|
||||
override string toString() { result = getDeclaration().toString() }
|
||||
override string toString() { result = this.getDeclaration().toString() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -572,7 +577,7 @@ abstract class DeclarationViolation extends ConsistencyViolation, DeclarationChe
|
||||
*/
|
||||
class PropertyWithNoAccessors extends DeclarationViolation {
|
||||
PropertyWithNoAccessors() {
|
||||
exists(Property p | p = getDeclaration() | not exists(p.getAnAccessor()))
|
||||
exists(Property p | p = this.getDeclaration() | not exists(p.getAnAccessor()))
|
||||
}
|
||||
|
||||
override string getMessage() { result = "Property has no accessors" }
|
||||
@@ -646,7 +651,7 @@ class TypeMultiplyDefined extends TypeViolation, DisabledCheck {
|
||||
|
||||
override string getMessage() {
|
||||
result =
|
||||
"This type (" + getType().toStringWithTypes() + ") has " +
|
||||
"This type (" + this.getType().toStringWithTypes() + ") has " +
|
||||
count(Type t |
|
||||
not t instanceof ConstructedGeneric and
|
||||
t.toStringWithTypes() = this.getType().toStringWithTypes()
|
||||
@@ -669,11 +674,11 @@ class MissingCilDeclaration extends ConsistencyViolation, MissingCSharpCheck {
|
||||
|
||||
override string getMessage() {
|
||||
result =
|
||||
"Cannot locate CIL for " + getDeclaration().toStringWithTypes() + " of class " +
|
||||
getDeclaration().getPrimaryQlClasses()
|
||||
"Cannot locate CIL for " + this.getDeclaration().toStringWithTypes() + " of class " +
|
||||
this.getDeclaration().getPrimaryQlClasses()
|
||||
}
|
||||
|
||||
override string toString() { result = getDeclaration().toStringWithTypes() }
|
||||
override string toString() { result = this.getDeclaration().toStringWithTypes() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -717,21 +722,23 @@ private predicate expectedCilDeclaration(CS::Declaration decl) {
|
||||
/** A member with an invalid name. */
|
||||
class MemberWithInvalidName extends DeclarationViolation {
|
||||
MemberWithInvalidName() {
|
||||
exists(string name | name = getDeclaration().(Member).getName() |
|
||||
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 " + getDeclaration().(Member).getName() }
|
||||
override string getMessage() {
|
||||
result = "Invalid name " + this.getDeclaration().(Member).getName()
|
||||
}
|
||||
}
|
||||
|
||||
class ConstructedSourceDeclarationMethod extends MethodViolation {
|
||||
Method method;
|
||||
|
||||
ConstructedSourceDeclarationMethod() {
|
||||
method = getMethod() and
|
||||
method = this.getMethod() and
|
||||
method = method.getUnboundDeclaration() and
|
||||
(
|
||||
method instanceof ConstructedGeneric or
|
||||
@@ -751,7 +758,7 @@ class DeclarationWithMultipleLabels extends DeclarationViolation {
|
||||
}
|
||||
|
||||
override string getMessage() {
|
||||
result = "Multiple labels " + concat(getDeclaration().getLabel(), ", ")
|
||||
result = "Multiple labels " + concat(this.getDeclaration().getLabel(), ", ")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -23,13 +23,13 @@ class ControlFlowNode extends @cil_controlflow_node {
|
||||
int getPopCount() { result = 0 }
|
||||
|
||||
/** Gets a successor of this node, if any. */
|
||||
final Instruction getASuccessor() { result = getASuccessorType(_) }
|
||||
final Instruction getASuccessor() { result = this.getASuccessorType(_) }
|
||||
|
||||
/** Gets a true successor of this node, if any. */
|
||||
final Instruction getTrueSuccessor() { result = getASuccessorType(any(TrueFlow f)) }
|
||||
final Instruction getTrueSuccessor() { result = this.getASuccessorType(any(TrueFlow f)) }
|
||||
|
||||
/** Gets a false successor of this node, if any. */
|
||||
final Instruction getFalseSuccessor() { result = getASuccessorType(any(FalseFlow f)) }
|
||||
final Instruction getFalseSuccessor() { result = this.getASuccessorType(any(FalseFlow f)) }
|
||||
|
||||
/** Gets a successor to this node, of type `type`, if any. */
|
||||
cached
|
||||
@@ -57,7 +57,7 @@ class ControlFlowNode extends @cil_controlflow_node {
|
||||
}
|
||||
|
||||
/** Gets an operand of this instruction, if any. */
|
||||
ControlFlowNode getAnOperand() { result = getOperand(_) }
|
||||
ControlFlowNode getAnOperand() { result = this.getOperand(_) }
|
||||
|
||||
/** Gets an expression that consumes the output of this instruction on the stack. */
|
||||
Instruction getParentExpr() { this = result.getAnOperand() }
|
||||
@@ -86,17 +86,17 @@ class ControlFlowNode extends @cil_controlflow_node {
|
||||
)
|
||||
}
|
||||
|
||||
private int getStackDelta() { result = getPushCount() - getPopCount() }
|
||||
private int getStackDelta() { result = this.getPushCount() - this.getPopCount() }
|
||||
|
||||
/** Gets the stack size before this instruction. */
|
||||
int getStackSizeBefore() { result = getAPredecessor().getStackSizeAfter() }
|
||||
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 .. getImplementation().getStackSize()] and
|
||||
result = getStackSizeBefore() + getStackDelta()
|
||||
result in [0 .. this.getImplementation().getStackSize()] and
|
||||
result = this.getStackSizeBefore() + this.getStackDelta()
|
||||
}
|
||||
|
||||
/** Gets the method containing this control flow node. */
|
||||
|
||||
@@ -68,7 +68,7 @@ class Member extends DotNet::Member, Declaration, @cil_member {
|
||||
/** Holds if this member has a security attribute. */
|
||||
predicate hasSecurity() { cil_security(this) }
|
||||
|
||||
override Location getLocation() { result = getDeclaringType().getLocation() }
|
||||
override Location getLocation() { result = this.getDeclaringType().getLocation() }
|
||||
}
|
||||
|
||||
/** A property. */
|
||||
@@ -87,24 +87,25 @@ class Property extends DotNet::Property, Member, CustomModifierReceiver, @cil_pr
|
||||
override Setter getSetter() { this = result.getProperty() }
|
||||
|
||||
/** Gets an accessor of this property. */
|
||||
Accessor getAnAccessor() { result = getGetter() or result = getSetter() }
|
||||
Accessor getAnAccessor() { result = this.getGetter() or result = this.getSetter() }
|
||||
|
||||
override string toString() { result = "property " + getName() }
|
||||
override string toString() { result = "property " + this.getName() }
|
||||
|
||||
override string toStringWithTypes() {
|
||||
result =
|
||||
getType().toStringWithTypes() + " " + getDeclaringType().toStringWithTypes() + "." + getName()
|
||||
this.getType().toStringWithTypes() + " " + this.getDeclaringType().toStringWithTypes() + "." +
|
||||
this.getName()
|
||||
}
|
||||
}
|
||||
|
||||
/** A property that is trivial (wraps a field). */
|
||||
class TrivialProperty extends Property {
|
||||
TrivialProperty() {
|
||||
getGetter().(TrivialGetter).getField() = getSetter().(TrivialSetter).getField()
|
||||
this.getGetter().(TrivialGetter).getField() = this.getSetter().(TrivialSetter).getField()
|
||||
}
|
||||
|
||||
/** Gets the underlying field of this property. */
|
||||
Field getField() { result = getGetter().(TrivialGetter).getField() }
|
||||
Field getField() { result = this.getGetter().(TrivialGetter).getField() }
|
||||
}
|
||||
|
||||
/** An event. */
|
||||
@@ -125,9 +126,9 @@ class Event extends DotNet::Event, Member, @cil_event {
|
||||
/** Gets the raiser. */
|
||||
Method getRaiser() { cil_raiser(this, result) }
|
||||
|
||||
override string toString() { result = "event " + getName() }
|
||||
override string toString() { result = "event " + this.getName() }
|
||||
|
||||
override string toStringWithTypes() {
|
||||
result = getDeclaringType().toStringWithTypes() + "." + getName()
|
||||
result = this.getDeclaringType().toStringWithTypes() + "." + this.getName()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,5 +45,5 @@ class ConstructedType extends ConstructedGeneric, Type {
|
||||
|
||||
/** A constructed generic method. */
|
||||
class ConstructedMethod extends ConstructedGeneric, Method {
|
||||
final override UnboundGenericMethod getUnboundGeneric() { result = getUnboundMethod() }
|
||||
final override UnboundGenericMethod getUnboundGeneric() { result = this.getUnboundMethod() }
|
||||
}
|
||||
|
||||
@@ -4,15 +4,17 @@ private import CIL
|
||||
|
||||
/** An instruction. */
|
||||
class Instruction extends Element, ControlFlowNode, DataFlowNode, @cil_instruction {
|
||||
override string toString() { result = getOpcodeName() }
|
||||
override string toString() { result = this.getOpcodeName() }
|
||||
|
||||
/** Gets a more verbose textual representation of this instruction. */
|
||||
string toStringExtra() { result = getIndex() + ": " + getOpcodeName() + getExtraStr() }
|
||||
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 = getImplementation().getMethod() }
|
||||
override Method getMethod() { result = this.getImplementation().getMethod() }
|
||||
|
||||
/**
|
||||
* Gets the index of this instruction.
|
||||
@@ -30,7 +32,7 @@ class Instruction extends Element, ControlFlowNode, DataFlowNode, @cil_instructi
|
||||
string getExtra() { none() }
|
||||
|
||||
private string getExtraStr() {
|
||||
if exists(getExtra()) then result = " " + getExtra() else result = ""
|
||||
if exists(this.getExtra()) then result = " " + this.getExtra() else result = ""
|
||||
}
|
||||
|
||||
/** Gets the declaration accessed by this instruction, if any. */
|
||||
@@ -39,8 +41,8 @@ class Instruction extends Element, ControlFlowNode, DataFlowNode, @cil_instructi
|
||||
/** Gets a successor instruction to this instruction. */
|
||||
override Instruction getASuccessorType(FlowType t) {
|
||||
t instanceof NormalFlow and
|
||||
canFlowNext() and
|
||||
result = this.getImplementation().getInstruction(getIndex() + 1)
|
||||
this.canFlowNext() and
|
||||
result = this.getImplementation().getInstruction(this.getIndex() + 1)
|
||||
}
|
||||
|
||||
/** Holds if this instruction passes control flow into the next instruction. */
|
||||
@@ -61,7 +63,7 @@ class Instruction extends Element, ControlFlowNode, DataFlowNode, @cil_instructi
|
||||
override Location getALocation() {
|
||||
cil_instruction_location(this, result) // The source code, if available
|
||||
or
|
||||
result = getImplementation().getLocation() // The containing assembly
|
||||
result = this.getImplementation().getLocation() // The containing assembly
|
||||
}
|
||||
|
||||
override Location getLocation() { result = Element.super.getLocation() }
|
||||
|
||||
@@ -14,7 +14,7 @@ class Expr extends DotNet::Expr, Instruction, @cil_expr {
|
||||
|
||||
override Type getType() { result = Instruction.super.getType() }
|
||||
|
||||
override Method getEnclosingCallable() { result = getImplementation().getMethod() }
|
||||
override Method getEnclosingCallable() { result = this.getImplementation().getMethod() }
|
||||
|
||||
/**
|
||||
* The "parent" of a CIL expression is taken to be the instruction
|
||||
@@ -28,13 +28,13 @@ class Branch extends Instruction, @cil_jump {
|
||||
/** Gets the instruction that is jumped to. */
|
||||
Instruction getTarget() { cil_jump(this, result) }
|
||||
|
||||
override string getExtra() { result = getTarget().getIndex() + ":" }
|
||||
override string getExtra() { result = this.getTarget().getIndex() + ":" }
|
||||
}
|
||||
|
||||
/** An instruction that unconditionally jumps to another instruction. */
|
||||
class UnconditionalBranch extends Branch, @cil_unconditional_jump {
|
||||
override Instruction getASuccessorType(FlowType t) {
|
||||
t instanceof NormalFlow and result = getTarget()
|
||||
t instanceof NormalFlow and result = this.getTarget()
|
||||
}
|
||||
|
||||
override predicate canFlowNext() { none() }
|
||||
@@ -43,9 +43,9 @@ class UnconditionalBranch extends Branch, @cil_unconditional_jump {
|
||||
/** An instruction that jumps to a target based on a condition. */
|
||||
class ConditionalBranch extends Branch, @cil_conditional_jump {
|
||||
override Instruction getASuccessorType(FlowType t) {
|
||||
t instanceof TrueFlow and result = getTarget()
|
||||
t instanceof TrueFlow and result = this.getTarget()
|
||||
or
|
||||
t instanceof FalseFlow and result = getImplementation().getInstruction(getIndex() + 1)
|
||||
t instanceof FalseFlow and result = this.getImplementation().getInstruction(this.getIndex() + 1)
|
||||
}
|
||||
|
||||
override int getPushCount() { result = 0 }
|
||||
@@ -61,7 +61,7 @@ class UnaryExpr extends Expr, @cil_unary_expr {
|
||||
override int getPopCount() { result = 1 }
|
||||
|
||||
/** Gets the operand of this unary expression. */
|
||||
Expr getOperand() { result = getOperand(0) }
|
||||
Expr getOperand() { result = this.getOperand(0) }
|
||||
}
|
||||
|
||||
/** A binary expression that compares two values. */
|
||||
@@ -73,8 +73,8 @@ class ComparisonOperation extends BinaryExpr, @cil_comparison_operation {
|
||||
class BinaryArithmeticExpr extends BinaryExpr, @cil_binary_arithmetic_operation {
|
||||
override Type getType() {
|
||||
exists(Type t0, Type t1 |
|
||||
t0 = getOperand(0).getType().getUnderlyingType() and
|
||||
t1 = getOperand(1).getType().getUnderlyingType()
|
||||
t0 = this.getOperand(0).getType().getUnderlyingType() and
|
||||
t1 = this.getOperand(1).getType().getUnderlyingType()
|
||||
|
|
||||
t0 = t1 and result = t0
|
||||
or
|
||||
@@ -100,7 +100,7 @@ class UnaryBitwiseOperation extends UnaryExpr, @cil_unary_bitwise_operation {
|
||||
/** A unary expression that converts a value from one primitive type to another. */
|
||||
class Conversion extends UnaryExpr, @cil_conversion_operation {
|
||||
/** Gets the expression being converted. */
|
||||
Expr getExpr() { result = getOperand(0) }
|
||||
Expr getExpr() { result = this.getOperand(0) }
|
||||
}
|
||||
|
||||
/** A branch that leaves the scope of a `Handler`. */
|
||||
@@ -111,7 +111,7 @@ class Literal extends DotNet::Literal, Expr, @cil_literal {
|
||||
/** Gets the pushed value. */
|
||||
override string getValue() { cil_value(this, result) }
|
||||
|
||||
override string getExtra() { result = getValue() }
|
||||
override string getExtra() { result = this.getValue() }
|
||||
}
|
||||
|
||||
/** An integer literal. */
|
||||
@@ -149,44 +149,44 @@ 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 = getTarget().getAnOverrider*() }
|
||||
override Method getARuntimeTarget() { result = this.getTarget().getAnOverrider*() }
|
||||
|
||||
override string getExtra() { result = getTarget().getQualifiedName() }
|
||||
override string getExtra() { result = this.getTarget().getQualifiedName() }
|
||||
|
||||
/**
|
||||
* 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 = getTarget().getReturnType() }
|
||||
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 = getTarget().getCallPopCount() }
|
||||
override int getPopCount() { result = this.getTarget().getCallPopCount() }
|
||||
|
||||
override int getPushCount() { result = getTarget().getCallPushCount() }
|
||||
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() {
|
||||
getImplementation().getInstruction(getIndex() - 1) instanceof Opcodes::Tail
|
||||
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 = getOperand(getPopCount() - i - 1) }
|
||||
override Expr getRawArgument(int i) { result = this.getOperand(this.getPopCount() - i - 1) }
|
||||
|
||||
/** Gets the qualifier of this call, if any. */
|
||||
Expr getQualifier() { result = getRawArgument(0) and not getTarget().isStatic() }
|
||||
Expr getQualifier() { result = this.getRawArgument(0) and not this.getTarget().isStatic() }
|
||||
|
||||
override Expr getArgument(int i) {
|
||||
if getTarget().isStatic()
|
||||
then result = getRawArgument(i)
|
||||
if this.getTarget().isStatic()
|
||||
then result = this.getRawArgument(i)
|
||||
else (
|
||||
result = getRawArgument(i + 1) and i >= 0
|
||||
result = this.getRawArgument(i + 1) and i >= 0
|
||||
)
|
||||
}
|
||||
|
||||
@@ -217,10 +217,10 @@ class VirtualCall extends Call {
|
||||
/** A read of an array element. */
|
||||
class ReadArrayElement extends BinaryExpr, @cil_read_array {
|
||||
/** Gets the array being read. */
|
||||
Expr getArray() { result = getOperand(1) }
|
||||
Expr getArray() { result = this.getOperand(1) }
|
||||
|
||||
/** Gets the index into the array. */
|
||||
Expr getArrayIndex() { result = getOperand(0) }
|
||||
Expr getArrayIndex() { result = this.getOperand(0) }
|
||||
}
|
||||
|
||||
/** A write of an array element. */
|
||||
@@ -233,14 +233,14 @@ class WriteArrayElement extends Instruction, @cil_write_array {
|
||||
/** A `return` statement. */
|
||||
class Return extends Instruction, @cil_ret {
|
||||
/** Gets the expression being returned, if any. */
|
||||
Expr getExpr() { result = getOperand(0) }
|
||||
Expr getExpr() { result = this.getOperand(0) }
|
||||
|
||||
override predicate canFlowNext() { none() }
|
||||
}
|
||||
|
||||
/** A `throw` statement. */
|
||||
class Throw extends Instruction, DotNet::Throw, @cil_throw_any {
|
||||
override Expr getExpr() { result = getOperand(0) }
|
||||
override Expr getExpr() { result = this.getOperand(0) }
|
||||
|
||||
override predicate canFlowNext() { none() }
|
||||
}
|
||||
@@ -250,10 +250,10 @@ class StoreIndirect extends Instruction, @cil_stind {
|
||||
override int getPopCount() { result = 2 }
|
||||
|
||||
/** Gets the location to store the value at. */
|
||||
Expr getAddress() { result = getOperand(1) }
|
||||
Expr getAddress() { result = this.getOperand(1) }
|
||||
|
||||
/** Gets the value to store. */
|
||||
Expr getExpr() { result = getOperand(0) }
|
||||
Expr getExpr() { result = this.getOperand(0) }
|
||||
}
|
||||
|
||||
/** Loads a value from an address/location. */
|
||||
|
||||
@@ -83,21 +83,21 @@ module Opcodes {
|
||||
class Ldc_i4 extends IntLiteral, @cil_ldc_i4 {
|
||||
override string getOpcodeName() { result = "ldc.i4" }
|
||||
|
||||
override string getExtra() { result = getValue() }
|
||||
override string getExtra() { result = this.getValue() }
|
||||
}
|
||||
|
||||
/** An `ldc.i8` instruction. */
|
||||
class Ldc_i8 extends IntLiteral, @cil_ldc_i8 {
|
||||
override string getOpcodeName() { result = "ldc.i8" }
|
||||
|
||||
override string getExtra() { result = getValue() }
|
||||
override string getExtra() { result = this.getValue() }
|
||||
}
|
||||
|
||||
/** An `ldc.i4.s` instruction. */
|
||||
class Ldc_i4_s extends IntLiteral, @cil_ldc_i4_s {
|
||||
override string getOpcodeName() { result = "ldc.i4.s" }
|
||||
|
||||
override string getExtra() { result = getValue() }
|
||||
override string getExtra() { result = this.getValue() }
|
||||
}
|
||||
|
||||
/** An `ldnull` instruction. */
|
||||
@@ -115,7 +115,7 @@ module Opcodes {
|
||||
class Ldc_r4 extends FloatLiteral, @cil_ldc_r4 {
|
||||
override string getOpcodeName() { result = "ldc.r4" }
|
||||
|
||||
override string getExtra() { result = getValue() }
|
||||
override string getExtra() { result = this.getValue() }
|
||||
|
||||
override Type getType() { result instanceof FloatType }
|
||||
}
|
||||
@@ -124,7 +124,7 @@ module Opcodes {
|
||||
class Ldc_r8 extends FloatLiteral, @cil_ldc_r8 {
|
||||
override string getOpcodeName() { result = "ldc.r8" }
|
||||
|
||||
override string getExtra() { result = getValue() }
|
||||
override string getExtra() { result = this.getValue() }
|
||||
|
||||
override Type getType() { result instanceof DoubleType }
|
||||
}
|
||||
@@ -199,9 +199,9 @@ module Opcodes {
|
||||
override string getOpcodeName() { result = "neg" }
|
||||
|
||||
override NumericType getType() {
|
||||
result = getOperand().getType()
|
||||
result = this.getOperand().getType()
|
||||
or
|
||||
getOperand().getType() instanceof Enum and result instanceof IntType
|
||||
this.getOperand().getType() instanceof Enum and result instanceof IntType
|
||||
}
|
||||
}
|
||||
|
||||
@@ -260,7 +260,7 @@ module Opcodes {
|
||||
|
||||
override int getPushCount() { result = 2 } // This is the only instruction that pushes 2 items
|
||||
|
||||
override Type getType() { result = getOperand(0).getType() }
|
||||
override Type getType() { result = this.getOperand(0).getType() }
|
||||
}
|
||||
|
||||
/** A `ret` instruction. */
|
||||
@@ -270,7 +270,7 @@ module Opcodes {
|
||||
override predicate canFlowNext() { none() }
|
||||
|
||||
override int getPopCount() {
|
||||
if getImplementation().getMethod().returnsVoid() then result = 0 else result = 1
|
||||
if this.getImplementation().getMethod().returnsVoid() then result = 0 else result = 1
|
||||
}
|
||||
}
|
||||
|
||||
@@ -283,7 +283,7 @@ module Opcodes {
|
||||
class Ldstr extends StringLiteral, @cil_ldstr {
|
||||
override string getOpcodeName() { result = "ldstr" }
|
||||
|
||||
override string getExtra() { result = "\"" + getValue() + "\"" }
|
||||
override string getExtra() { result = "\"" + this.getValue() + "\"" }
|
||||
|
||||
override Type getType() { result instanceof StringType }
|
||||
}
|
||||
@@ -427,11 +427,14 @@ module Opcodes {
|
||||
|
||||
override Instruction getASuccessorType(FlowType t) {
|
||||
t instanceof NormalFlow and
|
||||
(result = getTarget(_) or result = getImplementation().getInstruction(getIndex() + 1))
|
||||
(
|
||||
result = this.getTarget(_) or
|
||||
result = this.getImplementation().getInstruction(this.getIndex() + 1)
|
||||
)
|
||||
}
|
||||
|
||||
override string getExtra() {
|
||||
result = concat(int n | exists(getTarget(n)) | getTarget(n).getIndex() + ":", " ")
|
||||
result = concat(int n | exists(this.getTarget(n)) | this.getTarget(n).getIndex() + ":", " ")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -493,9 +496,9 @@ module Opcodes {
|
||||
|
||||
// The number of items popped/pushed from the stack depends on the target of
|
||||
// the call. Also, we need to pop the function pointer itself too.
|
||||
override int getPopCount() { result = getTargetType().getCallPopCount() + 1 }
|
||||
override int getPopCount() { result = this.getTargetType().getCallPopCount() + 1 }
|
||||
|
||||
override int getPushCount() { result = getTargetType().getCallPushCount() }
|
||||
override int getPushCount() { result = this.getTargetType().getCallPushCount() }
|
||||
}
|
||||
|
||||
/** A `callvirt` instruction. */
|
||||
@@ -524,49 +527,49 @@ module Opcodes {
|
||||
override BoolType getType() { exists(result) }
|
||||
|
||||
/** Gets the type that is being tested against. */
|
||||
Type getTestedType() { result = getAccess() }
|
||||
Type getTestedType() { result = this.getAccess() }
|
||||
|
||||
override string getExtra() { result = getTestedType().getQualifiedName() }
|
||||
override string getExtra() { result = this.getTestedType().getQualifiedName() }
|
||||
}
|
||||
|
||||
/** A `castclass` instruction. */
|
||||
class Castclass extends UnaryExpr, @cil_castclass {
|
||||
override string getOpcodeName() { result = "castclass" }
|
||||
|
||||
override Type getType() { result = getAccess() }
|
||||
override Type getType() { result = this.getAccess() }
|
||||
|
||||
/** Gets the type that is being cast to. */
|
||||
Type getTestedType() { result = getAccess() }
|
||||
Type getTestedType() { result = this.getAccess() }
|
||||
|
||||
override string getExtra() { result = getTestedType().getQualifiedName() }
|
||||
override string getExtra() { result = this.getTestedType().getQualifiedName() }
|
||||
}
|
||||
|
||||
/** An `stloc.0` instruction. */
|
||||
class Stloc_0 extends LocalVariableWriteAccess, @cil_stloc_0 {
|
||||
override string getOpcodeName() { result = "stloc.0" }
|
||||
|
||||
override LocalVariable getTarget() { result = getImplementation().getLocalVariable(0) }
|
||||
override LocalVariable getTarget() { result = this.getImplementation().getLocalVariable(0) }
|
||||
}
|
||||
|
||||
/** An `stloc.1` instruction. */
|
||||
class Stloc_1 extends LocalVariableWriteAccess, @cil_stloc_1 {
|
||||
override string getOpcodeName() { result = "stloc.1" }
|
||||
|
||||
override LocalVariable getTarget() { result = getImplementation().getLocalVariable(1) }
|
||||
override LocalVariable getTarget() { result = this.getImplementation().getLocalVariable(1) }
|
||||
}
|
||||
|
||||
/** An `stloc.2` instruction. */
|
||||
class Stloc_2 extends LocalVariableWriteAccess, @cil_stloc_2 {
|
||||
override string getOpcodeName() { result = "stloc.2" }
|
||||
|
||||
override LocalVariable getTarget() { result = getImplementation().getLocalVariable(2) }
|
||||
override LocalVariable getTarget() { result = this.getImplementation().getLocalVariable(2) }
|
||||
}
|
||||
|
||||
/** An `stloc.3` instruction. */
|
||||
class Stloc_3 extends LocalVariableWriteAccess, @cil_stloc_3 {
|
||||
override string getOpcodeName() { result = "stloc.3" }
|
||||
|
||||
override LocalVariable getTarget() { result = getImplementation().getLocalVariable(3) }
|
||||
override LocalVariable getTarget() { result = this.getImplementation().getLocalVariable(3) }
|
||||
}
|
||||
|
||||
/** An `stloc.s` instruction. */
|
||||
@@ -587,28 +590,28 @@ module Opcodes {
|
||||
class Ldloc_0 extends LocalVariableReadAccess, @cil_ldloc_0 {
|
||||
override string getOpcodeName() { result = "ldloc.0" }
|
||||
|
||||
override LocalVariable getTarget() { result = getImplementation().getLocalVariable(0) }
|
||||
override LocalVariable getTarget() { result = this.getImplementation().getLocalVariable(0) }
|
||||
}
|
||||
|
||||
/** An `ldloc.1` instruction. */
|
||||
class Ldloc_1 extends LocalVariableReadAccess, @cil_ldloc_1 {
|
||||
override string getOpcodeName() { result = "ldloc.1" }
|
||||
|
||||
override LocalVariable getTarget() { result = getImplementation().getLocalVariable(1) }
|
||||
override LocalVariable getTarget() { result = this.getImplementation().getLocalVariable(1) }
|
||||
}
|
||||
|
||||
/** An `ldloc.2` instruction. */
|
||||
class Ldloc_2 extends LocalVariableReadAccess, @cil_ldloc_2 {
|
||||
override string getOpcodeName() { result = "ldloc.2" }
|
||||
|
||||
override LocalVariable getTarget() { result = getImplementation().getLocalVariable(2) }
|
||||
override LocalVariable getTarget() { result = this.getImplementation().getLocalVariable(2) }
|
||||
}
|
||||
|
||||
/** An `ldloc.3` instruction. */
|
||||
class Ldloc_3 extends LocalVariableReadAccess, @cil_ldloc_3 {
|
||||
override string getOpcodeName() { result = "ldloc.3" }
|
||||
|
||||
override LocalVariable getTarget() { result = getImplementation().getLocalVariable(3) }
|
||||
override LocalVariable getTarget() { result = this.getImplementation().getLocalVariable(3) }
|
||||
}
|
||||
|
||||
/** An `ldloc.s` instruction. */
|
||||
@@ -617,7 +620,7 @@ module Opcodes {
|
||||
|
||||
override LocalVariable getTarget() { cil_access(this, result) }
|
||||
|
||||
override string getExtra() { result = "L" + getTarget().getIndex() }
|
||||
override string getExtra() { result = "L" + this.getTarget().getIndex() }
|
||||
}
|
||||
|
||||
/** An `ldloca.s` instruction. */
|
||||
@@ -626,7 +629,7 @@ module Opcodes {
|
||||
|
||||
override LocalVariable getTarget() { cil_access(this, result) }
|
||||
|
||||
override string getExtra() { result = "L" + getTarget().getIndex() }
|
||||
override string getExtra() { result = "L" + this.getTarget().getIndex() }
|
||||
}
|
||||
|
||||
/** An `ldloc` instruction. */
|
||||
@@ -635,7 +638,7 @@ module Opcodes {
|
||||
|
||||
override LocalVariable getTarget() { cil_access(this, result) }
|
||||
|
||||
override string getExtra() { result = "L" + getTarget().getIndex() }
|
||||
override string getExtra() { result = "L" + this.getTarget().getIndex() }
|
||||
}
|
||||
|
||||
/** An `ldarg.0` instruction. */
|
||||
@@ -643,7 +646,7 @@ module Opcodes {
|
||||
override string getOpcodeName() { result = "ldarg.0" }
|
||||
|
||||
override MethodParameter getTarget() {
|
||||
result = getImplementation().getMethod().getRawParameter(0)
|
||||
result = this.getImplementation().getMethod().getRawParameter(0)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -652,7 +655,7 @@ module Opcodes {
|
||||
override string getOpcodeName() { result = "ldarg.1" }
|
||||
|
||||
override MethodParameter getTarget() {
|
||||
result = getImplementation().getMethod().getRawParameter(1)
|
||||
result = this.getImplementation().getMethod().getRawParameter(1)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -661,7 +664,7 @@ module Opcodes {
|
||||
override string getOpcodeName() { result = "ldarg.2" }
|
||||
|
||||
override MethodParameter getTarget() {
|
||||
result = getImplementation().getMethod().getRawParameter(2)
|
||||
result = this.getImplementation().getMethod().getRawParameter(2)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -670,7 +673,7 @@ module Opcodes {
|
||||
override string getOpcodeName() { result = "ldarg.3" }
|
||||
|
||||
override MethodParameter getTarget() {
|
||||
result = getImplementation().getMethod().getRawParameter(3)
|
||||
result = this.getImplementation().getMethod().getRawParameter(3)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -710,7 +713,7 @@ module Opcodes {
|
||||
|
||||
override int getPopCount() { result = 1 }
|
||||
|
||||
override Expr getQualifier() { result = getOperand(0) }
|
||||
override Expr getQualifier() { result = this.getOperand(0) }
|
||||
}
|
||||
|
||||
/** An `ldflda` instruction. */
|
||||
@@ -719,7 +722,7 @@ module Opcodes {
|
||||
|
||||
override int getPopCount() { result = 1 }
|
||||
|
||||
override Expr getQualifier() { result = getOperand(0) }
|
||||
override Expr getQualifier() { result = this.getOperand(0) }
|
||||
}
|
||||
|
||||
/** An `ldsfld` instruction. */
|
||||
@@ -746,9 +749,9 @@ module Opcodes {
|
||||
|
||||
override int getPopCount() { result = 2 }
|
||||
|
||||
override Expr getQualifier() { result = getOperand(1) }
|
||||
override Expr getQualifier() { result = this.getOperand(1) }
|
||||
|
||||
override Expr getExpr() { result = getOperand(0) }
|
||||
override Expr getExpr() { result = this.getOperand(0) }
|
||||
}
|
||||
|
||||
/** An `stsfld` instruction. */
|
||||
@@ -759,7 +762,7 @@ module Opcodes {
|
||||
|
||||
override Expr getQualifier() { none() }
|
||||
|
||||
override Expr getExpr() { result = getOperand(0) }
|
||||
override Expr getExpr() { result = this.getOperand(0) }
|
||||
}
|
||||
|
||||
/** A `newobj` instruction. */
|
||||
@@ -772,7 +775,7 @@ module Opcodes {
|
||||
|
||||
override Type getType() { result = this.getTarget().getDeclaringType() }
|
||||
|
||||
override Expr getArgument(int i) { result = getRawArgument(i) }
|
||||
override Expr getArgument(int i) { result = this.getRawArgument(i) }
|
||||
|
||||
pragma[noinline]
|
||||
private Parameter getARawTargetParameter() { result = this.getTarget().getARawParameter() }
|
||||
@@ -796,21 +799,21 @@ module Opcodes {
|
||||
class Box extends UnaryExpr, @cil_box {
|
||||
override string getOpcodeName() { result = "box" }
|
||||
|
||||
override Type getType() { result = getAccess() }
|
||||
override Type getType() { result = this.getAccess() }
|
||||
}
|
||||
|
||||
/** An `unbox.any` instruction. */
|
||||
class Unbox_any extends UnaryExpr, @cil_unbox_any {
|
||||
override string getOpcodeName() { result = "unbox.any" }
|
||||
|
||||
override Type getType() { result = getAccess() }
|
||||
override Type getType() { result = this.getAccess() }
|
||||
}
|
||||
|
||||
/** An `unbox` instruction. */
|
||||
class Unbox extends UnaryExpr, @cil_unbox {
|
||||
override string getOpcodeName() { result = "unbox" }
|
||||
|
||||
override Type getType() { result = getAccess() }
|
||||
override Type getType() { result = this.getAccess() }
|
||||
}
|
||||
|
||||
/** An `ldobj` instruction. */
|
||||
@@ -820,7 +823,7 @@ module Opcodes {
|
||||
/** Gets the type of the object. */
|
||||
Type getTarget() { cil_access(this, result) }
|
||||
|
||||
override Type getType() { result = getAccess() }
|
||||
override Type getType() { result = this.getAccess() }
|
||||
}
|
||||
|
||||
/** An `ldtoken` instruction. */
|
||||
@@ -867,31 +870,31 @@ module Opcodes {
|
||||
// Note that this is technically wrong - it should be
|
||||
// result.(ArrayType).getElementType() = getAccess()
|
||||
// However the (ArrayType) may not be in the database.
|
||||
result = getAccess()
|
||||
result = this.getAccess()
|
||||
}
|
||||
|
||||
override string getExtra() { result = getType().getQualifiedName() }
|
||||
override string getExtra() { result = this.getType().getQualifiedName() }
|
||||
}
|
||||
|
||||
/** An `ldelem` instruction. */
|
||||
class Ldelem extends ReadArrayElement, @cil_ldelem {
|
||||
override string getOpcodeName() { result = "ldelem" }
|
||||
|
||||
override Type getType() { result = getAccess() }
|
||||
override Type getType() { result = this.getAccess() }
|
||||
}
|
||||
|
||||
/** An `ldelem.ref` instruction. */
|
||||
class Ldelem_ref extends ReadArrayElement, @cil_ldelem_ref {
|
||||
override string getOpcodeName() { result = "ldelem.ref" }
|
||||
|
||||
override Type getType() { result = getArray().getType() }
|
||||
override Type getType() { result = this.getArray().getType() }
|
||||
}
|
||||
|
||||
/** An `ldelema` instruction. */
|
||||
class Ldelema extends ReadArrayElement, ReadRef, @cil_ldelema {
|
||||
override string getOpcodeName() { result = "ldelema" }
|
||||
|
||||
override Type getType() { result = getAccess() }
|
||||
override Type getType() { result = this.getAccess() }
|
||||
}
|
||||
|
||||
/** An `stelem.ref` instruction. */
|
||||
@@ -1410,7 +1413,7 @@ module Opcodes {
|
||||
|
||||
override int getPopCount() { result = 1 }
|
||||
|
||||
override Type getType() { result = getAccess() }
|
||||
override Type getType() { result = this.getAccess() }
|
||||
}
|
||||
|
||||
/** A `refanytype` instruction. */
|
||||
|
||||
@@ -28,13 +28,13 @@ class MethodImplementation extends EntryPoint, @cil_method_implementation {
|
||||
LocalVariable getLocalVariable(int n) { cil_local_variable(result, this, n, _) }
|
||||
|
||||
/** Gets a local variable of this implementation, if any. */
|
||||
LocalVariable getALocalVariable() { result = getLocalVariable(_) }
|
||||
LocalVariable getALocalVariable() { result = this.getLocalVariable(_) }
|
||||
|
||||
/** Gets an instruction in this implementation, if any. */
|
||||
Instruction getAnInstruction() { result = getInstruction(_) }
|
||||
Instruction getAnInstruction() { result = this.getInstruction(_) }
|
||||
|
||||
/** Gets the total number of instructions in this implementation. */
|
||||
int getNumberOfInstructions() { result = count(getAnInstruction()) }
|
||||
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 }
|
||||
@@ -49,7 +49,7 @@ class MethodImplementation extends EntryPoint, @cil_method_implementation {
|
||||
/** Gets the maximum stack size of this implementation. */
|
||||
int getStackSize() { cil_method_stack_size(this, result) }
|
||||
|
||||
override string toString() { result = getMethod().toString() }
|
||||
override string toString() { result = this.getMethod().toString() }
|
||||
|
||||
/** Gets a string representing the disassembly of this implementation. */
|
||||
string getDisassembly() {
|
||||
@@ -75,13 +75,13 @@ class Method extends DotNet::Callable, Element, Member, TypeContainer, DataFlowN
|
||||
MethodImplementation getAnImplementation() { result.getMethod() = this }
|
||||
|
||||
/** Gets the "best" implementation of this method, if any. */
|
||||
BestImplementation getImplementation() { result = getAnImplementation() }
|
||||
BestImplementation getImplementation() { result = this.getAnImplementation() }
|
||||
|
||||
override Method getMethod() { result = this }
|
||||
|
||||
override string getName() { cil_method(this, result, _, _) }
|
||||
|
||||
override string getUndecoratedName() { result = getName() }
|
||||
override string getUndecoratedName() { result = this.getName() }
|
||||
|
||||
override string toString() { result = this.getName() }
|
||||
|
||||
@@ -92,25 +92,29 @@ class Method extends DotNet::Callable, Element, Member, TypeContainer, DataFlowN
|
||||
override Location getALocation() { cil_method_location(this.getUnboundDeclaration(), result) }
|
||||
|
||||
override MethodParameter getParameter(int n) {
|
||||
if isStatic() then result = getRawParameter(n) else (result = getRawParameter(n + 1) and n >= 0)
|
||||
if this.isStatic()
|
||||
then result = this.getRawParameter(n)
|
||||
else (
|
||||
result = this.getRawParameter(n + 1) and n >= 0
|
||||
)
|
||||
}
|
||||
|
||||
override Type getType() { result = getReturnType() }
|
||||
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() { getReturnType() instanceof VoidType }
|
||||
predicate returnsVoid() { this.getReturnType() instanceof VoidType }
|
||||
|
||||
/** Gets the number of stack items pushed in a call to this method. */
|
||||
int getCallPushCount() { if returnsVoid() then result = 0 else result = 1 }
|
||||
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(getRawParameter(_)) }
|
||||
int getCallPopCount() { result = count(this.getRawParameter(_)) }
|
||||
|
||||
/** Gets a method called by this method. */
|
||||
Method getACallee() { result = getImplementation().getAnInstruction().(Call).getTarget() }
|
||||
Method getACallee() { result = this.getImplementation().getAnInstruction().(Call).getTarget() }
|
||||
|
||||
/** Holds if this method is `virtual`. */
|
||||
predicate isVirtual() { cil_virtual(this) }
|
||||
@@ -129,43 +133,45 @@ class Method extends DotNet::Callable, Element, Member, TypeContainer, DataFlowN
|
||||
/** Gets the unbound declaration of this method, or the method itself. */
|
||||
Method getUnboundMethod() { cil_method_source_declaration(this, result) }
|
||||
|
||||
override Method getUnboundDeclaration() { result = getUnboundMethod() }
|
||||
override Method getUnboundDeclaration() { result = this.getUnboundMethod() }
|
||||
|
||||
/** Holds if this method is an instance constructor. */
|
||||
predicate isInstanceConstructor() { isSpecial() and getName() = ".ctor" }
|
||||
predicate isInstanceConstructor() { this.isSpecial() and this.getName() = ".ctor" }
|
||||
|
||||
/** Holds if this method is a static class constructor. */
|
||||
predicate isStaticConstructor() { isSpecial() and getName() = ".cctor" }
|
||||
predicate isStaticConstructor() { this.isSpecial() and this.getName() = ".cctor" }
|
||||
|
||||
/** Holds if this method is a constructor (static or instance). */
|
||||
predicate isConstructor() { isStaticConstructor() or isInstanceConstructor() }
|
||||
predicate isConstructor() { this.isStaticConstructor() or this.isInstanceConstructor() }
|
||||
|
||||
/** Holds if this method is a destructor/finalizer. */
|
||||
predicate isFinalizer() { getOverriddenMethod*().getQualifiedName() = "System.Object.Finalize" }
|
||||
predicate isFinalizer() {
|
||||
this.getOverriddenMethod*().getQualifiedName() = "System.Object.Finalize"
|
||||
}
|
||||
|
||||
/** Holds if this method is an operator. */
|
||||
predicate isOperator() { isSpecial() and getName().matches("op\\_%") }
|
||||
predicate isOperator() { this.isSpecial() and this.getName().matches("op\\_%") }
|
||||
|
||||
/** Holds if this method is a getter. */
|
||||
predicate isGetter() { isSpecial() and getName().matches("get\\_%") }
|
||||
predicate isGetter() { this.isSpecial() and this.getName().matches("get\\_%") }
|
||||
|
||||
/** Holds if this method is a setter. */
|
||||
predicate isSetter() { isSpecial() and getName().matches("set\\_%") }
|
||||
predicate isSetter() { this.isSpecial() and this.getName().matches("set\\_%") }
|
||||
|
||||
/** Holds if this method is an adder/add event accessor. */
|
||||
predicate isAdder() { isSpecial() and getName().matches("add\\_%") }
|
||||
predicate isAdder() { this.isSpecial() and this.getName().matches("add\\_%") }
|
||||
|
||||
/** Holds if this method is a remover/remove event accessor. */
|
||||
predicate isRemove() { isSpecial() and getName().matches("remove\\_%") }
|
||||
predicate isRemove() { this.isSpecial() and this.getName().matches("remove\\_%") }
|
||||
|
||||
/** Holds if this method is an implicit conversion operator. */
|
||||
predicate isImplicitConversion() { isSpecial() and getName() = "op_Implicit" }
|
||||
predicate isImplicitConversion() { this.isSpecial() and this.getName() = "op_Implicit" }
|
||||
|
||||
/** Holds if this method is an explicit conversion operator. */
|
||||
predicate isExplicitConversion() { isSpecial() and getName() = "op_Explicit" }
|
||||
predicate isExplicitConversion() { this.isSpecial() and this.getName() = "op_Explicit" }
|
||||
|
||||
/** Holds if this method is a conversion operator. */
|
||||
predicate isConversion() { isImplicitConversion() or isExplicitConversion() }
|
||||
predicate isConversion() { this.isImplicitConversion() or this.isExplicitConversion() }
|
||||
|
||||
/**
|
||||
* Gets a method that is overridden, either in a base class
|
||||
@@ -176,7 +182,7 @@ class Method extends DotNet::Callable, Element, Member, TypeContainer, DataFlowN
|
||||
/** Gets a method that overrides this method, if any. */
|
||||
final Method getAnOverrider() { result.getOverriddenMethod() = this }
|
||||
|
||||
override predicate hasBody() { exists(getImplementation()) }
|
||||
override predicate hasBody() { exists(this.getImplementation()) }
|
||||
|
||||
override predicate canReturn(DotNet::Expr expr) {
|
||||
exists(Return ret | ret.getImplementation() = this.getImplementation() and expr = ret.getExpr())
|
||||
@@ -206,7 +212,7 @@ class InstanceConstructor extends Constructor {
|
||||
/** A method that always returns the `this` parameter. */
|
||||
class ChainingMethod extends Method {
|
||||
ChainingMethod() {
|
||||
forex(Return ret | ret = getImplementation().getAnInstruction() |
|
||||
forex(Return ret | ret = this.getImplementation().getAnInstruction() |
|
||||
ret.getExpr() instanceof ThisAccess
|
||||
)
|
||||
}
|
||||
@@ -231,7 +237,7 @@ class Getter extends Accessor {
|
||||
*/
|
||||
class TrivialGetter extends Method {
|
||||
TrivialGetter() {
|
||||
exists(MethodImplementation impl | impl = getAnImplementation() |
|
||||
exists(MethodImplementation impl | impl = this.getAnImplementation() |
|
||||
impl.getInstruction(0) instanceof ThisAccess and
|
||||
impl.getInstruction(1) instanceof FieldReadAccess and
|
||||
impl.getInstruction(2) instanceof Return
|
||||
@@ -239,7 +245,9 @@ class TrivialGetter extends Method {
|
||||
}
|
||||
|
||||
/** Gets the underlying field of this getter. */
|
||||
Field getField() { getImplementation().getAnInstruction().(FieldReadAccess).getTarget() = result }
|
||||
Field getField() {
|
||||
this.getImplementation().getAnInstruction().(FieldReadAccess).getTarget() = result
|
||||
}
|
||||
}
|
||||
|
||||
/** A setter. */
|
||||
@@ -262,7 +270,7 @@ class Setter extends Accessor {
|
||||
*/
|
||||
class TrivialSetter extends Method {
|
||||
TrivialSetter() {
|
||||
exists(MethodImplementation impl | impl = getImplementation() |
|
||||
exists(MethodImplementation impl | impl = this.getImplementation() |
|
||||
impl.getInstruction(0) instanceof ThisAccess and
|
||||
impl.getInstruction(1).(ParameterReadAccess).getTarget().getIndex() = 1 and
|
||||
impl.getInstruction(2) instanceof FieldWriteAccess
|
||||
@@ -271,7 +279,7 @@ class TrivialSetter extends Method {
|
||||
|
||||
/** Gets the underlying field of this setter. */
|
||||
Field getField() {
|
||||
result = getImplementation().getAnInstruction().(FieldWriteAccess).getTarget()
|
||||
result = this.getImplementation().getAnInstruction().(FieldWriteAccess).getTarget()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -283,5 +291,5 @@ class Operator extends Method {
|
||||
Operator() { this.isOperator() }
|
||||
|
||||
/** Gets the name of the implementing method (for compatibility with C# data model). */
|
||||
string getFunctionName() { result = getName() }
|
||||
string getFunctionName() { result = this.getName() }
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ class TypeContainer extends DotNet::NamedElement, @cil_type_container {
|
||||
|
||||
/** A namespace. */
|
||||
class Namespace extends DotNet::Namespace, TypeContainer, @namespace {
|
||||
override string toString() { result = getQualifiedName() }
|
||||
override string toString() { result = this.getQualifiedName() }
|
||||
|
||||
override Namespace getParent() { result = this.getParentNamespace() }
|
||||
|
||||
@@ -39,7 +39,7 @@ class Type extends DotNet::Type, Declaration, TypeContainer, @cil_type {
|
||||
override string toString() { result = this.getName() }
|
||||
|
||||
/** Gets the containing type of this type, if any. */
|
||||
override Type getDeclaringType() { result = getParent() }
|
||||
override Type getDeclaringType() { result = this.getParent() }
|
||||
|
||||
/** Gets a member of this type, if any. */
|
||||
Member getAMember() { result.getDeclaringType() = this }
|
||||
@@ -96,13 +96,13 @@ class Type extends DotNet::Type, Declaration, TypeContainer, @cil_type {
|
||||
Type getABaseInterface() { cil_base_interface(this, result) }
|
||||
|
||||
/** Gets an immediate base type of this type, if any. */
|
||||
Type getABaseType() { result = getBaseClass() or result = getABaseInterface() }
|
||||
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 = getParent() }
|
||||
Namespace getNamespace() { result = this.getParent() }
|
||||
|
||||
/**
|
||||
* Gets an index for implicit conversions. A type can be converted to another numeric type
|
||||
|
||||
@@ -12,7 +12,7 @@ class TypeParameter extends DotNet::TypeParameter, Type, @cil_typeparameter {
|
||||
/** Gets the generic type/method declaring this type parameter. */
|
||||
TypeContainer getGeneric() { cil_type_parameter(result, _, this) }
|
||||
|
||||
override Location getLocation() { result = getParent().getLocation() }
|
||||
override Location getLocation() { result = this.getParent().getLocation() }
|
||||
|
||||
/** Holds if this type parameter has the `new` constraint. */
|
||||
predicate isDefaultConstructible() { cil_typeparam_new(this) }
|
||||
@@ -34,11 +34,11 @@ class TypeParameter extends DotNet::TypeParameter, Type, @cil_typeparameter {
|
||||
|
||||
/** A value or reference type. */
|
||||
class ValueOrRefType extends DotNet::ValueOrRefType, Type, @cil_valueorreftype {
|
||||
override ValueOrRefType getDeclaringType() { result = getParent() }
|
||||
override ValueOrRefType getDeclaringType() { result = this.getParent() }
|
||||
|
||||
override string getUndecoratedName() { cil_type(this, result, _, _, _) }
|
||||
|
||||
override Namespace getDeclaringNamespace() { result = getNamespace() }
|
||||
override Namespace getDeclaringNamespace() { result = this.getNamespace() }
|
||||
|
||||
override ValueOrRefType getABaseType() { result = Type.super.getABaseType() }
|
||||
}
|
||||
@@ -79,7 +79,7 @@ class ArrayType extends DotNet::ArrayType, Type, @cil_array_type {
|
||||
|
||||
override string toStringWithTypes() { result = DotNet::ArrayType.super.toStringWithTypes() }
|
||||
|
||||
override Location getLocation() { result = getElementType().getLocation() }
|
||||
override Location getLocation() { result = this.getElementType().getLocation() }
|
||||
|
||||
override ValueOrRefType getABaseType() { result = Type.super.getABaseType() }
|
||||
}
|
||||
@@ -92,7 +92,7 @@ class PointerType extends DotNet::PointerType, PrimitiveType, @cil_pointer_type
|
||||
|
||||
override string getName() { result = DotNet::PointerType.super.getName() }
|
||||
|
||||
override Location getLocation() { result = getReferentType().getLocation() }
|
||||
override Location getLocation() { result = this.getReferentType().getLocation() }
|
||||
|
||||
override string toString() { result = DotNet::PointerType.super.toString() }
|
||||
|
||||
@@ -312,13 +312,13 @@ class FunctionPointerType extends Type, CustomModifierReceiver, Parameterizable,
|
||||
override string toString() { result = Type.super.toString() }
|
||||
|
||||
/** Holds if the return type is `void`. */
|
||||
predicate returnsVoid() { getReturnType() instanceof VoidType }
|
||||
predicate returnsVoid() { this.getReturnType() instanceof VoidType }
|
||||
|
||||
/** Gets the number of stack items pushed in a call to this method. */
|
||||
int getCallPushCount() { if returnsVoid() then result = 0 else result = 1 }
|
||||
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(getRawParameter(_)) }
|
||||
int getCallPopCount() { result = count(this.getRawParameter(_)) }
|
||||
|
||||
override string getLabel() { result = getName() }
|
||||
override string getLabel() { result = this.getName() }
|
||||
}
|
||||
|
||||
@@ -17,10 +17,10 @@ class Variable extends DotNet::Variable, Declaration, DataFlowNode, @cil_variabl
|
||||
VariableAccess getAnAccess() { result.getTarget() = this }
|
||||
|
||||
/** Gets a read access to this variable, if any. */
|
||||
ReadAccess getARead() { result = getAnAccess() }
|
||||
ReadAccess getARead() { result = this.getAnAccess() }
|
||||
|
||||
/** Gets a write access to this variable, if any. */
|
||||
WriteAccess getAWrite() { result = getAnAccess() }
|
||||
WriteAccess getAWrite() { result = this.getAnAccess() }
|
||||
|
||||
override string toString() { result = Declaration.super.toString() }
|
||||
|
||||
@@ -40,20 +40,21 @@ class StackVariable extends Variable, @cil_stack_variable {
|
||||
class LocalVariable extends StackVariable, @cil_local_variable {
|
||||
override string toString() {
|
||||
result =
|
||||
"Local variable " + getIndex() + " of method " + getImplementation().getMethod().getName()
|
||||
"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 = getImplementation().getLocalVariable(result) }
|
||||
int getIndex() { this = this.getImplementation().getLocalVariable(result) }
|
||||
|
||||
override Type getType() { cil_local_variable(this, _, _, result) }
|
||||
|
||||
override Location getLocation() { result = getImplementation().getLocation() }
|
||||
override Location getLocation() { result = this.getImplementation().getLocation() }
|
||||
|
||||
override Method getMethod() { result = getImplementation().getMethod() }
|
||||
override Method getMethod() { result = this.getImplementation().getMethod() }
|
||||
}
|
||||
|
||||
/** A parameter of a `Method` or `FunctionPointerType`. */
|
||||
@@ -64,7 +65,7 @@ class Parameter extends DotNet::Parameter, CustomModifierReceiver, @cil_paramete
|
||||
int getIndex() { cil_parameter(this, _, result, _) }
|
||||
|
||||
override string toString() {
|
||||
result = "Parameter " + getIndex() + " of " + getDeclaringElement().getName()
|
||||
result = "Parameter " + this.getIndex() + " of " + this.getDeclaringElement().getName()
|
||||
}
|
||||
|
||||
override Type getType() { cil_parameter(this, _, _, result) }
|
||||
@@ -82,23 +83,25 @@ class Parameter extends DotNet::Parameter, CustomModifierReceiver, @cil_paramete
|
||||
predicate hasInFlag() { cil_parameter_in(this) }
|
||||
|
||||
/** Holds if this parameter has C# `out` semantics. */
|
||||
override predicate isOut() { hasOutFlag() and not hasInFlag() }
|
||||
override predicate isOut() { this.hasOutFlag() and not this.hasInFlag() }
|
||||
|
||||
/** Holds if this parameter has C# `ref` semantics. */
|
||||
override predicate isRef() { hasOutFlag() and hasInFlag() }
|
||||
override predicate isRef() { this.hasOutFlag() and this.hasInFlag() }
|
||||
|
||||
override string toStringWithTypes() { result = getPrefix() + getType().toStringWithTypes() }
|
||||
override string toStringWithTypes() {
|
||||
result = this.getPrefix() + this.getType().toStringWithTypes()
|
||||
}
|
||||
|
||||
private string getPrefix() {
|
||||
if isOut()
|
||||
if this.isOut()
|
||||
then result = "out "
|
||||
else
|
||||
if isRef()
|
||||
if this.isRef()
|
||||
then result = "ref "
|
||||
else result = ""
|
||||
}
|
||||
|
||||
override Location getLocation() { result = getDeclaringElement().getLocation() }
|
||||
override Location getLocation() { result = this.getDeclaringElement().getLocation() }
|
||||
}
|
||||
|
||||
/** A method parameter. */
|
||||
@@ -110,11 +113,11 @@ class MethodParameter extends Parameter, StackVariable {
|
||||
|
||||
/** Gets a parameter in an overridden method. */
|
||||
MethodParameter getOverriddenParameter() {
|
||||
result = getMethod().getOverriddenMethod().getRawParameter(getRawPosition())
|
||||
result = this.getMethod().getOverriddenMethod().getRawParameter(this.getRawPosition())
|
||||
}
|
||||
|
||||
override MethodParameter getUnboundDeclaration() {
|
||||
result = getMethod().getUnboundDeclaration().getRawParameter(getRawPosition())
|
||||
result = this.getMethod().getUnboundDeclaration().getRawParameter(this.getRawPosition())
|
||||
}
|
||||
|
||||
override string toString() { result = Parameter.super.toString() }
|
||||
@@ -136,10 +139,10 @@ class ThisParameter extends MethodParameter {
|
||||
|
||||
/** A field. */
|
||||
class Field extends DotNet::Field, Variable, Member, CustomModifierReceiver, @cil_field {
|
||||
override string toString() { result = getName() }
|
||||
override string toString() { result = this.getName() }
|
||||
|
||||
override string toStringWithTypes() {
|
||||
result = getDeclaringType().toStringWithTypes() + "." + getName()
|
||||
result = this.getDeclaringType().toStringWithTypes() + "." + this.getName()
|
||||
}
|
||||
|
||||
override string getName() { cil_field(this, _, result, _) }
|
||||
@@ -148,5 +151,5 @@ class Field extends DotNet::Field, Variable, Member, CustomModifierReceiver, @ci
|
||||
|
||||
override ValueOrRefType getDeclaringType() { cil_field(this, result, _, _) }
|
||||
|
||||
override Location getLocation() { result = getDeclaringType().getLocation() }
|
||||
override Location getLocation() { result = this.getDeclaringType().getLocation() }
|
||||
}
|
||||
|
||||
@@ -67,7 +67,7 @@ private module Annotations {
|
||||
|
||||
Nullability() { this = TNullability(nullability) }
|
||||
|
||||
override string toString() { result = getMemberString() + getSelfNullability() }
|
||||
override string toString() { result = this.getMemberString() + this.getSelfNullability() }
|
||||
|
||||
language[monotonicAggregates]
|
||||
private string getMemberString() {
|
||||
@@ -125,7 +125,9 @@ private module Annotations {
|
||||
}
|
||||
|
||||
/** Gets a textual representation of this type annotation. */
|
||||
string toString() { result = getTypePrefix() + getNullability() + getTypeSuffix() }
|
||||
string toString() {
|
||||
result = this.getTypePrefix() + this.getNullability() + this.getTypeSuffix()
|
||||
}
|
||||
|
||||
private int getFlags() { this = TAnnotationFlags(result, _) }
|
||||
|
||||
@@ -136,7 +138,7 @@ private module Annotations {
|
||||
|
||||
/** Gets an annotation in this set of annotations. */
|
||||
TypeAnnotation getAnAnnotation() {
|
||||
isSet(result.getBit())
|
||||
this.isSet(result.getBit())
|
||||
or
|
||||
result = this.getNullability()
|
||||
}
|
||||
@@ -298,7 +300,7 @@ class AnnotatedType extends TAnnotatedType {
|
||||
/** Gets a textual representation of this annotated type. */
|
||||
string toString() {
|
||||
result =
|
||||
annotations.getTypePrefix() + getUnderlyingType().toStringWithTypes() +
|
||||
annotations.getTypePrefix() + this.getUnderlyingType().toStringWithTypes() +
|
||||
annotations.getTypeSuffix()
|
||||
}
|
||||
|
||||
@@ -327,7 +329,7 @@ class AnnotatedType extends TAnnotatedType {
|
||||
|
||||
/** Gets a type annotation of this annotated type. */
|
||||
private Annotations::TypeAnnotation getAnAnnotation() {
|
||||
result = getAnnotations().getAnAnnotation()
|
||||
result = this.getAnnotations().getAnAnnotation()
|
||||
}
|
||||
|
||||
/** Holds if the type is a non-nullable reference, for example, `string` in a nullable-enabled context. */
|
||||
@@ -376,7 +378,7 @@ class AnnotatedArrayType extends AnnotatedType {
|
||||
|
||||
private string getDimensionString(AnnotatedType elementType) {
|
||||
exists(AnnotatedType et, string res |
|
||||
et = getElementType() and
|
||||
et = this.getElementType() and
|
||||
res = type.getArraySuffix() and
|
||||
if et.getUnderlyingType() instanceof ArrayType and not et.isNullableRefType()
|
||||
then result = res + et.(AnnotatedArrayType).getDimensionString(elementType)
|
||||
|
||||
@@ -89,7 +89,7 @@ class Attribute extends TopLevelExprParent, @attribute {
|
||||
override Location getALocation() { attribute_location(this, result) }
|
||||
|
||||
override string toString() {
|
||||
exists(string type, string name | type = getType().getName() |
|
||||
exists(string type, string name | type = this.getType().getName() |
|
||||
(if type.matches("%Attribute") then name = type.prefix(type.length() - 9) else name = type) and
|
||||
result = "[" + name + "(...)]"
|
||||
)
|
||||
|
||||
@@ -117,7 +117,7 @@ class Callable extends DotNet::Callable, Parameterizable, ExprOrStmtParent, @cal
|
||||
final BlockStmt getAStatementBody() { result = this.getStatementBody() }
|
||||
|
||||
/** Holds if this callable has a statement body. */
|
||||
final predicate hasStatementBody() { exists(getStatementBody()) }
|
||||
final predicate hasStatementBody() { exists(this.getStatementBody()) }
|
||||
|
||||
/**
|
||||
* Gets the expression body of this callable (if any), specified by `=>`.
|
||||
@@ -157,7 +157,7 @@ class Callable extends DotNet::Callable, Parameterizable, ExprOrStmtParent, @cal
|
||||
deprecated final Expr getAnExpressionBody() { result = this.getExpressionBody() }
|
||||
|
||||
/** Holds if this callable has an expression body. */
|
||||
final predicate hasExpressionBody() { exists(getExpressionBody()) }
|
||||
final predicate hasExpressionBody() { exists(this.getExpressionBody()) }
|
||||
|
||||
/** Gets the entry point in the control graph for this callable. */
|
||||
ControlFlow::Nodes::EntryNode getEntryPoint() { result.getCallable() = this }
|
||||
@@ -218,7 +218,9 @@ class Callable extends DotNet::Callable, Parameterizable, ExprOrStmtParent, @cal
|
||||
exists(YieldReturnStmt yield | yield.getEnclosingCallable() = this | e = yield.getExpr())
|
||||
}
|
||||
|
||||
override string toStringWithTypes() { result = getName() + "(" + parameterTypesToString() + ")" }
|
||||
override string toStringWithTypes() {
|
||||
result = this.getName() + "(" + this.parameterTypesToString() + ")"
|
||||
}
|
||||
|
||||
/** Gets a `Call` that has this callable as a target. */
|
||||
Call getACall() { this = result.getTarget() }
|
||||
@@ -270,18 +272,18 @@ class Method extends Callable, Virtualizable, Attributable, @method {
|
||||
override Location getALocation() { method_location(this, result) }
|
||||
|
||||
/** Holds if this method is an extension method. */
|
||||
predicate isExtensionMethod() { getParameter(0).hasExtensionMethodModifier() }
|
||||
predicate isExtensionMethod() { this.getParameter(0).hasExtensionMethodModifier() }
|
||||
|
||||
/** Gets the type of the `params` parameter of this method, if any. */
|
||||
Type getParamsType() {
|
||||
exists(Parameter last | last = getParameter(getNumberOfParameters() - 1) |
|
||||
exists(Parameter last | last = this.getParameter(this.getNumberOfParameters() - 1) |
|
||||
last.isParams() and
|
||||
result = last.getType().(ArrayType).getElementType()
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if this method has a `params` parameter. */
|
||||
predicate hasParams() { exists(getParamsType()) }
|
||||
predicate hasParams() { exists(this.getParamsType()) }
|
||||
|
||||
// Remove when `Callable.isOverridden()` is removed
|
||||
override predicate isOverridden() { Virtualizable.super.isOverridden() }
|
||||
@@ -316,7 +318,7 @@ class ExtensionMethod extends Method {
|
||||
|
||||
/** Gets the type being extended by this method. */
|
||||
pragma[noinline]
|
||||
Type getExtendedType() { result = getParameter(0).getType() }
|
||||
Type getExtendedType() { result = this.getParameter(0).getType() }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "ExtensionMethod" }
|
||||
}
|
||||
@@ -355,7 +357,7 @@ class Constructor extends DotNet::Constructor, Callable, Member, Attributable, @
|
||||
ConstructorInitializer getInitializer() { result = this.getChildExpr(-1) }
|
||||
|
||||
/** Holds if this constructor has an initializer. */
|
||||
predicate hasInitializer() { exists(getInitializer()) }
|
||||
predicate hasInitializer() { exists(this.getInitializer()) }
|
||||
|
||||
override ValueOrRefType getDeclaringType() { constructors(this, _, result, _) }
|
||||
|
||||
@@ -467,7 +469,7 @@ class Operator extends Callable, Member, Attributable, @operator {
|
||||
|
||||
override string toString() { result = Callable.super.toString() }
|
||||
|
||||
override Parameter getRawParameter(int i) { result = getParameter(i) }
|
||||
override Parameter getRawParameter(int i) { result = this.getParameter(i) }
|
||||
}
|
||||
|
||||
/** A clone method on a record. */
|
||||
@@ -999,10 +1001,10 @@ class LocalFunction extends Callable, Modifiable, Attributable, @local_function
|
||||
|
||||
override Type getReturnType() { local_functions(this, _, result, _) }
|
||||
|
||||
override Element getParent() { result = getStatement().getParent() }
|
||||
override Element getParent() { result = this.getStatement().getParent() }
|
||||
|
||||
/** Gets the local function statement defining this function. */
|
||||
LocalFunctionStmt getStatement() { result.getLocalFunction() = getUnboundDeclaration() }
|
||||
LocalFunctionStmt getStatement() { result.getLocalFunction() = this.getUnboundDeclaration() }
|
||||
|
||||
override Callable getEnclosingCallable() { result = this.getStatement().getEnclosingCallable() }
|
||||
|
||||
@@ -1011,9 +1013,9 @@ class LocalFunction extends Callable, Modifiable, Attributable, @local_function
|
||||
name = this.getName()
|
||||
}
|
||||
|
||||
override Location getALocation() { result = getStatement().getALocation() }
|
||||
override Location getALocation() { result = this.getStatement().getALocation() }
|
||||
|
||||
override Parameter getRawParameter(int i) { result = getParameter(i) }
|
||||
override Parameter getRawParameter(int i) { result = this.getParameter(i) }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "LocalFunction" }
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ import Location
|
||||
/**
|
||||
* A single line of comment.
|
||||
*
|
||||
* Either a single line comment (`SingleLineComment`), an XML comment (`XmlComment`),
|
||||
* Either a single line comment (`SinglelineComment`), an XML comment (`XmlComment`),
|
||||
* or a line in a multi-line comment (`MultilineComment`).
|
||||
*/
|
||||
class CommentLine extends @commentline {
|
||||
|
||||
@@ -31,7 +31,7 @@ class Element extends DotNet::Element, @element {
|
||||
Element getParent() { result.getAChild() = this }
|
||||
|
||||
/** Gets a child of this element, if any. */
|
||||
Element getAChild() { result = getChild(_) }
|
||||
Element getAChild() { result = this.getChild(_) }
|
||||
|
||||
/** Gets the `i`th child of this element (zero-based). */
|
||||
Element getChild(int i) { none() }
|
||||
|
||||
@@ -29,10 +29,10 @@ class Event extends DeclarationWithAccessors, @event {
|
||||
EventAccessor getAnEventAccessor() { result.getDeclaration() = this }
|
||||
|
||||
/** Gets the `add` accessor of this event, if any. */
|
||||
AddEventAccessor getAddEventAccessor() { result = getAnEventAccessor() }
|
||||
AddEventAccessor getAddEventAccessor() { result = this.getAnEventAccessor() }
|
||||
|
||||
/** Gets the `remove` accessor of this event, if any. */
|
||||
RemoveEventAccessor getRemoveEventAccessor() { result = getAnEventAccessor() }
|
||||
RemoveEventAccessor getRemoveEventAccessor() { result = this.getAnEventAccessor() }
|
||||
|
||||
/**
|
||||
* Holds if this event can be used like a field within its declaring type
|
||||
@@ -111,9 +111,9 @@ class EventAccessor extends Accessor, @event_accessor {
|
||||
* ```
|
||||
*/
|
||||
class AddEventAccessor extends EventAccessor, @add_event_accessor {
|
||||
override string getName() { result = "add" + "_" + getDeclaration().getName() }
|
||||
override string getName() { result = "add" + "_" + this.getDeclaration().getName() }
|
||||
|
||||
override string getUndecoratedName() { result = "add" + "_" + getDeclaration().getName() }
|
||||
override string getUndecoratedName() { result = "add" + "_" + this.getDeclaration().getName() }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "AddEventAccessor" }
|
||||
}
|
||||
@@ -132,9 +132,9 @@ class AddEventAccessor extends EventAccessor, @add_event_accessor {
|
||||
* ```
|
||||
*/
|
||||
class RemoveEventAccessor extends EventAccessor, @remove_event_accessor {
|
||||
override string getName() { result = "remove" + "_" + getDeclaration().getName() }
|
||||
override string getName() { result = "remove" + "_" + this.getDeclaration().getName() }
|
||||
|
||||
override string getUndecoratedName() { result = "remove" + "_" + getDeclaration().getName() }
|
||||
override string getUndecoratedName() { result = "remove" + "_" + this.getDeclaration().getName() }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "RemoveEventAccessor" }
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ class Container extends @container {
|
||||
*/
|
||||
string getRelativePath() {
|
||||
exists(string absPath, string pref |
|
||||
absPath = getAbsolutePath() and sourceLocationPrefix(pref)
|
||||
absPath = this.getAbsolutePath() and sourceLocationPrefix(pref)
|
||||
|
|
||||
absPath = pref and result = ""
|
||||
or
|
||||
@@ -74,7 +74,7 @@ class Container extends @container {
|
||||
* </table>
|
||||
*/
|
||||
string getBaseName() {
|
||||
result = getAbsolutePath().regexpCapture(".*/(([^/]*?)(?:\\.([^.]*))?)", 1)
|
||||
result = this.getAbsolutePath().regexpCapture(".*/(([^/]*?)(?:\\.([^.]*))?)", 1)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -100,7 +100,9 @@ class Container extends @container {
|
||||
* <tr><td>"/tmp/x.tar.gz"</td><td>"gz"</td></tr>
|
||||
* </table>
|
||||
*/
|
||||
string getExtension() { result = getAbsolutePath().regexpCapture(".*/([^/]*?)(\\.([^.]*))?", 3) }
|
||||
string getExtension() {
|
||||
result = this.getAbsolutePath().regexpCapture(".*/([^/]*?)(\\.([^.]*))?", 3)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the stem of this container, that is, the prefix of its base name up to
|
||||
@@ -119,7 +121,9 @@ class Container extends @container {
|
||||
* <tr><td>"/tmp/x.tar.gz"</td><td>"x.tar"</td></tr>
|
||||
* </table>
|
||||
*/
|
||||
string getStem() { result = getAbsolutePath().regexpCapture(".*/([^/]*?)(?:\\.([^.]*))?", 1) }
|
||||
string getStem() {
|
||||
result = this.getAbsolutePath().regexpCapture(".*/([^/]*?)(?:\\.([^.]*))?", 1)
|
||||
}
|
||||
|
||||
/** Gets the parent container of this file or folder, if any. */
|
||||
Container getParentContainer() { containerparent(result, this) }
|
||||
@@ -128,52 +132,52 @@ class Container extends @container {
|
||||
Container getAChildContainer() { this = result.getParentContainer() }
|
||||
|
||||
/** Gets a file in this container. */
|
||||
File getAFile() { result = getAChildContainer() }
|
||||
File getAFile() { result = this.getAChildContainer() }
|
||||
|
||||
/** Gets the file in this container that has the given `baseName`, if any. */
|
||||
File getFile(string baseName) {
|
||||
result = getAFile() and
|
||||
result = this.getAFile() and
|
||||
result.getBaseName() = baseName
|
||||
}
|
||||
|
||||
/** Gets a sub-folder in this container. */
|
||||
Folder getAFolder() { result = getAChildContainer() }
|
||||
Folder getAFolder() { result = this.getAChildContainer() }
|
||||
|
||||
/** Gets the sub-folder in this container that has the given `baseName`, if any. */
|
||||
Folder getFolder(string baseName) {
|
||||
result = getAFolder() and
|
||||
result = this.getAFolder() and
|
||||
result.getBaseName() = baseName
|
||||
}
|
||||
|
||||
/** Gets the file or sub-folder in this container that has the given `name`, if any. */
|
||||
Container getChildContainer(string name) {
|
||||
result = getAChildContainer() and
|
||||
result = this.getAChildContainer() and
|
||||
result.getBaseName() = name
|
||||
}
|
||||
|
||||
/** Gets the file in this container that has the given `stem` and `extension`, if any. */
|
||||
File getFile(string stem, string extension) {
|
||||
result = getAChildContainer() and
|
||||
result = this.getAChildContainer() and
|
||||
result.getStem() = stem and
|
||||
result.getExtension() = extension
|
||||
}
|
||||
|
||||
/** Gets a sub-folder contained in this container. */
|
||||
Folder getASubFolder() { result = getAChildContainer() }
|
||||
Folder getASubFolder() { result = this.getAChildContainer() }
|
||||
|
||||
/**
|
||||
* Gets a textual representation of the path of this container.
|
||||
*
|
||||
* This is the absolute path of the container.
|
||||
*/
|
||||
string toString() { result = getAbsolutePath() }
|
||||
string toString() { result = this.getAbsolutePath() }
|
||||
}
|
||||
|
||||
/** A folder. */
|
||||
class Folder extends Container, @folder {
|
||||
override string getAbsolutePath() { folders(this, result) }
|
||||
|
||||
override string getURL() { result = "folder://" + getAbsolutePath() }
|
||||
override string getURL() { result = "folder://" + this.getAbsolutePath() }
|
||||
}
|
||||
|
||||
/** A file. */
|
||||
|
||||
@@ -71,14 +71,14 @@ class ConstructedGeneric extends DotNet::ConstructedGeneric, Generic {
|
||||
override UnboundGeneric getUnboundGeneric() { constructed_generic(this, result) }
|
||||
|
||||
override UnboundGeneric getUnboundDeclaration() {
|
||||
result = getUnboundGeneric().getUnboundDeclaration()
|
||||
result = this.getUnboundGeneric().getUnboundDeclaration()
|
||||
}
|
||||
|
||||
override int getNumberOfTypeArguments() { result = count(int i | type_arguments(_, i, this)) }
|
||||
|
||||
override Type getTypeArgument(int i) { none() }
|
||||
|
||||
override Type getATypeArgument() { result = getTypeArgument(_) }
|
||||
override Type getATypeArgument() { result = this.getTypeArgument(_) }
|
||||
|
||||
/** Gets the annotated type of type argument `i`. */
|
||||
final AnnotatedType getAnnotatedTypeArgument(int i) { result.appliesToTypeArgument(this, i) }
|
||||
@@ -141,7 +141,7 @@ class UnboundGenericType extends ValueOrRefType, UnboundGeneric {
|
||||
result = ValueOrRefType.super.getUnboundDeclaration()
|
||||
}
|
||||
|
||||
final override Type getChild(int n) { result = getTypeParameter(n) }
|
||||
final override Type getChild(int n) { result = this.getTypeParameter(n) }
|
||||
|
||||
override string toStringWithTypes() {
|
||||
result = this.getUndecoratedName() + "<" + getTypeParametersToString(this) + ">"
|
||||
@@ -173,7 +173,7 @@ class TypeParameter extends DotNet::TypeParameter, Type, @type_parameter {
|
||||
TypeParameterConstraints getConstraints() { result.getTypeParameter() = this }
|
||||
|
||||
override predicate isRefType() {
|
||||
exists(TypeParameterConstraints tpc | tpc = getConstraints() |
|
||||
exists(TypeParameterConstraints tpc | tpc = this.getConstraints() |
|
||||
tpc.hasRefTypeConstraint() or
|
||||
tpc.getATypeConstraint() instanceof Class or
|
||||
tpc.getATypeConstraint().(TypeParameter).isRefType()
|
||||
@@ -182,7 +182,7 @@ class TypeParameter extends DotNet::TypeParameter, Type, @type_parameter {
|
||||
}
|
||||
|
||||
override predicate isValueType() {
|
||||
exists(TypeParameterConstraints tpc | tpc = getConstraints() |
|
||||
exists(TypeParameterConstraints tpc | tpc = this.getConstraints() |
|
||||
tpc.hasValueTypeConstraint() or
|
||||
tpc.getATypeConstraint().(TypeParameter).isValueType()
|
||||
)
|
||||
@@ -219,9 +219,9 @@ class TypeParameter extends DotNet::TypeParameter, Type, @type_parameter {
|
||||
|
||||
/** Gets a non-type-parameter type that was transitively supplied for this parameter. */
|
||||
Type getAnUltimatelySuppliedType() {
|
||||
result = getASuppliedType() and not result instanceof TypeParameter
|
||||
result = this.getASuppliedType() and not result instanceof TypeParameter
|
||||
or
|
||||
result = getASuppliedType().(TypeParameter).getAnUltimatelySuppliedType()
|
||||
result = this.getASuppliedType().(TypeParameter).getAnUltimatelySuppliedType()
|
||||
}
|
||||
|
||||
override int getIndex() { type_parameters(this, result, _, _) }
|
||||
@@ -376,8 +376,8 @@ class UnboundGenericDelegateType extends DelegateType, UnboundGenericType {
|
||||
|
||||
override string toStringWithTypes() {
|
||||
result =
|
||||
getUndecoratedName() + "<" + getTypeParametersToString(this) + ">(" + parameterTypesToString()
|
||||
+ ")"
|
||||
this.getUndecoratedName() + "<" + getTypeParametersToString(this) + ">(" +
|
||||
this.parameterTypesToString() + ")"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -404,7 +404,7 @@ class ConstructedType extends ValueOrRefType, ConstructedGeneric {
|
||||
|
||||
override UnboundGenericType getUnboundGeneric() { constructed_generic(this, getTypeRef(result)) }
|
||||
|
||||
final override Type getChild(int n) { result = getTypeArgument(n) }
|
||||
final override Type getChild(int n) { result = this.getTypeArgument(n) }
|
||||
|
||||
final override string toStringWithTypes() {
|
||||
result = this.getUndecoratedName() + "<" + getTypeArgumentsToString(this) + ">"
|
||||
@@ -542,12 +542,12 @@ class UnboundGenericMethod extends Method, UnboundGeneric {
|
||||
|
||||
override string toStringWithTypes() {
|
||||
result =
|
||||
getUndecoratedName() + "<" + getTypeParametersToString(this) + ">" + "(" +
|
||||
parameterTypesToString() + ")"
|
||||
this.getUndecoratedName() + "<" + getTypeParametersToString(this) + ">" + "(" +
|
||||
this.parameterTypesToString() + ")"
|
||||
}
|
||||
|
||||
final override string getName() {
|
||||
result = getUndecoratedName() + "<" + getTypeParameterCommas(this) + ">"
|
||||
result = this.getUndecoratedName() + "<" + getTypeParameterCommas(this) + ">"
|
||||
}
|
||||
|
||||
final override string getUndecoratedName() { methods(this, result, _, _, _) }
|
||||
@@ -580,8 +580,8 @@ class ConstructedMethod extends Method, ConstructedGeneric {
|
||||
|
||||
override string toStringWithTypes() {
|
||||
result =
|
||||
getUndecoratedName() + "<" + getTypeArgumentsToString(this) + ">" + "(" +
|
||||
parameterTypesToString() + ")"
|
||||
this.getUndecoratedName() + "<" + getTypeArgumentsToString(this) + ">" + "(" +
|
||||
this.parameterTypesToString() + ")"
|
||||
}
|
||||
|
||||
override UnboundGenericMethod getUnboundDeclaration() {
|
||||
@@ -589,12 +589,12 @@ class ConstructedMethod extends Method, ConstructedGeneric {
|
||||
}
|
||||
|
||||
final override string getName() {
|
||||
result = getUndecoratedName() + "<" + getTypeArgumentsNames(this) + ">"
|
||||
result = this.getUndecoratedName() + "<" + getTypeArgumentsNames(this) + ">"
|
||||
}
|
||||
|
||||
override predicate hasQualifiedName(string qualifier, string name) {
|
||||
qualifier = getDeclaringType().getQualifiedName() and
|
||||
name = getUndecoratedName() + "<" + getTypeArgumentsQualifiedNames(this) + ">"
|
||||
qualifier = this.getDeclaringType().getQualifiedName() and
|
||||
name = this.getUndecoratedName() + "<" + getTypeArgumentsQualifiedNames(this) + ">"
|
||||
}
|
||||
|
||||
final override string getUndecoratedName() { methods(this, result, _, _, _) }
|
||||
|
||||
@@ -155,7 +155,9 @@ class Modifiable extends Declaration, @modifiable {
|
||||
* Holds if this declaration is effectively `public`, meaning that it can be
|
||||
* referenced outside the declaring assembly.
|
||||
*/
|
||||
predicate isEffectivelyPublic() { not isEffectivelyPrivate() and not isEffectivelyInternal() }
|
||||
predicate isEffectivelyPublic() {
|
||||
not this.isEffectivelyPrivate() and not this.isEffectivelyInternal()
|
||||
}
|
||||
}
|
||||
|
||||
/** A declaration that is a member of a type. */
|
||||
@@ -193,12 +195,12 @@ class Virtualizable extends Member, @virtualizable {
|
||||
|
||||
override predicate isPublic() {
|
||||
Member.super.isPublic() or
|
||||
implementsExplicitInterface()
|
||||
this.implementsExplicitInterface()
|
||||
}
|
||||
|
||||
override predicate isPrivate() {
|
||||
super.isPrivate() and
|
||||
not implementsExplicitInterface()
|
||||
not this.implementsExplicitInterface()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -211,17 +213,17 @@ class Virtualizable extends Member, @virtualizable {
|
||||
/**
|
||||
* Holds if this member implements an interface member explicitly.
|
||||
*/
|
||||
predicate implementsExplicitInterface() { exists(getExplicitlyImplementedInterface()) }
|
||||
predicate implementsExplicitInterface() { exists(this.getExplicitlyImplementedInterface()) }
|
||||
|
||||
/** Holds if this member can be overridden or implemented. */
|
||||
predicate isOverridableOrImplementable() {
|
||||
not isSealed() and
|
||||
not getDeclaringType().isSealed() and
|
||||
not this.isSealed() and
|
||||
not this.getDeclaringType().isSealed() and
|
||||
(
|
||||
isVirtual() or
|
||||
isOverride() or
|
||||
isAbstract() or
|
||||
getDeclaringType() instanceof Interface
|
||||
this.isVirtual() or
|
||||
this.isOverride() or
|
||||
this.isAbstract() or
|
||||
this.getDeclaringType() instanceof Interface
|
||||
)
|
||||
}
|
||||
|
||||
@@ -243,10 +245,10 @@ class Virtualizable extends Member, @virtualizable {
|
||||
Virtualizable getAnOverrider() { this = result.getOverridee() }
|
||||
|
||||
/** Holds if this member is overridden by some other member. */
|
||||
predicate isOverridden() { exists(getAnOverrider()) }
|
||||
predicate isOverridden() { exists(this.getAnOverrider()) }
|
||||
|
||||
/** Holds if this member overrides another member. */
|
||||
predicate overrides() { exists(getOverridee()) }
|
||||
predicate overrides() { exists(this.getOverridee()) }
|
||||
|
||||
/**
|
||||
* Gets the interface member that is immediately implemented by this member, if any.
|
||||
@@ -274,7 +276,7 @@ class Virtualizable extends Member, @virtualizable {
|
||||
Virtualizable getImplementee(ValueOrRefType t) { implements(this, result, t) }
|
||||
|
||||
/** Gets the interface member that is immediately implemented by this member, if any. */
|
||||
Virtualizable getImplementee() { result = getImplementee(_) }
|
||||
Virtualizable getImplementee() { result = this.getImplementee(_) }
|
||||
|
||||
/**
|
||||
* Gets a member that immediately implements this interface member, if any.
|
||||
@@ -338,8 +340,8 @@ class Virtualizable extends Member, @virtualizable {
|
||||
|
|
||||
this = implementation
|
||||
or
|
||||
getOverridee+() = implementation and
|
||||
getDeclaringType().getABaseType+() = implementationType
|
||||
this.getOverridee+() = implementation and
|
||||
this.getDeclaringType().getABaseType+() = implementationType
|
||||
)
|
||||
}
|
||||
|
||||
@@ -355,10 +357,10 @@ class Virtualizable extends Member, @virtualizable {
|
||||
Virtualizable getAnUltimateImplementor() { this = result.getAnUltimateImplementee() }
|
||||
|
||||
/** Holds if this interface member is implemented by some other member. */
|
||||
predicate isImplemented() { exists(getAnImplementor()) }
|
||||
predicate isImplemented() { exists(this.getAnImplementor()) }
|
||||
|
||||
/** Holds if this member implements (transitively) an interface member. */
|
||||
predicate implements() { exists(getAnUltimateImplementee()) }
|
||||
predicate implements() { exists(this.getAnUltimateImplementee()) }
|
||||
|
||||
/**
|
||||
* Holds if this member overrides or implements (reflexively, transitively)
|
||||
@@ -366,8 +368,8 @@ class Virtualizable extends Member, @virtualizable {
|
||||
*/
|
||||
predicate overridesOrImplementsOrEquals(Virtualizable that) {
|
||||
this = that or
|
||||
getOverridee+() = that or
|
||||
getAnUltimateImplementee() = that
|
||||
this.getOverridee+() = that or
|
||||
this.getAnUltimateImplementee() = that
|
||||
}
|
||||
}
|
||||
|
||||
@@ -386,7 +388,7 @@ class Parameterizable extends DotNet::Parameterizable, Declaration, @parameteriz
|
||||
*/
|
||||
private string parameterTypeToString(int i) {
|
||||
exists(Parameter p, string prefix |
|
||||
p = getParameter(i) and
|
||||
p = this.getParameter(i) and
|
||||
result = prefix + p.getType().toStringWithTypes()
|
||||
|
|
||||
if p.isOut()
|
||||
@@ -407,6 +409,7 @@ class Parameterizable extends DotNet::Parameterizable, Declaration, @parameteriz
|
||||
*/
|
||||
language[monotonicAggregates]
|
||||
string parameterTypesToString() {
|
||||
result = concat(int i | exists(getParameter(i)) | parameterTypeToString(i), ", " order by i)
|
||||
result =
|
||||
concat(int i | exists(this.getParameter(i)) | this.parameterTypeToString(i), ", " order by i)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,9 +20,9 @@ class Modifier extends Element, @modifier {
|
||||
*/
|
||||
class AccessModifier extends Modifier {
|
||||
AccessModifier() {
|
||||
hasName("public") or
|
||||
hasName("private") or
|
||||
hasName("internal") or
|
||||
hasName("protected")
|
||||
this.hasName("public") or
|
||||
this.hasName("private") or
|
||||
this.hasName("internal") or
|
||||
this.hasName("protected")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -289,7 +289,7 @@ class IfDirective extends ConditionalDirective, @directive_if {
|
||||
}
|
||||
|
||||
/** Gets a sibling `#elif` or `#else` preprocessor directive. */
|
||||
BranchDirective getASiblingDirective() { result = getSiblingDirective(_) }
|
||||
BranchDirective getASiblingDirective() { result = this.getSiblingDirective(_) }
|
||||
|
||||
override string toString() { result = "#if ..." }
|
||||
|
||||
|
||||
@@ -171,7 +171,7 @@ class PrintAstNode extends TPrintAstNode {
|
||||
/**
|
||||
* Gets a child of this node.
|
||||
*/
|
||||
final PrintAstNode getAChild() { result = getChild(_) }
|
||||
final PrintAstNode getAChild() { result = this.getChild(_) }
|
||||
|
||||
/**
|
||||
* Gets the parent of this node, if any.
|
||||
@@ -189,7 +189,7 @@ class PrintAstNode extends TPrintAstNode {
|
||||
*/
|
||||
string getProperty(string key) {
|
||||
key = "semmle.label" and
|
||||
result = toString()
|
||||
result = this.toString()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -198,7 +198,7 @@ class PrintAstNode extends TPrintAstNode {
|
||||
* this.
|
||||
*/
|
||||
string getChildEdgeLabel(int childIndex) {
|
||||
exists(getChild(childIndex)) and
|
||||
exists(this.getChild(childIndex)) and
|
||||
result = childIndex.toString()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,10 +53,10 @@ class DeclarationWithAccessors extends AssignableMember, Virtualizable, Attribut
|
||||
class DeclarationWithGetSetAccessors extends DeclarationWithAccessors, TopLevelExprParent,
|
||||
@assignable_with_accessors {
|
||||
/** Gets the `get` accessor of this declaration, if any. */
|
||||
Getter getGetter() { result = getAnAccessor() }
|
||||
Getter getGetter() { result = this.getAnAccessor() }
|
||||
|
||||
/** Gets the `set` accessor of this declaration, if any. */
|
||||
Setter getSetter() { result = getAnAccessor() }
|
||||
Setter getSetter() { result = this.getAnAccessor() }
|
||||
|
||||
override DeclarationWithGetSetAccessors getOverridee() {
|
||||
result = DeclarationWithAccessors.super.getOverridee()
|
||||
@@ -182,10 +182,10 @@ class Property extends DotNet::Property, DeclarationWithGetSetAccessors, @proper
|
||||
or
|
||||
// For library types, we don't know about assignments in constructors. We instead assume that
|
||||
// arguments passed to parameters of constructors with suitable names.
|
||||
getDeclaringType().fromLibrary() and
|
||||
this.getDeclaringType().fromLibrary() and
|
||||
exists(Parameter param, Constructor c, string propertyName |
|
||||
propertyName = getName() and
|
||||
c = getDeclaringType().getAConstructor() and
|
||||
propertyName = this.getName() and
|
||||
c = this.getDeclaringType().getAConstructor() and
|
||||
param = c.getAParameter() and
|
||||
// Find a constructor parameter with the same name, but with a lower case initial letter.
|
||||
param.hasName(propertyName.charAt(0).toLowerCase() + propertyName.suffix(1))
|
||||
@@ -256,7 +256,7 @@ class Indexer extends DeclarationWithGetSetAccessors, Parameterizable, @indexer
|
||||
override string getUndecoratedName() { indexers(this, result, _, _, _) }
|
||||
|
||||
/** Gets the dimension of this indexer, that is, its number of parameters. */
|
||||
int getDimension() { result = getNumberOfParameters() }
|
||||
int getDimension() { result = this.getNumberOfParameters() }
|
||||
|
||||
override ValueOrRefType getDeclaringType() { indexers(this, _, result, _, _) }
|
||||
|
||||
@@ -304,7 +304,9 @@ class Indexer extends DeclarationWithGetSetAccessors, Parameterizable, @indexer
|
||||
|
||||
override Location getALocation() { indexer_location(this, result) }
|
||||
|
||||
override string toStringWithTypes() { result = getName() + "[" + parameterTypesToString() + "]" }
|
||||
override string toStringWithTypes() {
|
||||
result = this.getName() + "[" + this.parameterTypesToString() + "]"
|
||||
}
|
||||
|
||||
override string getAPrimaryQlClass() { result = "Indexer" }
|
||||
}
|
||||
@@ -368,17 +370,17 @@ class Accessor extends Callable, Modifiable, Attributable, @callable_accessor {
|
||||
* ```
|
||||
*/
|
||||
override Modifier getAModifier() {
|
||||
result = getAnAccessModifier()
|
||||
result = this.getAnAccessModifier()
|
||||
or
|
||||
result = getDeclaration().getAModifier() and
|
||||
not (result instanceof AccessModifier and exists(getAnAccessModifier()))
|
||||
result = this.getDeclaration().getAModifier() and
|
||||
not (result instanceof AccessModifier and exists(this.getAnAccessModifier()))
|
||||
}
|
||||
|
||||
override Accessor getUnboundDeclaration() { accessors(this, _, _, _, result) }
|
||||
|
||||
override Location getALocation() { accessor_location(this, result) }
|
||||
|
||||
override string toString() { result = getName() }
|
||||
override string toString() { result = this.getName() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -395,11 +397,11 @@ class Accessor extends Callable, Modifiable, Attributable, @callable_accessor {
|
||||
* ```
|
||||
*/
|
||||
class Getter extends Accessor, @getter {
|
||||
override string getName() { result = "get" + "_" + getDeclaration().getName() }
|
||||
override string getName() { result = "get" + "_" + this.getDeclaration().getName() }
|
||||
|
||||
override string getUndecoratedName() { result = "get" + "_" + getDeclaration().getName() }
|
||||
override string getUndecoratedName() { result = "get" + "_" + this.getDeclaration().getName() }
|
||||
|
||||
override Type getReturnType() { result = getDeclaration().getType() }
|
||||
override Type getReturnType() { result = this.getDeclaration().getType() }
|
||||
|
||||
/**
|
||||
* Gets the field used in the trival implementation of this getter, if any.
|
||||
@@ -417,8 +419,8 @@ class Getter extends Accessor, @getter {
|
||||
*/
|
||||
Field trivialGetterField() {
|
||||
exists(ReturnStmt ret |
|
||||
getStatementBody().getNumberOfStmts() = 1 and
|
||||
getStatementBody().getAChild() = ret and
|
||||
this.getStatementBody().getNumberOfStmts() = 1 and
|
||||
this.getStatementBody().getAChild() = ret and
|
||||
ret.getExpr() = result.getAnAccess()
|
||||
)
|
||||
}
|
||||
@@ -444,9 +446,9 @@ class Getter extends Accessor, @getter {
|
||||
* ```
|
||||
*/
|
||||
class Setter extends Accessor, @setter {
|
||||
override string getName() { result = "set" + "_" + getDeclaration().getName() }
|
||||
override string getName() { result = "set" + "_" + this.getDeclaration().getName() }
|
||||
|
||||
override string getUndecoratedName() { result = "set" + "_" + getDeclaration().getName() }
|
||||
override string getUndecoratedName() { result = "set" + "_" + this.getDeclaration().getName() }
|
||||
|
||||
override Type getReturnType() {
|
||||
exists(this) and // needed to avoid compiler warning
|
||||
@@ -469,8 +471,8 @@ class Setter extends Accessor, @setter {
|
||||
*/
|
||||
Field trivialSetterField() {
|
||||
exists(AssignExpr assign |
|
||||
getStatementBody().getNumberOfStmts() = 1 and
|
||||
assign.getParent() = getStatementBody().getAChild() and
|
||||
this.getStatementBody().getNumberOfStmts() = 1 and
|
||||
assign.getParent() = this.getStatementBody().getAChild() and
|
||||
assign.getLValue() = result.getAnAccess() and
|
||||
assign.getRValue() = accessToValue()
|
||||
)
|
||||
@@ -521,9 +523,9 @@ private ParameterAccess accessToValue() {
|
||||
*/
|
||||
class TrivialProperty extends Property {
|
||||
TrivialProperty() {
|
||||
isAutoImplemented()
|
||||
this.isAutoImplemented()
|
||||
or
|
||||
getGetter().trivialGetterField() = getSetter().trivialSetterField()
|
||||
this.getGetter().trivialGetterField() = this.getSetter().trivialSetterField()
|
||||
or
|
||||
exists(CIL::TrivialProperty prop | this.matchesHandle(prop))
|
||||
}
|
||||
|
||||
@@ -65,10 +65,10 @@ class BlockStmt extends Stmt, @block_stmt {
|
||||
int getNumberOfStmts() { result = count(this.getAStmt()) }
|
||||
|
||||
/** Gets the first statement in this block, if any. */
|
||||
Stmt getFirstStmt() { result = getStmt(0) }
|
||||
Stmt getFirstStmt() { result = this.getStmt(0) }
|
||||
|
||||
/** Gets the last statement in this block, if any. */
|
||||
Stmt getLastStmt() { result = getStmt(getNumberOfStmts() - 1) }
|
||||
Stmt getLastStmt() { result = this.getStmt(this.getNumberOfStmts() - 1) }
|
||||
|
||||
/** Holds if this block is an empty block with no statements. */
|
||||
predicate isEmpty() { not exists(this.getAStmt()) }
|
||||
@@ -79,8 +79,8 @@ class BlockStmt extends Stmt, @block_stmt {
|
||||
}
|
||||
|
||||
override Stmt stripSingletonBlocks() {
|
||||
if getNumberOfStmts() = 1
|
||||
then result = getAChildStmt().stripSingletonBlocks()
|
||||
if this.getNumberOfStmts() = 1
|
||||
then result = this.getAChildStmt().stripSingletonBlocks()
|
||||
else result = this
|
||||
}
|
||||
|
||||
@@ -420,7 +420,7 @@ class ForStmt extends LoopStmt, @for_stmt {
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
Expr getAnInitializer() { result = getInitializer(_) }
|
||||
Expr getAnInitializer() { result = this.getInitializer(_) }
|
||||
|
||||
/**
|
||||
* Gets the `n`th initializer expression of this `for` loop
|
||||
@@ -451,7 +451,7 @@ class ForStmt extends LoopStmt, @for_stmt {
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
Expr getAnUpdate() { result = getUpdate(_) }
|
||||
Expr getAnUpdate() { result = this.getUpdate(_) }
|
||||
|
||||
/**
|
||||
* Gets the `n`th update expression of this `for` loop (starting at index 0).
|
||||
@@ -519,7 +519,7 @@ class ForeachStmt extends LoopStmt, @foreach_stmt {
|
||||
* ```
|
||||
*/
|
||||
LocalVariableDeclExpr getVariableDeclExpr(int i) {
|
||||
result = getVariableDeclTuple().getArgument(i)
|
||||
result = this.getVariableDeclTuple().getArgument(i)
|
||||
or
|
||||
i = 0 and result = this.getChild(0)
|
||||
}
|
||||
@@ -547,7 +547,7 @@ class ForeachStmt extends LoopStmt, @foreach_stmt {
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
LocalVariable getVariable(int i) { result = getVariableDeclExpr(i).getVariable() }
|
||||
LocalVariable getVariable(int i) { result = this.getVariableDeclExpr(i).getVariable() }
|
||||
|
||||
/**
|
||||
* Gets a local variable of this `foreach` loop.
|
||||
@@ -560,7 +560,7 @@ class ForeachStmt extends LoopStmt, @foreach_stmt {
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
LocalVariable getAVariable() { result = getVariable(_) }
|
||||
LocalVariable getAVariable() { result = this.getVariable(_) }
|
||||
|
||||
/**
|
||||
* Gets a local variable declaration of this `foreach` loop.
|
||||
@@ -573,7 +573,7 @@ class ForeachStmt extends LoopStmt, @foreach_stmt {
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
LocalVariableDeclExpr getAVariableDeclExpr() { result = getVariableDeclExpr(_) }
|
||||
LocalVariableDeclExpr getAVariableDeclExpr() { result = this.getVariableDeclExpr(_) }
|
||||
|
||||
override Expr getCondition() { none() }
|
||||
|
||||
@@ -690,8 +690,8 @@ class GotoLabelStmt extends GotoStmt, @goto_stmt {
|
||||
|
||||
/** Gets the target statement that this `goto` statement jumps to. */
|
||||
LabeledStmt getTarget() {
|
||||
result.getEnclosingCallable() = getEnclosingCallable() and
|
||||
result.getLabel() = getLabel()
|
||||
result.getEnclosingCallable() = this.getEnclosingCallable() and
|
||||
result.getLabel() = this.getLabel()
|
||||
}
|
||||
|
||||
override string getAPrimaryQlClass() { result = "GotoLabelStmt" }
|
||||
@@ -717,7 +717,7 @@ class GotoCaseStmt extends GotoStmt, @goto_case_stmt {
|
||||
/** Gets the constant expression that this `goto case` statement jumps to. */
|
||||
Expr getExpr() { result = this.getChild(0) }
|
||||
|
||||
override string getLabel() { result = getExpr().getValue() }
|
||||
override string getLabel() { result = this.getExpr().getValue() }
|
||||
|
||||
override string toString() { result = "goto case ...;" }
|
||||
|
||||
@@ -764,14 +764,14 @@ class ThrowStmt extends JumpStmt, ThrowElement, @throw_stmt {
|
||||
override ExceptionClass getThrownExceptionType() {
|
||||
result = ThrowElement.super.getThrownExceptionType()
|
||||
or
|
||||
result = getRethrowParent().(CatchClause).getCaughtExceptionType()
|
||||
result = this.getRethrowParent().(CatchClause).getCaughtExceptionType()
|
||||
}
|
||||
|
||||
private ControlFlowElement getRethrowParent() {
|
||||
result = this and not exists(getExpr())
|
||||
result = this and not exists(this.getExpr())
|
||||
or
|
||||
exists(ControlFlowElement mid |
|
||||
mid = getRethrowParent() and
|
||||
mid = this.getRethrowParent() and
|
||||
not mid instanceof CatchClause and
|
||||
result = mid.getParent()
|
||||
)
|
||||
@@ -785,7 +785,7 @@ class ThrowStmt extends JumpStmt, ThrowElement, @throw_stmt {
|
||||
* and may be thrown as an exception.
|
||||
*/
|
||||
class ExceptionClass extends Class {
|
||||
ExceptionClass() { getBaseClass*() instanceof SystemExceptionClass }
|
||||
ExceptionClass() { this.getBaseClass*() instanceof SystemExceptionClass }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -897,13 +897,15 @@ class TryStmt extends Stmt, @try_stmt {
|
||||
override string getAPrimaryQlClass() { result = "TryStmt" }
|
||||
|
||||
/** Gets the `catch` clause that handles an exception of type `ex`, if any. */
|
||||
CatchClause getAnExceptionHandler(ExceptionClass ex) { result = clauseHandlesException(ex, 0) }
|
||||
CatchClause getAnExceptionHandler(ExceptionClass ex) {
|
||||
result = this.clauseHandlesException(ex, 0)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if catch clause `cc` definitely handles exceptions of type `ex`.
|
||||
*/
|
||||
predicate definitelyHandles(ExceptionClass ex, CatchClause cc) {
|
||||
cc = getACatchClause() and
|
||||
cc = this.getACatchClause() and
|
||||
not exists(cc.getFilterClause()) and
|
||||
(
|
||||
cc.getCaughtExceptionType() = ex.getBaseClass*()
|
||||
@@ -913,22 +915,22 @@ class TryStmt extends Stmt, @try_stmt {
|
||||
}
|
||||
|
||||
private predicate maybeHandles(ExceptionClass ex, CatchClause cc) {
|
||||
cc = getACatchClause() and
|
||||
cc = this.getACatchClause() and
|
||||
cc.getCaughtExceptionType().getBaseClass*() = ex
|
||||
}
|
||||
|
||||
private CatchClause clauseHandlesException(ExceptionClass ex, int n) {
|
||||
exists(CatchClause clause | clause = getCatchClause(n) |
|
||||
if definitelyHandles(ex, clause)
|
||||
exists(CatchClause clause | clause = this.getCatchClause(n) |
|
||||
if this.definitelyHandles(ex, clause)
|
||||
then result = clause
|
||||
else
|
||||
if maybeHandles(ex, clause)
|
||||
if this.maybeHandles(ex, clause)
|
||||
then
|
||||
result = clause or
|
||||
result = clauseHandlesException(ex, n + 1)
|
||||
result = this.clauseHandlesException(ex, n + 1)
|
||||
else
|
||||
// Does not handle
|
||||
result = clauseHandlesException(ex, n + 1)
|
||||
result = this.clauseHandlesException(ex, n + 1)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -939,10 +941,10 @@ class TryStmt extends Stmt, @try_stmt {
|
||||
* `try` statement.
|
||||
*/
|
||||
ControlFlowElement getATriedElement() {
|
||||
result = getBlock()
|
||||
result = this.getBlock()
|
||||
or
|
||||
exists(ControlFlowElement mid |
|
||||
mid = getATriedElement() and
|
||||
mid = this.getATriedElement() and
|
||||
not mid instanceof TryStmt and
|
||||
result = getAChild(mid, mid.getEnclosingCallable())
|
||||
)
|
||||
@@ -996,10 +998,10 @@ class CatchClause extends Stmt, @catch {
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
Expr getFilterClause() { result = getChild(2) }
|
||||
Expr getFilterClause() { result = this.getChild(2) }
|
||||
|
||||
/** Holds if this `catch` clause has a filter. */
|
||||
predicate hasFilterClause() { exists(getFilterClause()) }
|
||||
predicate hasFilterClause() { exists(this.getFilterClause()) }
|
||||
|
||||
/** Holds if this is the last `catch` clause in the `try` statement that it belongs to. */
|
||||
predicate isLast() {
|
||||
@@ -1120,7 +1122,7 @@ class LockStmt extends Stmt, @lock_stmt {
|
||||
override string toString() { result = "lock (...) {...}" }
|
||||
|
||||
/** Gets the variable being locked, if any. */
|
||||
Variable getLockVariable() { result.getAnAccess() = getExpr() }
|
||||
Variable getLockVariable() { result.getAnAccess() = this.getExpr() }
|
||||
|
||||
/** Gets a statement in the scope of this `lock` statement. */
|
||||
Stmt getALockedStmt() {
|
||||
@@ -1128,14 +1130,14 @@ class LockStmt extends Stmt, @lock_stmt {
|
||||
// delegates and lambdas
|
||||
result.getParent() = this
|
||||
or
|
||||
exists(Stmt mid | mid = getALockedStmt() and result.getParent() = mid)
|
||||
exists(Stmt mid | mid = this.getALockedStmt() and result.getParent() = mid)
|
||||
}
|
||||
|
||||
/** Holds if this statement is of the form `lock(this) { ... }`. */
|
||||
predicate isLockThis() { getExpr() instanceof ThisAccess }
|
||||
predicate isLockThis() { this.getExpr() instanceof ThisAccess }
|
||||
|
||||
/** Gets the type `T` if this statement is of the form `lock(typeof(T)) { ... }`. */
|
||||
Type getLockTypeObject() { result = getExpr().(TypeofExpr).getTypeAccess().getTarget() }
|
||||
Type getLockTypeObject() { result = this.getExpr().(TypeofExpr).getTypeAccess().getTarget() }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "LockStmt" }
|
||||
}
|
||||
@@ -1453,7 +1455,7 @@ class LocalFunctionStmt extends Stmt, @local_function_stmt {
|
||||
/** Gets the local function defined by this statement. */
|
||||
LocalFunction getLocalFunction() { local_function_stmts(this, result) }
|
||||
|
||||
override string toString() { result = getLocalFunction().getName() + "(...)" }
|
||||
override string toString() { result = this.getLocalFunction().getName() + "(...)" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "LocalFunctionStmt" }
|
||||
}
|
||||
|
||||
@@ -37,7 +37,7 @@ class Type extends DotNet::Type, Member, TypeContainer, @type {
|
||||
predicate containsTypeParameters() {
|
||||
this instanceof TypeParameter
|
||||
or
|
||||
not this instanceof UnboundGenericType and getAChild().containsTypeParameters()
|
||||
not this instanceof UnboundGenericType and this.getAChild().containsTypeParameters()
|
||||
}
|
||||
|
||||
/** Holds if this type is a reference type, or a type parameter that is a reference type. */
|
||||
@@ -133,8 +133,8 @@ class ValueOrRefType extends DotNet::ValueOrRefType, Type, Attributable, @value_
|
||||
|
||||
/** Gets an immediate base type of this type, if any. */
|
||||
override ValueOrRefType getABaseType() {
|
||||
result = getBaseClass() or
|
||||
result = getABaseInterface()
|
||||
result = this.getBaseClass() or
|
||||
result = this.getABaseInterface()
|
||||
}
|
||||
|
||||
/** Gets an immediate subtype of this type, if any. */
|
||||
@@ -200,9 +200,9 @@ class ValueOrRefType extends DotNet::ValueOrRefType, Type, Attributable, @value_
|
||||
*/
|
||||
pragma[inline]
|
||||
predicate hasCallable(Callable c) {
|
||||
hasMethod(c)
|
||||
this.hasMethod(c)
|
||||
or
|
||||
hasMember(c.(Accessor).getDeclaration())
|
||||
this.hasMember(c.(Accessor).getDeclaration())
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -234,63 +234,63 @@ class ValueOrRefType extends DotNet::ValueOrRefType, Type, Attributable, @value_
|
||||
or
|
||||
hasNonOverriddenMember(this.getBaseClass+(), m)
|
||||
or
|
||||
hasOverriddenMember(m)
|
||||
this.hasOverriddenMember(m)
|
||||
}
|
||||
|
||||
cached
|
||||
private predicate hasOverriddenMember(Virtualizable v) {
|
||||
v.isOverridden() and
|
||||
v = getAMember()
|
||||
v = this.getAMember()
|
||||
or
|
||||
getBaseClass().(ValueOrRefType).hasOverriddenMember(v) and
|
||||
this.getBaseClass().(ValueOrRefType).hasOverriddenMember(v) and
|
||||
not v.isPrivate() and
|
||||
not memberOverrides(v)
|
||||
not this.memberOverrides(v)
|
||||
}
|
||||
|
||||
// Predicate folding for proper join-order
|
||||
pragma[noinline]
|
||||
private predicate memberOverrides(Virtualizable v) {
|
||||
getAMember().(Virtualizable).getOverridee() = v
|
||||
this.getAMember().(Virtualizable).getOverridee() = v
|
||||
}
|
||||
|
||||
/** Gets a field (or member constant) with the given name. */
|
||||
Field getField(string name) { result = getAMember() and result.hasName(name) }
|
||||
Field getField(string name) { result = this.getAMember() and result.hasName(name) }
|
||||
|
||||
/** Gets a field (or member constant) of this type, if any. */
|
||||
Field getAField() { result = this.getField(_) }
|
||||
|
||||
/** Gets a member constant of this type, if any. */
|
||||
MemberConstant getAConstant() { result = getAMember() }
|
||||
MemberConstant getAConstant() { result = this.getAMember() }
|
||||
|
||||
/** Gets a method of this type, if any. */
|
||||
Method getAMethod() { result = getAMember() }
|
||||
Method getAMethod() { result = this.getAMember() }
|
||||
|
||||
/** Gets a method of this type with the given name. */
|
||||
Method getAMethod(string name) { result = getAMember() and result.hasName(name) }
|
||||
Method getAMethod(string name) { result = this.getAMember() and result.hasName(name) }
|
||||
|
||||
/** Gets a property of this type, if any. */
|
||||
Property getAProperty() { result = getAMember() }
|
||||
Property getAProperty() { result = this.getAMember() }
|
||||
|
||||
/** Gets a named property of this type. */
|
||||
Property getProperty(string name) { result = getAMember() and result.hasName(name) }
|
||||
Property getProperty(string name) { result = this.getAMember() and result.hasName(name) }
|
||||
|
||||
/** Gets an indexer of this type, if any. */
|
||||
Indexer getAnIndexer() { result = getAMember() }
|
||||
Indexer getAnIndexer() { result = this.getAMember() }
|
||||
|
||||
/** Gets an event of this type, if any. */
|
||||
Event getAnEvent() { result = getAMember() }
|
||||
Event getAnEvent() { result = this.getAMember() }
|
||||
|
||||
/** Gets a user-defined operator of this type, if any. */
|
||||
Operator getAnOperator() { result = getAMember() }
|
||||
Operator getAnOperator() { result = this.getAMember() }
|
||||
|
||||
/** Gets a static or instance constructor of this type, if any. */
|
||||
Constructor getAConstructor() { result = getAMember() }
|
||||
Constructor getAConstructor() { result = this.getAMember() }
|
||||
|
||||
/** Gets the static constructor of this type, if any. */
|
||||
StaticConstructor getStaticConstructor() { result = getAMember() }
|
||||
StaticConstructor getStaticConstructor() { result = this.getAMember() }
|
||||
|
||||
/** Gets a nested type of this type, if any. */
|
||||
NestedType getANestedType() { result = getAMember() }
|
||||
NestedType getANestedType() { result = this.getAMember() }
|
||||
|
||||
/** Gets the number of types that directly depend on this type. */
|
||||
int getAfferentCoupling() { afferentCoupling(this, result) }
|
||||
@@ -675,10 +675,10 @@ class Enum extends ValueType, @enum_type {
|
||||
*/
|
||||
class Struct extends ValueType, @struct_type {
|
||||
/** Holds if this `struct` has a `ref` modifier. */
|
||||
predicate isRef() { hasModifier("ref") }
|
||||
predicate isRef() { this.hasModifier("ref") }
|
||||
|
||||
/** Holds if this `struct` has a `readonly` modifier. */
|
||||
predicate isReadonly() { hasModifier("readonly") }
|
||||
predicate isReadonly() { this.hasModifier("readonly") }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "Struct" }
|
||||
}
|
||||
@@ -695,7 +695,7 @@ class RefType extends ValueOrRefType, @ref_type {
|
||||
|
||||
/** Gets a member that overrides a non-abstract member in a super type, if any. */
|
||||
private Virtualizable getAnOverrider() {
|
||||
getAMember() = result and
|
||||
this.getAMember() = result and
|
||||
exists(Virtualizable v | result.getOverridee() = v and not v.isAbstract())
|
||||
}
|
||||
|
||||
@@ -897,14 +897,14 @@ class FunctionPointerType extends Type, Parameterizable, @function_pointer_type
|
||||
}
|
||||
|
||||
/** Gets an unmanaged calling convention. */
|
||||
Type getAnUnmanagedCallingConvention() { result = getUnmanagedCallingConvention(_) }
|
||||
Type getAnUnmanagedCallingConvention() { result = this.getUnmanagedCallingConvention(_) }
|
||||
|
||||
/** Gets the annotated return type of this function pointer type. */
|
||||
AnnotatedType getAnnotatedReturnType() { result.appliesTo(this) }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "FunctionPointerType" }
|
||||
|
||||
override string getLabel() { result = getName() }
|
||||
override string getLabel() { result = this.getName() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -922,13 +922,15 @@ class NullableType extends ValueType, DotNet::ConstructedGeneric, @nullable_type
|
||||
*/
|
||||
Type getUnderlyingType() { nullable_underlying_type(this, getTypeRef(result)) }
|
||||
|
||||
override string toStringWithTypes() { result = getUnderlyingType().toStringWithTypes() + "?" }
|
||||
override string toStringWithTypes() {
|
||||
result = this.getUnderlyingType().toStringWithTypes() + "?"
|
||||
}
|
||||
|
||||
override Type getChild(int n) { result = getUnderlyingType() and n = 0 }
|
||||
override Type getChild(int n) { result = this.getUnderlyingType() and n = 0 }
|
||||
|
||||
override Location getALocation() { result = getUnderlyingType().getALocation() }
|
||||
override Location getALocation() { result = this.getUnderlyingType().getALocation() }
|
||||
|
||||
override Type getTypeArgument(int p) { p = 0 and result = getUnderlyingType() }
|
||||
override Type getTypeArgument(int p) { p = 0 and result = this.getUnderlyingType() }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "NullableType" }
|
||||
|
||||
@@ -966,8 +968,8 @@ class ArrayType extends DotNet::ArrayType, RefType, @array_type {
|
||||
|
||||
/** Holds if this array type has the same shape (dimension and rank) as `that` array type. */
|
||||
predicate hasSameShapeAs(ArrayType that) {
|
||||
getDimension() = that.getDimension() and
|
||||
getRank() = that.getRank()
|
||||
this.getDimension() = that.getDimension() and
|
||||
this.getRank() = that.getRank()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -981,7 +983,7 @@ class ArrayType extends DotNet::ArrayType, RefType, @array_type {
|
||||
private string getDimensionString(Type elementType) {
|
||||
exists(Type et, string res |
|
||||
et = this.getElementType() and
|
||||
res = getArraySuffix() and
|
||||
res = this.getArraySuffix() and
|
||||
if et instanceof ArrayType
|
||||
then result = res + et.(ArrayType).getDimensionString(elementType)
|
||||
else (
|
||||
@@ -996,7 +998,7 @@ class ArrayType extends DotNet::ArrayType, RefType, @array_type {
|
||||
)
|
||||
}
|
||||
|
||||
override Type getChild(int n) { result = getElementType() and n = 0 }
|
||||
override Type getChild(int n) { result = this.getElementType() and n = 0 }
|
||||
|
||||
override Location getALocation() {
|
||||
type_location(this, result)
|
||||
@@ -1021,13 +1023,15 @@ class PointerType extends DotNet::PointerType, Type, @pointer_type {
|
||||
|
||||
override string toStringWithTypes() { result = DotNet::PointerType.super.toStringWithTypes() }
|
||||
|
||||
override Type getChild(int n) { result = getReferentType() and n = 0 }
|
||||
override Type getChild(int n) { result = this.getReferentType() and n = 0 }
|
||||
|
||||
final override string getName() { types(this, _, result) }
|
||||
|
||||
final override string getUndecoratedName() { result = getReferentType().getUndecoratedName() }
|
||||
final override string getUndecoratedName() {
|
||||
result = this.getReferentType().getUndecoratedName()
|
||||
}
|
||||
|
||||
override Location getALocation() { result = getReferentType().getALocation() }
|
||||
override Location getALocation() { result = this.getReferentType().getALocation() }
|
||||
|
||||
override string toString() { result = DotNet::PointerType.super.toString() }
|
||||
|
||||
@@ -1082,10 +1086,10 @@ class TupleType extends ValueType, @tuple_type {
|
||||
* Gets the type of the `n`th element of this tuple, indexed from 0.
|
||||
* For example, the 0th (first) element type of `(int, string)` is `int`.
|
||||
*/
|
||||
Type getElementType(int n) { result = getElement(n).getType() }
|
||||
Type getElementType(int n) { result = this.getElement(n).getType() }
|
||||
|
||||
/** Gets an element of this tuple. */
|
||||
Field getAnElement() { result = getElement(_) }
|
||||
Field getAnElement() { result = this.getElement(_) }
|
||||
|
||||
override Location getALocation() { type_location(this, result) }
|
||||
|
||||
@@ -1093,23 +1097,27 @@ class TupleType extends ValueType, @tuple_type {
|
||||
* Gets the arity of this tuple. For example, the arity of
|
||||
* `(int, int, double)` is 3.
|
||||
*/
|
||||
int getArity() { result = count(getAnElement()) }
|
||||
int getArity() { result = count(this.getAnElement()) }
|
||||
|
||||
language[monotonicAggregates]
|
||||
override string toStringWithTypes() {
|
||||
result =
|
||||
"(" +
|
||||
concat(Type t, int i | t = getElement(i).getType() | t.toStringWithTypes(), ", " order by i)
|
||||
+ ")"
|
||||
concat(Type t, int i |
|
||||
t = this.getElement(i).getType()
|
||||
|
|
||||
t.toStringWithTypes(), ", " order by i
|
||||
) + ")"
|
||||
}
|
||||
|
||||
language[monotonicAggregates]
|
||||
override string getName() {
|
||||
result =
|
||||
"(" + concat(Type t, int i | t = getElement(i).getType() | t.getName(), "," order by i) + ")"
|
||||
"(" + concat(Type t, int i | t = this.getElement(i).getType() | t.getName(), "," order by i) +
|
||||
")"
|
||||
}
|
||||
|
||||
override string getLabel() { result = getUnderlyingType().getLabel() }
|
||||
override string getLabel() { result = this.getUnderlyingType().getLabel() }
|
||||
|
||||
override Type getChild(int i) { result = this.getUnderlyingType().getChild(i) }
|
||||
|
||||
|
||||
@@ -297,7 +297,7 @@ module Gvn {
|
||||
or
|
||||
result =
|
||||
strictconcat(int i, int j |
|
||||
toStringPart(i, j)
|
||||
this.toStringPart(i, j)
|
||||
|
|
||||
this.toStringConstructedPart(i, j) order by i desc, j
|
||||
)
|
||||
|
||||
@@ -149,7 +149,7 @@ class Parameter extends DotNet::Parameter, LocalScopeVariable, Attributable, Top
|
||||
predicate isIn() { params(this, _, _, _, 5, _, _) }
|
||||
|
||||
/** Holds if this parameter is an output or reference parameter. */
|
||||
predicate isOutOrRef() { isOut() or isRef() }
|
||||
predicate isOutOrRef() { this.isOut() or this.isRef() }
|
||||
|
||||
/**
|
||||
* Holds if this parameter is a parameter array. For example, `args`
|
||||
@@ -210,7 +210,7 @@ class Parameter extends DotNet::Parameter, LocalScopeVariable, Attributable, Top
|
||||
Expr getDefaultValue() { result = this.getUnboundDeclaration().getChildExpr(0) }
|
||||
|
||||
/** Holds if this parameter has a default value. */
|
||||
predicate hasDefaultValue() { exists(getDefaultValue()) }
|
||||
predicate hasDefaultValue() { exists(this.getDefaultValue()) }
|
||||
|
||||
/** Gets the callable to which this parameter belongs, if any. */
|
||||
override Callable getCallable() { result = this.getDeclaringElement() }
|
||||
@@ -238,7 +238,9 @@ class Parameter extends DotNet::Parameter, LocalScopeVariable, Attributable, Top
|
||||
* `y` is `5`, and the assigned arguments to `z` are `3` and `6`, respectively.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
Expr getAnAssignedArgument() { result = getCallable().getACall().getArgumentForParameter(this) }
|
||||
Expr getAnAssignedArgument() {
|
||||
result = this.getCallable().getACall().getArgumentForParameter(this)
|
||||
}
|
||||
|
||||
/** Holds if this parameter is potentially overwritten in the body of its callable. */
|
||||
predicate isOverwritten() {
|
||||
@@ -323,7 +325,7 @@ class LocalVariable extends LocalScopeVariable, @local_variable {
|
||||
/** Gets the enclosing callable of this local variable. */
|
||||
Callable getEnclosingCallable() { result = this.getVariableDeclExpr().getEnclosingCallable() }
|
||||
|
||||
override Callable getCallable() { result = getEnclosingCallable() }
|
||||
override Callable getCallable() { result = this.getEnclosingCallable() }
|
||||
|
||||
override predicate isRef() { localvars(this, 3, _, _, _, _) }
|
||||
|
||||
|
||||
@@ -108,7 +108,7 @@ class XMLParent extends @xmlparent {
|
||||
}
|
||||
|
||||
/** Gets the text value contained in this XML parent. */
|
||||
string getTextValue() { result = allCharactersString() }
|
||||
string getTextValue() { result = this.allCharactersString() }
|
||||
|
||||
/** Gets a printable representation of this XML parent. */
|
||||
string toString() { result = this.getName() }
|
||||
@@ -119,7 +119,7 @@ class XMLFile extends XMLParent, File {
|
||||
XMLFile() { xmlEncoding(this, _) }
|
||||
|
||||
/** Gets a printable representation of this XML file. */
|
||||
override string toString() { result = getName() }
|
||||
override string toString() { result = this.getName() }
|
||||
|
||||
/** Gets the name of this XML file. */
|
||||
override string getName() { result = File.super.getAbsolutePath() }
|
||||
@@ -129,14 +129,14 @@ class XMLFile extends XMLParent, File {
|
||||
*
|
||||
* Gets the path of this XML file.
|
||||
*/
|
||||
deprecated string getPath() { result = getAbsolutePath() }
|
||||
deprecated string getPath() { result = this.getAbsolutePath() }
|
||||
|
||||
/**
|
||||
* DEPRECATED: Use `getParentContainer().getAbsolutePath()` instead.
|
||||
*
|
||||
* Gets the path of the folder that contains this XML file.
|
||||
*/
|
||||
deprecated string getFolder() { result = getParentContainer().getAbsolutePath() }
|
||||
deprecated string getFolder() { result = this.getParentContainer().getAbsolutePath() }
|
||||
|
||||
/** Gets the encoding of this XML file. */
|
||||
string getEncoding() { xmlEncoding(this, result) }
|
||||
@@ -200,7 +200,7 @@ class XMLDTD extends XMLLocatable, @xmldtd {
|
||||
*/
|
||||
class XMLElement extends @xmlelement, XMLParent, XMLLocatable {
|
||||
/** Holds if this XML element has the given `name`. */
|
||||
predicate hasName(string name) { name = getName() }
|
||||
predicate hasName(string name) { name = this.getName() }
|
||||
|
||||
/** Gets the name of this XML element. */
|
||||
override string getName() { xmlElements(this, result, _, _, _) }
|
||||
@@ -239,7 +239,7 @@ class XMLElement extends @xmlelement, XMLParent, XMLLocatable {
|
||||
string getAttributeValue(string name) { result = this.getAttribute(name).getValue() }
|
||||
|
||||
/** Gets a printable representation of this XML element. */
|
||||
override string toString() { result = getName() }
|
||||
override string toString() { result = this.getName() }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -42,7 +42,7 @@ abstract class AssertMethod extends Method {
|
||||
*
|
||||
* Gets the index of a parameter being asserted.
|
||||
*/
|
||||
deprecated final int getAssertionIndex() { result = getAnAssertionIndex() }
|
||||
deprecated final int getAssertionIndex() { result = this.getAnAssertionIndex() }
|
||||
|
||||
/** Gets the parameter at position `i` being asserted. */
|
||||
final Parameter getAssertedParameter(int i) {
|
||||
@@ -55,7 +55,7 @@ abstract class AssertMethod extends Method {
|
||||
*
|
||||
* Gets a parameter being asserted.
|
||||
*/
|
||||
deprecated final Parameter getAssertedParameter() { result = getAssertedParameter(_) }
|
||||
deprecated final Parameter getAssertedParameter() { result = this.getAssertedParameter(_) }
|
||||
|
||||
/** Gets the failure type if the assertion fails for argument `i`, if any. */
|
||||
abstract AssertionFailure getAssertionFailure(int i);
|
||||
|
||||
@@ -57,7 +57,7 @@ abstract class GeneratedCodeComment extends CommentLine { }
|
||||
*/
|
||||
class GenericGeneratedCodeComment extends GeneratedCodeComment {
|
||||
GenericGeneratedCodeComment() {
|
||||
exists(string line, string entity, string was, string automatically | line = getText() |
|
||||
exists(string line, string entity, string was, string automatically | line = this.getText() |
|
||||
entity = "file|class|interface|art[ei]fact|module|script" and
|
||||
was = "was|is|has been" and
|
||||
automatically = "automatically |mechanically |auto[- ]?" and
|
||||
@@ -70,7 +70,7 @@ class GenericGeneratedCodeComment extends GeneratedCodeComment {
|
||||
/** A comment warning against modifications. */
|
||||
class DontModifyMarkerComment extends GeneratedCodeComment {
|
||||
DontModifyMarkerComment() {
|
||||
exists(string line | line = getText() |
|
||||
exists(string line | line = this.getText() |
|
||||
line.regexpMatch("(?i).*\\bGenerated by\\b.*\\bDo not edit\\b.*") or
|
||||
line.regexpMatch("(?i).*\\bAny modifications to this file will be lost\\b.*")
|
||||
)
|
||||
|
||||
@@ -11,7 +11,7 @@ private import ControlFlow::SuccessorTypes
|
||||
*/
|
||||
class BasicBlock extends TBasicBlockStart {
|
||||
/** Gets an immediate successor of this basic block, if any. */
|
||||
BasicBlock getASuccessor() { result.getFirstNode() = getLastNode().getASuccessor() }
|
||||
BasicBlock getASuccessor() { result.getFirstNode() = this.getLastNode().getASuccessor() }
|
||||
|
||||
/** Gets an immediate successor of this basic block of a given type, if any. */
|
||||
BasicBlock getASuccessorByType(ControlFlow::SuccessorType t) {
|
||||
@@ -42,7 +42,7 @@ class BasicBlock extends TBasicBlockStart {
|
||||
* The basic block on line 2 is an immediate `true` successor of the
|
||||
* basic block on line 1.
|
||||
*/
|
||||
BasicBlock getATrueSuccessor() { result.getFirstNode() = getLastNode().getATrueSuccessor() }
|
||||
BasicBlock getATrueSuccessor() { result.getFirstNode() = this.getLastNode().getATrueSuccessor() }
|
||||
|
||||
/**
|
||||
* Gets an immediate `false` successor, if any.
|
||||
@@ -60,25 +60,27 @@ class BasicBlock extends TBasicBlockStart {
|
||||
* The basic block on line 2 is an immediate `false` successor of the
|
||||
* basic block on line 1.
|
||||
*/
|
||||
BasicBlock getAFalseSuccessor() { result.getFirstNode() = getLastNode().getAFalseSuccessor() }
|
||||
BasicBlock getAFalseSuccessor() {
|
||||
result.getFirstNode() = this.getLastNode().getAFalseSuccessor()
|
||||
}
|
||||
|
||||
/** Gets the control flow node at a specific (zero-indexed) position in this basic block. */
|
||||
ControlFlow::Node getNode(int pos) { bbIndex(getFirstNode(), result, pos) }
|
||||
ControlFlow::Node getNode(int pos) { bbIndex(this.getFirstNode(), result, pos) }
|
||||
|
||||
/** Gets a control flow node in this basic block. */
|
||||
ControlFlow::Node getANode() { result = getNode(_) }
|
||||
ControlFlow::Node getANode() { result = this.getNode(_) }
|
||||
|
||||
/** Gets the first control flow node in this basic block. */
|
||||
ControlFlow::Node getFirstNode() { this = TBasicBlockStart(result) }
|
||||
|
||||
/** Gets the last control flow node in this basic block. */
|
||||
ControlFlow::Node getLastNode() { result = getNode(length() - 1) }
|
||||
ControlFlow::Node getLastNode() { result = this.getNode(this.length() - 1) }
|
||||
|
||||
/** Gets the callable that this basic block belongs to. */
|
||||
final Callable getCallable() { result = this.getFirstNode().getEnclosingCallable() }
|
||||
|
||||
/** Gets the length of this basic block. */
|
||||
int length() { result = strictcount(getANode()) }
|
||||
int length() { result = strictcount(this.getANode()) }
|
||||
|
||||
/**
|
||||
* Holds if this basic block immediately dominates basic block `bb`.
|
||||
@@ -151,7 +153,7 @@ class BasicBlock extends TBasicBlockStart {
|
||||
*/
|
||||
predicate dominates(BasicBlock bb) {
|
||||
bb = this or
|
||||
strictlyDominates(bb)
|
||||
this.strictlyDominates(bb)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -177,14 +179,14 @@ class BasicBlock extends TBasicBlockStart {
|
||||
* does not dominate the basic block on line 6.
|
||||
*/
|
||||
predicate inDominanceFrontier(BasicBlock df) {
|
||||
dominatesPredecessor(df) and
|
||||
not strictlyDominates(df)
|
||||
this.dominatesPredecessor(df) and
|
||||
not this.strictlyDominates(df)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this basic block dominates a predecessor of `df`.
|
||||
*/
|
||||
private predicate dominatesPredecessor(BasicBlock df) { dominates(df.getAPredecessor()) }
|
||||
private predicate dominatesPredecessor(BasicBlock df) { this.dominates(df.getAPredecessor()) }
|
||||
|
||||
/**
|
||||
* Gets the basic block that immediately dominates this basic block, if any.
|
||||
@@ -263,7 +265,7 @@ class BasicBlock extends TBasicBlockStart {
|
||||
* post-dominates itself.
|
||||
*/
|
||||
predicate postDominates(BasicBlock bb) {
|
||||
strictlyPostDominates(bb) or
|
||||
this.strictlyPostDominates(bb) or
|
||||
this = bb
|
||||
}
|
||||
|
||||
@@ -276,10 +278,10 @@ class BasicBlock extends TBasicBlockStart {
|
||||
predicate inLoop() { this.getASuccessor+() = this }
|
||||
|
||||
/** Gets a textual representation of this basic block. */
|
||||
string toString() { result = getFirstNode().toString() }
|
||||
string toString() { result = this.getFirstNode().toString() }
|
||||
|
||||
/** Gets the location of this basic block. */
|
||||
Location getLocation() { result = getFirstNode().getLocation() }
|
||||
Location getLocation() { result = this.getFirstNode().getLocation() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -420,7 +422,7 @@ private module JoinBlockPredecessors {
|
||||
|
||||
/** A basic block with more than one predecessor. */
|
||||
class JoinBlock extends BasicBlock {
|
||||
JoinBlock() { getFirstNode().isJoin() }
|
||||
JoinBlock() { this.getFirstNode().isJoin() }
|
||||
|
||||
/**
|
||||
* Gets the `i`th predecessor of this join block, with respect to some
|
||||
|
||||
@@ -72,13 +72,14 @@ class ControlFlowElement extends ExprOrStmtParent, @control_flow_element {
|
||||
ControlFlowElement getAReachableElement() {
|
||||
// Reachable in same basic block
|
||||
exists(BasicBlock bb, int i, int j |
|
||||
bb.getNode(i) = getAControlFlowNode() and
|
||||
bb.getNode(i) = this.getAControlFlowNode() and
|
||||
bb.getNode(j) = result.getAControlFlowNode() and
|
||||
i < j
|
||||
)
|
||||
or
|
||||
// Reachable in different basic blocks
|
||||
getAControlFlowNode().getBasicBlock().getASuccessor+().getANode() = result.getAControlFlowNode()
|
||||
this.getAControlFlowNode().getBasicBlock().getASuccessor+().getANode() =
|
||||
result.getAControlFlowNode()
|
||||
}
|
||||
|
||||
pragma[noinline]
|
||||
|
||||
@@ -33,10 +33,10 @@ module ControlFlow {
|
||||
ControlFlowElement getElement() { none() }
|
||||
|
||||
/** Gets the location of this control flow node. */
|
||||
Location getLocation() { result = getElement().getLocation() }
|
||||
Location getLocation() { result = this.getElement().getLocation() }
|
||||
|
||||
/** Holds if this control flow node has conditional successors. */
|
||||
predicate isCondition() { exists(getASuccessorByType(any(ConditionalSuccessor e))) }
|
||||
predicate isCondition() { exists(this.getASuccessorByType(any(ConditionalSuccessor e))) }
|
||||
|
||||
/** Gets the basic block that this control flow node belongs to. */
|
||||
BasicBlock getBasicBlock() { result.getANode() = this }
|
||||
@@ -67,7 +67,7 @@ module ControlFlow {
|
||||
// potentially very large predicate, so must be inlined
|
||||
pragma[inline]
|
||||
predicate dominates(Node that) {
|
||||
strictlyDominates(that)
|
||||
this.strictlyDominates(that)
|
||||
or
|
||||
this = that
|
||||
}
|
||||
@@ -138,7 +138,7 @@ module ControlFlow {
|
||||
// potentially very large predicate, so must be inlined
|
||||
pragma[inline]
|
||||
predicate postDominates(Node that) {
|
||||
strictlyPostDominates(that)
|
||||
this.strictlyPostDominates(that)
|
||||
or
|
||||
this = that
|
||||
}
|
||||
@@ -186,13 +186,13 @@ module ControlFlow {
|
||||
Node getASuccessorByType(SuccessorType t) { result = getASuccessor(this, t) }
|
||||
|
||||
/** Gets an immediate successor, if any. */
|
||||
Node getASuccessor() { result = getASuccessorByType(_) }
|
||||
Node getASuccessor() { result = this.getASuccessorByType(_) }
|
||||
|
||||
/** Gets an immediate predecessor node of a given flow type, if any. */
|
||||
Node getAPredecessorByType(SuccessorType t) { result.getASuccessorByType(t) = this }
|
||||
|
||||
/** Gets an immediate predecessor, if any. */
|
||||
Node getAPredecessor() { result = getAPredecessorByType(_) }
|
||||
Node getAPredecessor() { result = this.getAPredecessorByType(_) }
|
||||
|
||||
/**
|
||||
* Gets an immediate `true` successor, if any.
|
||||
@@ -211,7 +211,7 @@ module ControlFlow {
|
||||
* on line 1.
|
||||
*/
|
||||
Node getATrueSuccessor() {
|
||||
result = getASuccessorByType(any(BooleanSuccessor t | t.getValue() = true))
|
||||
result = this.getASuccessorByType(any(BooleanSuccessor t | t.getValue() = true))
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -231,7 +231,7 @@ module ControlFlow {
|
||||
* on line 1.
|
||||
*/
|
||||
Node getAFalseSuccessor() {
|
||||
result = getASuccessorByType(any(BooleanSuccessor t | t.getValue() = false))
|
||||
result = this.getASuccessorByType(any(BooleanSuccessor t | t.getValue() = false))
|
||||
}
|
||||
|
||||
/** Holds if this node has more than one predecessor. */
|
||||
@@ -285,7 +285,7 @@ module ControlFlow {
|
||||
|
||||
override Callable getEnclosingCallable() { result = this.getCallable() }
|
||||
|
||||
override Location getLocation() { result = getCallable().getLocation() }
|
||||
override Location getLocation() { result = this.getCallable().getLocation() }
|
||||
|
||||
override string toString() {
|
||||
exists(string s |
|
||||
@@ -293,7 +293,7 @@ module ControlFlow {
|
||||
or
|
||||
normal = false and s = "abnormal"
|
||||
|
|
||||
result = "exit " + getCallable() + " (" + s + ")"
|
||||
result = "exit " + this.getCallable() + " (" + s + ")"
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -307,9 +307,9 @@ module ControlFlow {
|
||||
|
||||
override Callable getEnclosingCallable() { result = this.getCallable() }
|
||||
|
||||
override Location getLocation() { result = getCallable().getLocation() }
|
||||
override Location getLocation() { result = this.getCallable().getLocation() }
|
||||
|
||||
override string toString() { result = "exit " + getCallable().toString() }
|
||||
override string toString() { result = "exit " + this.getCallable().toString() }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1740,7 +1740,7 @@ module Internal {
|
||||
e = this.getAChildExpr()
|
||||
or
|
||||
exists(Expr mid |
|
||||
descendant(mid) and
|
||||
this.descendant(mid) and
|
||||
not interestingDescendantCandidate(mid) and
|
||||
e = mid.getAChildExpr()
|
||||
)
|
||||
@@ -1748,7 +1748,7 @@ module Internal {
|
||||
|
||||
/** Holds if `e` is an interesting descendant of this descendant. */
|
||||
predicate interestingDescendant(Expr e) {
|
||||
descendant(e) and
|
||||
this.descendant(e) and
|
||||
interestingDescendantCandidate(e)
|
||||
}
|
||||
}
|
||||
@@ -1797,7 +1797,7 @@ module Internal {
|
||||
|
||||
override predicate candidate(ControlFlowElement x, ControlFlowElement y) {
|
||||
exists(BasicBlock bb, Declaration d |
|
||||
candidateAux(x, d, bb) and
|
||||
this.candidateAux(x, d, bb) and
|
||||
y =
|
||||
any(AccessOrCallExpr e |
|
||||
e.getAControlFlowNode().getBasicBlock() = bb and
|
||||
|
||||
@@ -495,7 +495,7 @@ module Expressions {
|
||||
// Flow from last element of left operand to first element of right operand
|
||||
last(this.getLeftOperand(), pred, c) and
|
||||
c.(NullnessCompletion).isNull() and
|
||||
first(getRightOperand(), succ)
|
||||
first(this.getRightOperand(), succ)
|
||||
or
|
||||
// Post-order: flow from last element of left operand to element itself
|
||||
last(this.getLeftOperand(), pred, c) and
|
||||
@@ -504,7 +504,7 @@ module Expressions {
|
||||
not c.(NullnessCompletion).isNull()
|
||||
or
|
||||
// Post-order: flow from last element of right operand to element itself
|
||||
last(getRightOperand(), pred, c) and
|
||||
last(this.getRightOperand(), pred, c) and
|
||||
c instanceof NormalCompletion and
|
||||
succ = this
|
||||
}
|
||||
@@ -575,7 +575,7 @@ module Expressions {
|
||||
PostOrderTree.super.last(last, c)
|
||||
or
|
||||
// Qualifier exits with a `null` completion
|
||||
lastQualifier(last, c) and
|
||||
this.lastQualifier(last, c) and
|
||||
c.(NullnessCompletion).isNull()
|
||||
}
|
||||
|
||||
@@ -1483,7 +1483,7 @@ module Statements {
|
||||
)
|
||||
or
|
||||
// Flow into `finally` block
|
||||
pred = getAFinallyPredecessor(c, true) and
|
||||
pred = this.getAFinallyPredecessor(c, true) and
|
||||
first(this.getFinally(), succ)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -69,9 +69,9 @@ class PreBasicBlock extends ControlFlowElement {
|
||||
|
||||
ControlFlowElement getFirstElement() { result = this }
|
||||
|
||||
ControlFlowElement getLastElement() { result = this.getElement(length() - 1) }
|
||||
ControlFlowElement getLastElement() { result = this.getElement(this.length() - 1) }
|
||||
|
||||
int length() { result = strictcount(getAnElement()) }
|
||||
int length() { result = strictcount(this.getAnElement()) }
|
||||
|
||||
predicate immediatelyDominates(PreBasicBlock bb) { bbIDominates(this, bb) }
|
||||
|
||||
@@ -117,7 +117,7 @@ class ConditionBlock extends PreBasicBlock {
|
||||
|
||||
pragma[nomagic]
|
||||
predicate controls(PreBasicBlock controlled, SuccessorTypes::ConditionalSuccessor s) {
|
||||
exists(PreBasicBlock succ, ConditionalCompletion c | immediatelyControls(succ, c) |
|
||||
exists(PreBasicBlock succ, ConditionalCompletion c | this.immediatelyControls(succ, c) |
|
||||
succ.dominates(controlled) and
|
||||
s = c.getAMatchingSuccessorType()
|
||||
)
|
||||
|
||||
@@ -628,7 +628,7 @@ module FinallySplitting {
|
||||
*/
|
||||
private predicate exit(ControlFlowElement pred, Completion c, boolean inherited) {
|
||||
exists(TryStmt try, FinallySplitType type |
|
||||
exit0(pred, try, this.getNestLevel(), c) and
|
||||
this.exit0(pred, try, this.getNestLevel(), c) and
|
||||
type = this.getType()
|
||||
|
|
||||
if last(try.getFinally(), pred, c)
|
||||
@@ -690,18 +690,18 @@ module FinallySplitting {
|
||||
override predicate hasExit(ControlFlowElement pred, ControlFlowElement succ, Completion c) {
|
||||
succ(pred, succ, c) and
|
||||
(
|
||||
exit(pred, c, _)
|
||||
this.exit(pred, c, _)
|
||||
or
|
||||
exit(pred, c.(NestedBreakCompletion).getAnInnerCompatibleCompletion(), _)
|
||||
this.exit(pred, c.(NestedBreakCompletion).getAnInnerCompatibleCompletion(), _)
|
||||
)
|
||||
}
|
||||
|
||||
override predicate hasExitScope(CfgScope scope, ControlFlowElement last, Completion c) {
|
||||
scopeLast(scope, last, c) and
|
||||
(
|
||||
exit(last, c, _)
|
||||
this.exit(last, c, _)
|
||||
or
|
||||
exit(last, c.(NestedBreakCompletion).getAnInnerCompatibleCompletion(), _)
|
||||
this.exit(last, c.(NestedBreakCompletion).getAnInnerCompatibleCompletion(), _)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -77,7 +77,7 @@ module SuccessorTypes {
|
||||
class BooleanSuccessor extends ConditionalSuccessor, TBooleanSuccessor {
|
||||
override boolean getValue() { this = TBooleanSuccessor(result) }
|
||||
|
||||
override string toString() { result = getValue().toString() }
|
||||
override string toString() { result = this.getValue().toString() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -310,7 +310,7 @@ module SuccessorTypes {
|
||||
/** Gets the type of exception. */
|
||||
ExceptionClass getExceptionClass() { this = TExceptionSuccessor(result) }
|
||||
|
||||
override string toString() { result = "exception(" + getExceptionClass().getName() + ")" }
|
||||
override string toString() { result = "exception(" + this.getExceptionClass().getName() + ")" }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -404,6 +404,7 @@ private string paramsString(InterpretedCallable c) {
|
||||
)
|
||||
}
|
||||
|
||||
pragma[nomagic]
|
||||
private Element interpretElement0(
|
||||
string namespace, string type, boolean subtypes, string name, string signature
|
||||
) {
|
||||
|
||||
@@ -505,20 +505,20 @@ class SystemBooleanFlow extends LibraryTypeDataFlow, SystemBooleanStruct {
|
||||
CallableFlowSource source, CallableFlowSink sink, SourceDeclarationCallable c,
|
||||
boolean preservesValue
|
||||
) {
|
||||
methodFlow(source, sink, c) and
|
||||
this.methodFlow(source, sink, c) and
|
||||
preservesValue = false
|
||||
}
|
||||
|
||||
private predicate methodFlow(
|
||||
CallableFlowSource source, CallableFlowSink sink, SourceDeclarationMethod m
|
||||
) {
|
||||
m = getParseMethod() and
|
||||
m = this.getParseMethod() and
|
||||
(
|
||||
source = TCallableFlowSourceArg(0) and
|
||||
sink = TCallableFlowSinkReturn()
|
||||
)
|
||||
or
|
||||
m = getTryParseMethod() and
|
||||
m = this.getTryParseMethod() and
|
||||
(
|
||||
source = TCallableFlowSourceArg(0) and
|
||||
(
|
||||
@@ -537,12 +537,12 @@ class SystemUriFlow extends LibraryTypeDataFlow, SystemUriClass {
|
||||
boolean preservesValue
|
||||
) {
|
||||
(
|
||||
constructorFlow(source, sink, c)
|
||||
this.constructorFlow(source, sink, c)
|
||||
or
|
||||
methodFlow(source, sink, c)
|
||||
this.methodFlow(source, sink, c)
|
||||
or
|
||||
exists(Property p |
|
||||
propertyFlow(p) and
|
||||
this.propertyFlow(p) and
|
||||
source = TCallableFlowSourceQualifier() and
|
||||
sink = TCallableFlowSinkReturn() and
|
||||
c = p.getGetter()
|
||||
@@ -552,7 +552,7 @@ class SystemUriFlow extends LibraryTypeDataFlow, SystemUriClass {
|
||||
}
|
||||
|
||||
private predicate constructorFlow(CallableFlowSource source, CallableFlowSink sink, Constructor c) {
|
||||
c = getAMember() and
|
||||
c = this.getAMember() and
|
||||
c.getParameter(0).getType() instanceof StringType and
|
||||
source = TCallableFlowSourceArg(0) and
|
||||
sink = TCallableFlowSinkReturn()
|
||||
@@ -567,11 +567,11 @@ class SystemUriFlow extends LibraryTypeDataFlow, SystemUriClass {
|
||||
}
|
||||
|
||||
private predicate propertyFlow(Property p) {
|
||||
p = getPathAndQueryProperty()
|
||||
p = this.getPathAndQueryProperty()
|
||||
or
|
||||
p = getQueryProperty()
|
||||
p = this.getQueryProperty()
|
||||
or
|
||||
p = getOriginalStringProperty()
|
||||
p = this.getOriginalStringProperty()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -582,15 +582,15 @@ class SystemIOStringReaderFlow extends LibraryTypeDataFlow, SystemIOStringReader
|
||||
boolean preservesValue
|
||||
) {
|
||||
(
|
||||
constructorFlow(source, sink, c)
|
||||
this.constructorFlow(source, sink, c)
|
||||
or
|
||||
methodFlow(source, sink, c)
|
||||
this.methodFlow(source, sink, c)
|
||||
) and
|
||||
preservesValue = false
|
||||
}
|
||||
|
||||
private predicate constructorFlow(CallableFlowSource source, CallableFlowSink sink, Constructor c) {
|
||||
c = getAMember() and
|
||||
c = this.getAMember() and
|
||||
c.getParameter(0).getType() instanceof StringType and
|
||||
source = TCallableFlowSourceArg(0) and
|
||||
sink = TCallableFlowSinkReturn()
|
||||
@@ -599,7 +599,7 @@ class SystemIOStringReaderFlow extends LibraryTypeDataFlow, SystemIOStringReader
|
||||
private predicate methodFlow(
|
||||
CallableFlowSource source, CallableFlowSink sink, SourceDeclarationMethod m
|
||||
) {
|
||||
m.getDeclaringType() = getABaseType*() and
|
||||
m.getDeclaringType() = this.getABaseType*() and
|
||||
m.getName().matches("Read%") and
|
||||
source = TCallableFlowSourceQualifier() and
|
||||
sink = TCallableFlowSinkReturn()
|
||||
@@ -612,17 +612,17 @@ class SystemStringFlow extends LibraryTypeDataFlow, SystemStringClass {
|
||||
CallableFlowSource source, AccessPath sourceAp, CallableFlowSink sink, AccessPath sinkAp,
|
||||
SourceDeclarationCallable c, boolean preservesValue
|
||||
) {
|
||||
constructorFlow(source, sourceAp, sink, sinkAp, c) and
|
||||
this.constructorFlow(source, sourceAp, sink, sinkAp, c) and
|
||||
preservesValue = false
|
||||
or
|
||||
methodFlow(source, sourceAp, sink, sinkAp, c, preservesValue)
|
||||
this.methodFlow(source, sourceAp, sink, sinkAp, c, preservesValue)
|
||||
}
|
||||
|
||||
private predicate constructorFlow(
|
||||
CallableFlowSource source, AccessPath sourceAp, CallableFlowSink sink, AccessPath sinkAp,
|
||||
Constructor c
|
||||
) {
|
||||
c = getAMember() and
|
||||
c = this.getAMember() and
|
||||
c.getParameter(0).getType().(ArrayType).getElementType() instanceof CharType and
|
||||
source = TCallableFlowSourceArg(0) and
|
||||
sourceAp = AccessPath::element() and
|
||||
@@ -641,14 +641,14 @@ class SystemStringFlow extends LibraryTypeDataFlow, SystemStringClass {
|
||||
sinkAp = AccessPath::empty() and
|
||||
preservesValue = true
|
||||
or
|
||||
m = getSplitMethod() and
|
||||
m = this.getSplitMethod() and
|
||||
source = TCallableFlowSourceQualifier() and
|
||||
sourceAp = AccessPath::empty() and
|
||||
sink = TCallableFlowSinkReturn() and
|
||||
sinkAp = AccessPath::element() and
|
||||
preservesValue = false
|
||||
or
|
||||
m = getReplaceMethod() and
|
||||
m = this.getReplaceMethod() and
|
||||
sourceAp = AccessPath::empty() and
|
||||
sinkAp = AccessPath::empty() and
|
||||
(
|
||||
@@ -661,21 +661,21 @@ class SystemStringFlow extends LibraryTypeDataFlow, SystemStringClass {
|
||||
preservesValue = false
|
||||
)
|
||||
or
|
||||
m = getSubstringMethod() and
|
||||
m = this.getSubstringMethod() and
|
||||
source = TCallableFlowSourceQualifier() and
|
||||
sourceAp = AccessPath::empty() and
|
||||
sink = TCallableFlowSinkReturn() and
|
||||
sinkAp = AccessPath::empty() and
|
||||
preservesValue = false
|
||||
or
|
||||
m = getCloneMethod() and
|
||||
m = this.getCloneMethod() and
|
||||
source = TCallableFlowSourceQualifier() and
|
||||
sourceAp = AccessPath::empty() and
|
||||
sink = TCallableFlowSinkReturn() and
|
||||
sinkAp = AccessPath::empty() and
|
||||
preservesValue = true
|
||||
or
|
||||
m = getInsertMethod() and
|
||||
m = this.getInsertMethod() and
|
||||
sourceAp = AccessPath::empty() and
|
||||
sinkAp = AccessPath::empty() and
|
||||
(
|
||||
@@ -688,21 +688,21 @@ class SystemStringFlow extends LibraryTypeDataFlow, SystemStringClass {
|
||||
preservesValue = false
|
||||
)
|
||||
or
|
||||
m = getNormalizeMethod() and
|
||||
m = this.getNormalizeMethod() and
|
||||
source = TCallableFlowSourceQualifier() and
|
||||
sourceAp = AccessPath::empty() and
|
||||
sink = TCallableFlowSinkReturn() and
|
||||
sinkAp = AccessPath::empty() and
|
||||
preservesValue = false
|
||||
or
|
||||
m = getRemoveMethod() and
|
||||
m = this.getRemoveMethod() and
|
||||
source = TCallableFlowSourceQualifier() and
|
||||
sourceAp = AccessPath::empty() and
|
||||
sink = TCallableFlowSinkReturn() and
|
||||
sinkAp = AccessPath::empty() and
|
||||
preservesValue = false
|
||||
or
|
||||
m = getAMethod() and
|
||||
m = this.getAMethod() and
|
||||
m.getName().regexpMatch("((ToLower|ToUpper)(Invariant)?)|(Trim(Start|End)?)|(Pad(Left|Right))") and
|
||||
source = TCallableFlowSourceQualifier() and
|
||||
sourceAp = AccessPath::empty() and
|
||||
@@ -710,7 +710,7 @@ class SystemStringFlow extends LibraryTypeDataFlow, SystemStringClass {
|
||||
sinkAp = AccessPath::empty() and
|
||||
preservesValue = false
|
||||
or
|
||||
m = getConcatMethod() and
|
||||
m = this.getConcatMethod() and
|
||||
exists(int i |
|
||||
source = getFlowSourceArg(m, i, sourceAp) and
|
||||
sink = TCallableFlowSinkReturn() and
|
||||
@@ -718,20 +718,20 @@ class SystemStringFlow extends LibraryTypeDataFlow, SystemStringClass {
|
||||
preservesValue = false
|
||||
)
|
||||
or
|
||||
m = getCopyMethod() and
|
||||
m = this.getCopyMethod() and
|
||||
source = TCallableFlowSourceArg(0) and
|
||||
sourceAp = AccessPath::empty() and
|
||||
sink = TCallableFlowSinkReturn() and
|
||||
sinkAp = AccessPath::empty() and
|
||||
preservesValue = true
|
||||
or
|
||||
m = getJoinMethod() and
|
||||
m = this.getJoinMethod() and
|
||||
source = getFlowSourceArg(m, [0, 1], sourceAp) and
|
||||
sink = TCallableFlowSinkReturn() and
|
||||
sinkAp = AccessPath::empty() and
|
||||
preservesValue = false
|
||||
or
|
||||
m = getFormatMethod() and
|
||||
m = this.getFormatMethod() and
|
||||
exists(int i |
|
||||
(m.getParameter(0).getType() instanceof SystemIFormatProviderInterface implies i != 0) and
|
||||
source = getFlowSourceArg(m, i, sourceAp) and
|
||||
@@ -749,10 +749,10 @@ class SystemTextStringBuilderFlow extends LibraryTypeDataFlow, SystemTextStringB
|
||||
SourceDeclarationCallable c, boolean preservesValue
|
||||
) {
|
||||
(
|
||||
constructorFlow(source, sourceAp, sink, sinkAp, c) and
|
||||
this.constructorFlow(source, sourceAp, sink, sinkAp, c) and
|
||||
preservesValue = true
|
||||
or
|
||||
methodFlow(source, sourceAp, sink, sinkAp, c, preservesValue)
|
||||
this.methodFlow(source, sourceAp, sink, sinkAp, c, preservesValue)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -760,7 +760,7 @@ class SystemTextStringBuilderFlow extends LibraryTypeDataFlow, SystemTextStringB
|
||||
CallableFlowSource source, AccessPath sourceAp, CallableFlowSink sink, AccessPath sinkAp,
|
||||
Constructor c
|
||||
) {
|
||||
c = getAMember() and
|
||||
c = this.getAMember() and
|
||||
c.getParameter(0).getType() instanceof StringType and
|
||||
source = TCallableFlowSourceArg(0) and
|
||||
sourceAp = AccessPath::empty() and
|
||||
@@ -894,7 +894,7 @@ class IEnumerableFlow extends LibraryTypeDataFlow, RefType {
|
||||
) {
|
||||
preservesValue = true and
|
||||
(
|
||||
methodFlowLINQExtensions(source, sourceAp, sink, sinkAp, c)
|
||||
this.methodFlowLINQExtensions(source, sourceAp, sink, sinkAp, c)
|
||||
or
|
||||
c = this.getFind() and
|
||||
sourceAp = AccessPath::element() and
|
||||
@@ -1674,14 +1674,14 @@ class SystemConvertFlow extends LibraryTypeDataFlow, SystemConvertClass {
|
||||
CallableFlowSource source, CallableFlowSink sink, SourceDeclarationCallable c,
|
||||
boolean preservesValue
|
||||
) {
|
||||
methodFlow(source, sink, c) and
|
||||
this.methodFlow(source, sink, c) and
|
||||
preservesValue = false
|
||||
}
|
||||
|
||||
private predicate methodFlow(
|
||||
CallableFlowSource source, CallableFlowSink sink, SourceDeclarationMethod m
|
||||
) {
|
||||
m = getAMethod() and
|
||||
m = this.getAMethod() and
|
||||
source = TCallableFlowSourceArg(0) and
|
||||
sink = TCallableFlowSinkReturn()
|
||||
}
|
||||
@@ -1694,7 +1694,7 @@ class SystemWebHttpCookieFlow extends LibraryTypeDataFlow, SystemWebHttpCookie {
|
||||
boolean preservesValue
|
||||
) {
|
||||
exists(Property p |
|
||||
propertyFlow(p) and
|
||||
this.propertyFlow(p) and
|
||||
source = TCallableFlowSourceQualifier() and
|
||||
sink = TCallableFlowSinkReturn() and
|
||||
c = p.getGetter()
|
||||
@@ -1703,8 +1703,8 @@ class SystemWebHttpCookieFlow extends LibraryTypeDataFlow, SystemWebHttpCookie {
|
||||
}
|
||||
|
||||
private predicate propertyFlow(Property p) {
|
||||
p = getValueProperty() or
|
||||
p = getValuesProperty()
|
||||
p = this.getValueProperty() or
|
||||
p = this.getValuesProperty()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1715,7 +1715,7 @@ class SystemNetCookieFlow extends LibraryTypeDataFlow, SystemNetCookieClass {
|
||||
boolean preservesValue
|
||||
) {
|
||||
exists(Property p |
|
||||
propertyFlow(p) and
|
||||
this.propertyFlow(p) and
|
||||
source = TCallableFlowSourceQualifier() and
|
||||
sink = TCallableFlowSinkReturn() and
|
||||
c = p.getGetter()
|
||||
@@ -1733,7 +1733,7 @@ class SystemNetIPHostEntryFlow extends LibraryTypeDataFlow, SystemNetIPHostEntry
|
||||
boolean preservesValue
|
||||
) {
|
||||
exists(Property p |
|
||||
propertyFlow(p) and
|
||||
this.propertyFlow(p) and
|
||||
source = TCallableFlowSourceQualifier() and
|
||||
sink = TCallableFlowSinkReturn() and
|
||||
c = p.getGetter()
|
||||
@@ -1742,8 +1742,8 @@ class SystemNetIPHostEntryFlow extends LibraryTypeDataFlow, SystemNetIPHostEntry
|
||||
}
|
||||
|
||||
private predicate propertyFlow(Property p) {
|
||||
p = getHostNameProperty() or
|
||||
p = getAliasesProperty()
|
||||
p = this.getHostNameProperty() or
|
||||
p = this.getAliasesProperty()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1755,7 +1755,7 @@ class SystemWebUIWebControlsTextBoxFlow extends LibraryTypeDataFlow,
|
||||
boolean preservesValue
|
||||
) {
|
||||
exists(Property p |
|
||||
propertyFlow(p) and
|
||||
this.propertyFlow(p) and
|
||||
source = TCallableFlowSourceQualifier() and
|
||||
sink = TCallableFlowSinkReturn() and
|
||||
c = p.getGetter()
|
||||
@@ -1763,7 +1763,7 @@ class SystemWebUIWebControlsTextBoxFlow extends LibraryTypeDataFlow,
|
||||
preservesValue = false
|
||||
}
|
||||
|
||||
private predicate propertyFlow(Property p) { p = getTextProperty() }
|
||||
private predicate propertyFlow(Property p) { p = this.getTextProperty() }
|
||||
}
|
||||
|
||||
/** Data flow for `System.Collections.Generic.KeyValuePair`. */
|
||||
@@ -1864,11 +1864,11 @@ class SystemThreadingTasksTaskFlow extends LibraryTypeDataFlow, SystemThreadingT
|
||||
SourceDeclarationCallable c, boolean preservesValue
|
||||
) {
|
||||
(
|
||||
constructorFlow(source, sink, c) and
|
||||
this.constructorFlow(source, sink, c) and
|
||||
sourceAp = AccessPath::empty() and
|
||||
sinkAp = AccessPath::empty()
|
||||
or
|
||||
methodFlow(source, sourceAp, sink, sinkAp, c)
|
||||
this.methodFlow(source, sourceAp, sink, sinkAp, c)
|
||||
) and
|
||||
preservesValue = true
|
||||
}
|
||||
@@ -1954,9 +1954,9 @@ class SystemThreadingTasksTaskTFlow extends LibraryTypeDataFlow, SystemThreading
|
||||
SourceDeclarationCallable c, boolean preservesValue
|
||||
) {
|
||||
(
|
||||
constructorFlow(source, sourceAp, sink, sinkAp, c)
|
||||
this.constructorFlow(source, sourceAp, sink, sinkAp, c)
|
||||
or
|
||||
methodFlow(source, sourceAp, sink, sinkAp, c)
|
||||
this.methodFlow(source, sourceAp, sink, sinkAp, c)
|
||||
) and
|
||||
preservesValue = true
|
||||
or
|
||||
@@ -2101,14 +2101,14 @@ private class SystemRuntimeCompilerServicesConfiguredTaskAwaitableTFlow extends
|
||||
class SystemThreadingTasksFactoryFlow extends LibraryTypeDataFlow {
|
||||
SystemThreadingTasksFactoryFlow() {
|
||||
this instanceof SystemThreadingTasksClass and
|
||||
getName().regexpMatch("TaskFactory(<>)?")
|
||||
this.getName().regexpMatch("TaskFactory(<>)?")
|
||||
}
|
||||
|
||||
override predicate callableFlow(
|
||||
CallableFlowSource source, AccessPath sourceAp, CallableFlowSink sink, AccessPath sinkAp,
|
||||
SourceDeclarationCallable c, boolean preservesValue
|
||||
) {
|
||||
methodFlow(source, sourceAp, sink, sinkAp, c) and
|
||||
this.methodFlow(source, sourceAp, sink, sinkAp, c) and
|
||||
preservesValue = true
|
||||
}
|
||||
|
||||
@@ -2236,12 +2236,12 @@ library class SystemTextEncodingFlow extends LibraryTypeDataFlow, SystemTextEnco
|
||||
preservesValue = false and
|
||||
c = this.getAMethod() and
|
||||
exists(Method m | m.getAnOverrider*().getUnboundDeclaration() = c |
|
||||
m = getGetBytesMethod() and
|
||||
m = this.getGetBytesMethod() and
|
||||
source = getFlowSourceArg(m, 0, sourceAp) and
|
||||
sink = TCallableFlowSinkReturn() and
|
||||
sinkAp = AccessPath::empty()
|
||||
or
|
||||
m = [getGetStringMethod(), getGetCharsMethod()] and
|
||||
m = [this.getGetStringMethod(), this.getGetCharsMethod()] and
|
||||
source = TCallableFlowSourceArg(0) and
|
||||
sourceAp = AccessPath::element() and
|
||||
sink = TCallableFlowSinkReturn() and
|
||||
@@ -2257,9 +2257,9 @@ library class SystemIOMemoryStreamFlow extends LibraryTypeDataFlow, SystemIOMemo
|
||||
boolean preservesValue
|
||||
) {
|
||||
(
|
||||
constructorFlow(source, sink, c)
|
||||
this.constructorFlow(source, sink, c)
|
||||
or
|
||||
c = getToArrayMethod().getAnOverrider*() and
|
||||
c = this.getToArrayMethod().getAnOverrider*() and
|
||||
source = TCallableFlowSourceQualifier() and
|
||||
sink = TCallableFlowSinkReturn()
|
||||
) and
|
||||
@@ -2267,7 +2267,7 @@ library class SystemIOMemoryStreamFlow extends LibraryTypeDataFlow, SystemIOMemo
|
||||
}
|
||||
|
||||
private predicate constructorFlow(CallableFlowSource source, CallableFlowSink sink, Constructor c) {
|
||||
c = getAMember() and
|
||||
c = this.getAMember() and
|
||||
c.getParameter(0).getType().(ArrayType).getElementType() instanceof ByteType and
|
||||
source = TCallableFlowSourceArg(0) and
|
||||
sink = TCallableFlowSinkReturn()
|
||||
@@ -2281,17 +2281,17 @@ class SystemIOStreamFlow extends LibraryTypeDataFlow, SystemIOStreamClass {
|
||||
boolean preservesValue
|
||||
) {
|
||||
(
|
||||
c = getAReadMethod().getAnOverrider*() and
|
||||
c = this.getAReadMethod().getAnOverrider*() and
|
||||
c.getParameter(0).getType().(ArrayType).getElementType() instanceof ByteType and
|
||||
sink = TCallableFlowSinkArg(0) and
|
||||
source = TCallableFlowSourceQualifier()
|
||||
or
|
||||
c = getAWriteMethod().getAnOverrider*() and
|
||||
c = this.getAWriteMethod().getAnOverrider*() and
|
||||
c.getParameter(0).getType().(ArrayType).getElementType() instanceof ByteType and
|
||||
source = TCallableFlowSourceArg(0) and
|
||||
sink = TCallableFlowSinkQualifier()
|
||||
or
|
||||
c = any(Method m | m = getAMethod() and m.getName().matches("CopyTo%")).getAnOverrider*() and
|
||||
c = any(Method m | m = this.getAMethod() and m.getName().matches("CopyTo%")).getAnOverrider*() and
|
||||
c.getParameter(0).getType() instanceof SystemIOStreamClass and
|
||||
source = TCallableFlowSourceQualifier() and
|
||||
sink = TCallableFlowSinkArg(0)
|
||||
@@ -2307,12 +2307,12 @@ class SystemIOCompressionDeflateStreamFlow extends LibraryTypeDataFlow,
|
||||
CallableFlowSource source, CallableFlowSink sink, SourceDeclarationCallable c,
|
||||
boolean preservesValue
|
||||
) {
|
||||
constructorFlow(source, sink, c) and
|
||||
this.constructorFlow(source, sink, c) and
|
||||
preservesValue = false
|
||||
}
|
||||
|
||||
private predicate constructorFlow(CallableFlowSource source, CallableFlowSink sink, Constructor c) {
|
||||
c = getAMember() and
|
||||
c = this.getAMember() and
|
||||
source = TCallableFlowSourceArg(0) and
|
||||
sink = TCallableFlowSinkReturn()
|
||||
}
|
||||
@@ -2324,7 +2324,7 @@ class SystemXmlXmlReaderFlow extends LibraryTypeDataFlow, SystemXmlXmlReaderClas
|
||||
CallableFlowSource source, CallableFlowSink sink, SourceDeclarationCallable c,
|
||||
boolean preservesValue
|
||||
) {
|
||||
c = getCreateMethod() and
|
||||
c = this.getCreateMethod() and
|
||||
source = TCallableFlowSourceArg(0) and
|
||||
sink = TCallableFlowSinkReturn() and
|
||||
preservesValue = false
|
||||
@@ -2337,7 +2337,7 @@ class SystemXmlXmlDocumentFlow extends LibraryTypeDataFlow, SystemXmlXmlDocument
|
||||
CallableFlowSource source, CallableFlowSink sink, SourceDeclarationCallable c,
|
||||
boolean preservesValue
|
||||
) {
|
||||
c = getLoadMethod() and
|
||||
c = this.getLoadMethod() and
|
||||
source = TCallableFlowSourceArg(0) and
|
||||
sink = TCallableFlowSinkQualifier() and
|
||||
preservesValue = false
|
||||
@@ -2352,13 +2352,13 @@ class SystemXmlXmlNodeFlow extends LibraryTypeDataFlow, SystemXmlXmlNodeClass {
|
||||
) {
|
||||
(
|
||||
exists(Property p |
|
||||
p = getAProperty() and
|
||||
p = this.getAProperty() and
|
||||
c = p.getGetter() and
|
||||
source = TCallableFlowSourceQualifier() and
|
||||
sink = TCallableFlowSinkReturn()
|
||||
)
|
||||
or
|
||||
c = getASelectNodeMethod() and
|
||||
c = this.getASelectNodeMethod() and
|
||||
source = TCallableFlowSourceQualifier() and
|
||||
sink = TCallableFlowSinkReturn()
|
||||
) and
|
||||
@@ -2372,7 +2372,7 @@ class SystemXmlXmlNamedNodeMapFlow extends LibraryTypeDataFlow, SystemXmlXmlName
|
||||
CallableFlowSource source, CallableFlowSink sink, SourceDeclarationCallable c,
|
||||
boolean preservesValue
|
||||
) {
|
||||
c = getGetNamedItemMethod() and
|
||||
c = this.getGetNamedItemMethod() and
|
||||
source = TCallableFlowSourceQualifier() and
|
||||
sink = TCallableFlowSinkReturn() and
|
||||
preservesValue = true
|
||||
@@ -2385,14 +2385,14 @@ class SystemIOPathFlow extends LibraryTypeDataFlow, SystemIOPathClass {
|
||||
CallableFlowSource source, AccessPath sourceAp, CallableFlowSink sink, AccessPath sinkAp,
|
||||
SourceDeclarationCallable c, boolean preservesValue
|
||||
) {
|
||||
c = getAMethod("Combine") and
|
||||
c = this.getAMethod("Combine") and
|
||||
source = getFlowSourceArg(c, _, sourceAp) and
|
||||
sink = TCallableFlowSinkReturn() and
|
||||
sinkAp = AccessPath::empty() and
|
||||
preservesValue = false
|
||||
or
|
||||
exists(Parameter p |
|
||||
c = getAMethod() and
|
||||
c = this.getAMethod() and
|
||||
c.getName().matches("Get%") and
|
||||
p = c.getAParameter() and
|
||||
p.hasName("path") and
|
||||
@@ -2411,10 +2411,10 @@ class SystemWebHttpUtilityFlow extends LibraryTypeDataFlow, SystemWebHttpUtility
|
||||
boolean preservesValue
|
||||
) {
|
||||
(
|
||||
c = getAnHtmlAttributeEncodeMethod() or
|
||||
c = getAnHtmlEncodeMethod() or
|
||||
c = getAJavaScriptStringEncodeMethod() or
|
||||
c = getAnUrlEncodeMethod()
|
||||
c = this.getAnHtmlAttributeEncodeMethod() or
|
||||
c = this.getAnHtmlEncodeMethod() or
|
||||
c = this.getAJavaScriptStringEncodeMethod() or
|
||||
c = this.getAnUrlEncodeMethod()
|
||||
) and
|
||||
source = TCallableFlowSourceArg(0) and
|
||||
sink = TCallableFlowSinkReturn() and
|
||||
@@ -2429,8 +2429,8 @@ class SystemWebHttpServerUtilityFlow extends LibraryTypeDataFlow, SystemWebHttpS
|
||||
boolean preservesValue
|
||||
) {
|
||||
(
|
||||
c = getAnHtmlEncodeMethod() or
|
||||
c = getAnUrlEncodeMethod()
|
||||
c = this.getAnHtmlEncodeMethod() or
|
||||
c = this.getAnUrlEncodeMethod()
|
||||
) and
|
||||
source = TCallableFlowSourceArg(0) and
|
||||
sink = TCallableFlowSinkReturn() and
|
||||
@@ -2445,8 +2445,8 @@ class SystemNetWebUtilityFlow extends LibraryTypeDataFlow, SystemNetWebUtility {
|
||||
boolean preservesValue
|
||||
) {
|
||||
(
|
||||
c = getAnHtmlEncodeMethod() or
|
||||
c = getAnUrlEncodeMethod()
|
||||
c = this.getAnHtmlEncodeMethod() or
|
||||
c = this.getAnUrlEncodeMethod()
|
||||
) and
|
||||
source = TCallableFlowSourceArg(0) and
|
||||
sink = TCallableFlowSinkReturn() and
|
||||
|
||||
@@ -76,9 +76,9 @@ module Ssa {
|
||||
|
||||
override Callable getEnclosingCallable() { this = SsaImpl::TLocalVar(result, _) }
|
||||
|
||||
override string toString() { result = getAssignable().getName() }
|
||||
override string toString() { result = this.getAssignable().getName() }
|
||||
|
||||
override Location getLocation() { result = getAssignable().getLocation() }
|
||||
override Location getLocation() { result = this.getAssignable().getLocation() }
|
||||
}
|
||||
|
||||
/** A fully qualified field or property. */
|
||||
@@ -105,7 +105,7 @@ module Ssa {
|
||||
)
|
||||
}
|
||||
|
||||
override Location getLocation() { result = getFirstAccess().getLocation() }
|
||||
override Location getLocation() { result = this.getFirstAccess().getLocation() }
|
||||
}
|
||||
|
||||
/** A plain field or property. */
|
||||
@@ -115,8 +115,8 @@ module Ssa {
|
||||
|
||||
override string toString() {
|
||||
exists(Assignable f, string prefix |
|
||||
f = getAssignable() and
|
||||
result = prefix + "." + getAssignable()
|
||||
f = this.getAssignable() and
|
||||
result = prefix + "." + this.getAssignable()
|
||||
|
|
||||
if f.(Modifiable).isStatic()
|
||||
then prefix = f.getDeclaringType().getQualifiedName()
|
||||
@@ -134,7 +134,7 @@ module Ssa {
|
||||
|
||||
override SourceVariable getQualifier() { this = SsaImpl::TQualifiedFieldOrProp(_, result, _) }
|
||||
|
||||
override string toString() { result = getQualifier() + "." + getAssignable() }
|
||||
override string toString() { result = this.getQualifier() + "." + this.getAssignable() }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -611,20 +611,20 @@ module Ssa {
|
||||
* and which targets the same assignable as this SSA definition.
|
||||
*/
|
||||
final AssignableDefinition getAPossibleDefinition() {
|
||||
exists(Callable setter | SsaImpl::updatesNamedFieldOrProp(_, _, getCall(), _, setter) |
|
||||
exists(Callable setter | SsaImpl::updatesNamedFieldOrProp(_, _, this.getCall(), _, setter) |
|
||||
result.getEnclosingCallable() = setter and
|
||||
result.getTarget() = this.getSourceVariable().getAssignable()
|
||||
)
|
||||
or
|
||||
SsaImpl::updatesCapturedVariable(_, _, getCall(), _, result, _) and
|
||||
SsaImpl::updatesCapturedVariable(_, _, this.getCall(), _, result, _) and
|
||||
result.getTarget() = this.getSourceVariable().getAssignable()
|
||||
}
|
||||
|
||||
override string toString() {
|
||||
result = getToStringPrefix(this) + "SSA call def(" + getSourceVariable() + ")"
|
||||
result = getToStringPrefix(this) + "SSA call def(" + this.getSourceVariable() + ")"
|
||||
}
|
||||
|
||||
override Location getLocation() { result = getCall().getLocation() }
|
||||
override Location getLocation() { result = this.getCall().getLocation() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -649,10 +649,10 @@ module Ssa {
|
||||
final Definition getQualifierDefinition() { result = q }
|
||||
|
||||
override string toString() {
|
||||
result = getToStringPrefix(this) + "SSA qualifier def(" + getSourceVariable() + ")"
|
||||
result = getToStringPrefix(this) + "SSA qualifier def(" + this.getSourceVariable() + ")"
|
||||
}
|
||||
|
||||
override Location getLocation() { result = getQualifierDefinition().getLocation() }
|
||||
override Location getLocation() { result = this.getQualifierDefinition().getLocation() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -699,7 +699,7 @@ module Ssa {
|
||||
}
|
||||
|
||||
override string toString() {
|
||||
result = getToStringPrefix(this) + "SSA phi(" + getSourceVariable() + ")"
|
||||
result = getToStringPrefix(this) + "SSA phi(" + this.getSourceVariable() + ")"
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user