зеркало из https://github.com/github/codeql.git
Go: Make implicit this receivers explicit
This commit is contained in:
Родитель
e9c25949fa
Коммит
e969018f99
|
@ -20,7 +20,7 @@ external string selectedSourceFile();
|
|||
* A hook to customize the functions printed by this query.
|
||||
*/
|
||||
class Cfg extends PrintAstConfiguration {
|
||||
override predicate shouldPrintFunction(FuncDecl func) { shouldPrintFile(func.getFile()) }
|
||||
override predicate shouldPrintFunction(FuncDecl func) { this.shouldPrintFile(func.getFile()) }
|
||||
|
||||
override predicate shouldPrintFile(File file) {
|
||||
file = getFileBySourceArchiveName(selectedSourceFile())
|
||||
|
|
|
@ -19,7 +19,7 @@ class Error extends @error {
|
|||
int getIndex() { errors(this, _, _, _, _, _, _, _, result) }
|
||||
|
||||
/** Gets the file in which this error was reported, if it can be determined. */
|
||||
ExtractedOrExternalFile getFile() { hasLocationInfo(result.getAbsolutePath(), _, _, _, _) }
|
||||
ExtractedOrExternalFile getFile() { this.hasLocationInfo(result.getAbsolutePath(), _, _, _, _) }
|
||||
|
||||
/**
|
||||
* Holds if this element is at the specified location.
|
||||
|
@ -37,7 +37,7 @@ class Error extends @error {
|
|||
}
|
||||
|
||||
/** Gets a textual representation of this error. */
|
||||
string toString() { result = getMessage() }
|
||||
string toString() { result = this.getMessage() }
|
||||
}
|
||||
|
||||
/** An error reported by an unknown part of the Go frontend. */
|
||||
|
|
|
@ -32,17 +32,19 @@ module HTML {
|
|||
/**
|
||||
* Holds if this is a toplevel element, that is, if it does not have a parent element.
|
||||
*/
|
||||
predicate isTopLevel() { not exists(getParent()) }
|
||||
predicate isTopLevel() { not exists(this.getParent()) }
|
||||
|
||||
/**
|
||||
* Gets the root HTML document element in which this element is contained.
|
||||
*/
|
||||
DocumentElement getDocument() { result = getRoot() }
|
||||
DocumentElement getDocument() { result = this.getRoot() }
|
||||
|
||||
/**
|
||||
* Gets the root element in which this element is contained.
|
||||
*/
|
||||
Element getRoot() { if isTopLevel() then result = this else result = getParent().getRoot() }
|
||||
Element getRoot() {
|
||||
if this.isTopLevel() then result = this else result = this.getParent().getRoot()
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the `i`th child element (0-based) of this element.
|
||||
|
@ -52,7 +54,7 @@ module HTML {
|
|||
/**
|
||||
* Gets a child element of this element.
|
||||
*/
|
||||
Element getChild() { result = getChild(_) }
|
||||
Element getChild() { result = this.getChild(_) }
|
||||
|
||||
/**
|
||||
* Gets the `i`th attribute (0-based) of this element.
|
||||
|
@ -62,13 +64,13 @@ module HTML {
|
|||
/**
|
||||
* Gets an attribute of this element.
|
||||
*/
|
||||
Attribute getAnAttribute() { result = getAttribute(_) }
|
||||
Attribute getAnAttribute() { result = this.getAttribute(_) }
|
||||
|
||||
/**
|
||||
* Gets an attribute of this element that has the given name.
|
||||
*/
|
||||
Attribute getAttributeByName(string name) {
|
||||
result = getAnAttribute() and
|
||||
result = this.getAnAttribute() and
|
||||
result.getName() = name
|
||||
}
|
||||
|
||||
|
@ -77,7 +79,7 @@ module HTML {
|
|||
*/
|
||||
TextNode getTextNode() { result.getParent() = this }
|
||||
|
||||
override string toString() { result = "<" + getName() + ">...</>" }
|
||||
override string toString() { result = "<" + this.getName() + ">...</>" }
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -106,7 +108,7 @@ module HTML {
|
|||
* Gets the root element in which the element to which this attribute
|
||||
* belongs is contained.
|
||||
*/
|
||||
Element getRoot() { result = getElement().getRoot() }
|
||||
Element getRoot() { result = this.getElement().getRoot() }
|
||||
|
||||
/**
|
||||
* Gets the name of this attribute.
|
||||
|
@ -121,7 +123,7 @@ module HTML {
|
|||
*/
|
||||
string getValue() { xmlAttrs(this, _, _, result, _, _) }
|
||||
|
||||
override string toString() { result = getName() + "=" + getValue() }
|
||||
override string toString() { result = this.getName() + "=" + this.getValue() }
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -138,7 +140,7 @@ module HTML {
|
|||
* ```
|
||||
*/
|
||||
class DocumentElement extends Element {
|
||||
DocumentElement() { getName() = "html" }
|
||||
DocumentElement() { this.getName() = "html" }
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -155,7 +157,7 @@ module HTML {
|
|||
class TextNode extends Locatable, @xmlcharacters {
|
||||
TextNode() { exists(HtmlFile f | xmlChars(this, _, _, _, _, f)) }
|
||||
|
||||
override string toString() { result = getText() }
|
||||
override string toString() { result = this.getText() }
|
||||
|
||||
/**
|
||||
* Gets the content of this text node.
|
||||
|
@ -198,7 +200,7 @@ module HTML {
|
|||
Element getParent() { xmlComments(this, _, result, _) }
|
||||
|
||||
/** Gets the text of this comment, not including delimiters. */
|
||||
string getText() { result = toString().regexpCapture("(?s)<!--(.*)-->", 1) }
|
||||
string getText() { result = this.toString().regexpCapture("(?s)<!--(.*)-->", 1) }
|
||||
|
||||
override string toString() { xmlComments(this, result, _, _) }
|
||||
|
||||
|
|
|
@ -25,12 +25,12 @@ class Location extends @location {
|
|||
int getEndColumn() { locations_default(this, _, _, _, _, result) }
|
||||
|
||||
/** Gets the number of lines covered by this location. */
|
||||
int getNumLines() { result = getEndLine() - getStartLine() + 1 }
|
||||
int getNumLines() { result = this.getEndLine() - this.getStartLine() + 1 }
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() {
|
||||
exists(string filepath, int startline, int startcolumn, int endline, int endcolumn |
|
||||
hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) and
|
||||
this.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) and
|
||||
result = filepath + "@" + startline + ":" + startcolumn + ":" + endline + ":" + endcolumn
|
||||
)
|
||||
}
|
||||
|
@ -55,13 +55,13 @@ class Location extends @location {
|
|||
/** A program element with a location. */
|
||||
class Locatable extends @locatable {
|
||||
/** Gets the file this program element comes from. */
|
||||
File getFile() { result = getLocation().getFile() }
|
||||
File getFile() { result = this.getLocation().getFile() }
|
||||
|
||||
/** Gets this element's location. */
|
||||
Location getLocation() { has_location(this, result) }
|
||||
|
||||
/** Gets the number of lines covered by this element. */
|
||||
int getNumLines() { result = getLocation().getNumLines() }
|
||||
int getNumLines() { result = this.getLocation().getNumLines() }
|
||||
|
||||
/**
|
||||
* Holds if this element is at the specified location.
|
||||
|
@ -73,7 +73,7 @@ class Locatable extends @locatable {
|
|||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) {
|
||||
getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
this.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
}
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
|
|
|
@ -22,7 +22,7 @@ class Package extends @package {
|
|||
PackageScope getScope() { packages(this, _, _, result) }
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = "package " + getPath() }
|
||||
string toString() { result = "package " + this.getPath() }
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -85,12 +85,12 @@ class PrintAstNode extends TPrintAstNode {
|
|||
* within a function are printed, but the query can override
|
||||
* `PrintAstConfiguration.shouldPrintFunction` to filter the output.
|
||||
*/
|
||||
predicate shouldPrint() { exists(getLocation()) }
|
||||
predicate shouldPrint() { exists(this.getLocation()) }
|
||||
|
||||
/**
|
||||
* Gets a child of this node.
|
||||
*/
|
||||
PrintAstNode getAChild() { result = getChild(_) }
|
||||
PrintAstNode getAChild() { result = this.getChild(_) }
|
||||
|
||||
/**
|
||||
* Gets the location of this node in the source code.
|
||||
|
@ -103,7 +103,7 @@ class PrintAstNode extends TPrintAstNode {
|
|||
*/
|
||||
string getProperty(string key) {
|
||||
key = "semmle.label" and
|
||||
result = toString()
|
||||
result = this.toString()
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -112,7 +112,7 @@ class PrintAstNode extends TPrintAstNode {
|
|||
* this.
|
||||
*/
|
||||
string getChildEdgeLabel(int childIndex) {
|
||||
exists(getChild(childIndex)) and
|
||||
exists(this.getChild(childIndex)) and
|
||||
result = childIndex.toString()
|
||||
}
|
||||
|
||||
|
@ -191,7 +191,7 @@ class FileNode extends BaseAstNode {
|
|||
result = super.getProperty(key)
|
||||
or
|
||||
key = "semmle.order" and
|
||||
result = getSortOrder().toString()
|
||||
result = this.getSortOrder().toString()
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -220,7 +220,7 @@ class FileNode extends BaseAstNode {
|
|||
*/
|
||||
override BaseAstNode getChild(int childIndex) {
|
||||
if exists(ast.getPackageNameExpr())
|
||||
then result = getChildPackageFirst(childIndex, TAstNode(ast.getPackageNameExpr()), _)
|
||||
then result = this.getChildPackageFirst(childIndex, TAstNode(ast.getPackageNameExpr()), _)
|
||||
else result = super.getChild(childIndex)
|
||||
}
|
||||
|
||||
|
@ -230,7 +230,7 @@ class FileNode extends BaseAstNode {
|
|||
* of this method.
|
||||
*/
|
||||
override string getChildEdgeLabel(int childIndex) {
|
||||
if getChild(childIndex) = TAstNode(ast.getPackageNameExpr())
|
||||
if this.getChild(childIndex) = TAstNode(ast.getPackageNameExpr())
|
||||
then result = "package"
|
||||
else result = super.getChildEdgeLabel(childIndex)
|
||||
}
|
||||
|
|
|
@ -69,9 +69,9 @@ class BadStmt extends @badstmt, Stmt {
|
|||
*/
|
||||
class DeclStmt extends @declstmt, Stmt, DeclParent {
|
||||
/** Gets the declaration in this statement. */
|
||||
Decl getDecl() { result = getDecl(0) }
|
||||
Decl getDecl() { result = this.getDecl(0) }
|
||||
|
||||
override predicate mayHaveSideEffects() { getDecl().mayHaveSideEffects() }
|
||||
override predicate mayHaveSideEffects() { this.getDecl().mayHaveSideEffects() }
|
||||
|
||||
override string toString() { result = "declaration statement" }
|
||||
|
||||
|
@ -104,15 +104,15 @@ class EmptyStmt extends @emptystmt, Stmt {
|
|||
*/
|
||||
class LabeledStmt extends @labeledstmt, Stmt {
|
||||
/** Gets the identifier representing the label. */
|
||||
Ident getLabelExpr() { result = getChildExpr(0) }
|
||||
Ident getLabelExpr() { result = this.getChildExpr(0) }
|
||||
|
||||
/** Gets the label. */
|
||||
string getLabel() { result = getLabelExpr().getName() }
|
||||
string getLabel() { result = this.getLabelExpr().getName() }
|
||||
|
||||
/** Gets the statement that is being labeled. */
|
||||
Stmt getStmt() { result = getChildStmt(1) }
|
||||
Stmt getStmt() { result = this.getChildStmt(1) }
|
||||
|
||||
override predicate mayHaveSideEffects() { getStmt().mayHaveSideEffects() }
|
||||
override predicate mayHaveSideEffects() { this.getStmt().mayHaveSideEffects() }
|
||||
|
||||
override string toString() { result = "labeled statement" }
|
||||
|
||||
|
@ -133,9 +133,9 @@ class LabeledStmt extends @labeledstmt, Stmt {
|
|||
*/
|
||||
class ExprStmt extends @exprstmt, Stmt {
|
||||
/** Gets the expression. */
|
||||
Expr getExpr() { result = getChildExpr(0) }
|
||||
Expr getExpr() { result = this.getChildExpr(0) }
|
||||
|
||||
override predicate mayHaveSideEffects() { getExpr().mayHaveSideEffects() }
|
||||
override predicate mayHaveSideEffects() { this.getExpr().mayHaveSideEffects() }
|
||||
|
||||
override string toString() { result = "expression statement" }
|
||||
|
||||
|
@ -153,10 +153,10 @@ class ExprStmt extends @exprstmt, Stmt {
|
|||
*/
|
||||
class SendStmt extends @sendstmt, Stmt {
|
||||
/** Gets the expression representing the channel. */
|
||||
Expr getChannel() { result = getChildExpr(0) }
|
||||
Expr getChannel() { result = this.getChildExpr(0) }
|
||||
|
||||
/** Gets the expression representing the value being sent. */
|
||||
Expr getValue() { result = getChildExpr(1) }
|
||||
Expr getValue() { result = this.getChildExpr(1) }
|
||||
|
||||
override predicate mayHaveSideEffects() { any() }
|
||||
|
||||
|
@ -177,7 +177,7 @@ class SendStmt extends @sendstmt, Stmt {
|
|||
*/
|
||||
class IncDecStmt extends @incdecstmt, Stmt {
|
||||
/** Gets the expression being incremented or decremented. */
|
||||
Expr getOperand() { result = getChildExpr(0) }
|
||||
Expr getOperand() { result = this.getChildExpr(0) }
|
||||
|
||||
/** Gets the increment or decrement operator. */
|
||||
string getOperator() { none() }
|
||||
|
@ -236,42 +236,44 @@ class Assignment extends @assignment, Stmt {
|
|||
/** Gets the `i`th left-hand side of this assignment (0-based). */
|
||||
Expr getLhs(int i) {
|
||||
i >= 0 and
|
||||
result = getChildExpr(-(i + 1))
|
||||
result = this.getChildExpr(-(i + 1))
|
||||
}
|
||||
|
||||
/** Gets a left-hand side of this assignment. */
|
||||
Expr getAnLhs() { result = getLhs(_) }
|
||||
Expr getAnLhs() { result = this.getLhs(_) }
|
||||
|
||||
/** Gets the number of left-hand sides of this assignment. */
|
||||
int getNumLhs() { result = count(getAnLhs()) }
|
||||
int getNumLhs() { result = count(this.getAnLhs()) }
|
||||
|
||||
/** Gets the unique left-hand side of this assignment, if there is only one. */
|
||||
Expr getLhs() { getNumLhs() = 1 and result = getLhs(0) }
|
||||
Expr getLhs() { this.getNumLhs() = 1 and result = this.getLhs(0) }
|
||||
|
||||
/** Gets the `i`th right-hand side of this assignment (0-based). */
|
||||
Expr getRhs(int i) {
|
||||
i >= 0 and
|
||||
result = getChildExpr(i + 1)
|
||||
result = this.getChildExpr(i + 1)
|
||||
}
|
||||
|
||||
/** Gets a right-hand side of this assignment. */
|
||||
Expr getAnRhs() { result = getRhs(_) }
|
||||
Expr getAnRhs() { result = this.getRhs(_) }
|
||||
|
||||
/** Gets the number of right-hand sides of this assignment. */
|
||||
int getNumRhs() { result = count(getAnRhs()) }
|
||||
int getNumRhs() { result = count(this.getAnRhs()) }
|
||||
|
||||
/** Gets the unique right-hand side of this assignment, if there is only one. */
|
||||
Expr getRhs() { getNumRhs() = 1 and result = getRhs(0) }
|
||||
Expr getRhs() { this.getNumRhs() = 1 and result = this.getRhs(0) }
|
||||
|
||||
/** Holds if this assignment assigns `rhs` to `lhs`. */
|
||||
predicate assigns(Expr lhs, Expr rhs) { exists(int i | lhs = getLhs(i) and rhs = getRhs(i)) }
|
||||
predicate assigns(Expr lhs, Expr rhs) {
|
||||
exists(int i | lhs = this.getLhs(i) and rhs = this.getRhs(i))
|
||||
}
|
||||
|
||||
/** Gets the assignment operator in this statement. */
|
||||
string getOperator() { none() }
|
||||
|
||||
override predicate mayHaveSideEffects() { any() }
|
||||
|
||||
override string toString() { result = "... " + getOperator() + " ..." }
|
||||
override string toString() { result = "... " + this.getOperator() + " ..." }
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -518,9 +520,9 @@ class AndNotAssignStmt extends @andnotassignstmt, CompoundAssignStmt {
|
|||
*/
|
||||
class GoStmt extends @gostmt, Stmt {
|
||||
/** Gets the call. */
|
||||
CallExpr getCall() { result = getChildExpr(0) }
|
||||
CallExpr getCall() { result = this.getChildExpr(0) }
|
||||
|
||||
override predicate mayHaveSideEffects() { getCall().mayHaveSideEffects() }
|
||||
override predicate mayHaveSideEffects() { this.getCall().mayHaveSideEffects() }
|
||||
|
||||
override string toString() { result = "go statement" }
|
||||
|
||||
|
@ -538,9 +540,9 @@ class GoStmt extends @gostmt, Stmt {
|
|||
*/
|
||||
class DeferStmt extends @deferstmt, Stmt {
|
||||
/** Gets the call being deferred. */
|
||||
CallExpr getCall() { result = getChildExpr(0) }
|
||||
CallExpr getCall() { result = this.getChildExpr(0) }
|
||||
|
||||
override predicate mayHaveSideEffects() { getCall().mayHaveSideEffects() }
|
||||
override predicate mayHaveSideEffects() { this.getCall().mayHaveSideEffects() }
|
||||
|
||||
override string toString() { result = "defer statement" }
|
||||
|
||||
|
@ -558,18 +560,18 @@ class DeferStmt extends @deferstmt, Stmt {
|
|||
*/
|
||||
class ReturnStmt extends @returnstmt, Stmt {
|
||||
/** Gets the `i`th returned expression (0-based) */
|
||||
Expr getExpr(int i) { result = getChildExpr(i) }
|
||||
Expr getExpr(int i) { result = this.getChildExpr(i) }
|
||||
|
||||
/** Gets a returned expression. */
|
||||
Expr getAnExpr() { result = getExpr(_) }
|
||||
Expr getAnExpr() { result = this.getExpr(_) }
|
||||
|
||||
/** Gets the number of returned expressions. */
|
||||
int getNumExpr() { result = count(getAnExpr()) }
|
||||
int getNumExpr() { result = count(this.getAnExpr()) }
|
||||
|
||||
/** Gets the unique returned expression, if there is only one. */
|
||||
Expr getExpr() { getNumChild() = 1 and result = getExpr(0) }
|
||||
Expr getExpr() { this.getNumChild() = 1 and result = this.getExpr(0) }
|
||||
|
||||
override predicate mayHaveSideEffects() { getAnExpr().mayHaveSideEffects() }
|
||||
override predicate mayHaveSideEffects() { this.getAnExpr().mayHaveSideEffects() }
|
||||
|
||||
override string toString() { result = "return statement" }
|
||||
|
||||
|
@ -592,10 +594,10 @@ class ReturnStmt extends @returnstmt, Stmt {
|
|||
*/
|
||||
class BranchStmt extends @branchstmt, Stmt {
|
||||
/** Gets the expression denoting the target label of the branch, if any. */
|
||||
Ident getLabelExpr() { result = getChildExpr(0) }
|
||||
Ident getLabelExpr() { result = this.getChildExpr(0) }
|
||||
|
||||
/** Gets the target label of the branch, if any. */
|
||||
string getLabel() { result = getLabelExpr().getName() }
|
||||
string getLabel() { result = this.getLabelExpr().getName() }
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -674,15 +676,15 @@ class FallthroughStmt extends @fallthroughstmt, BranchStmt {
|
|||
*/
|
||||
class BlockStmt extends @blockstmt, Stmt, ScopeNode {
|
||||
/** Gets the `i`th statement in this block (0-based). */
|
||||
Stmt getStmt(int i) { result = getChildStmt(i) }
|
||||
Stmt getStmt(int i) { result = this.getChildStmt(i) }
|
||||
|
||||
/** Gets a statement in this block. */
|
||||
Stmt getAStmt() { result = getAChildStmt() }
|
||||
Stmt getAStmt() { result = this.getAChildStmt() }
|
||||
|
||||
/** Gets the number of statements in this block. */
|
||||
int getNumStmt() { result = getNumChildStmt() }
|
||||
int getNumStmt() { result = this.getNumChildStmt() }
|
||||
|
||||
override predicate mayHaveSideEffects() { getAStmt().mayHaveSideEffects() }
|
||||
override predicate mayHaveSideEffects() { this.getAStmt().mayHaveSideEffects() }
|
||||
|
||||
override string toString() { result = "block statement" }
|
||||
|
||||
|
@ -704,22 +706,22 @@ class BlockStmt extends @blockstmt, Stmt, ScopeNode {
|
|||
*/
|
||||
class IfStmt extends @ifstmt, Stmt, ScopeNode {
|
||||
/** Gets the init statement of this `if` statement, if any. */
|
||||
Stmt getInit() { result = getChildStmt(0) }
|
||||
Stmt getInit() { result = this.getChildStmt(0) }
|
||||
|
||||
/** Gets the condition of this `if` statement. */
|
||||
Expr getCond() { result = getChildExpr(1) }
|
||||
Expr getCond() { result = this.getChildExpr(1) }
|
||||
|
||||
/** Gets the "then" branch of this `if` statement. */
|
||||
BlockStmt getThen() { result = getChildStmt(2) }
|
||||
BlockStmt getThen() { result = this.getChildStmt(2) }
|
||||
|
||||
/** Gets the "else" branch of this `if` statement, if any. */
|
||||
Stmt getElse() { result = getChildStmt(3) }
|
||||
Stmt getElse() { result = this.getChildStmt(3) }
|
||||
|
||||
override predicate mayHaveSideEffects() {
|
||||
getInit().mayHaveSideEffects() or
|
||||
getCond().mayHaveSideEffects() or
|
||||
getThen().mayHaveSideEffects() or
|
||||
getElse().mayHaveSideEffects()
|
||||
this.getInit().mayHaveSideEffects() or
|
||||
this.getCond().mayHaveSideEffects() or
|
||||
this.getThen().mayHaveSideEffects() or
|
||||
this.getElse().mayHaveSideEffects()
|
||||
}
|
||||
|
||||
override string toString() { result = "if statement" }
|
||||
|
@ -746,26 +748,26 @@ class IfStmt extends @ifstmt, Stmt, ScopeNode {
|
|||
*/
|
||||
class CaseClause extends @caseclause, Stmt, ScopeNode {
|
||||
/** Gets the `i`th expression of this `case` clause (0-based). */
|
||||
Expr getExpr(int i) { result = getChildExpr(-(i + 1)) }
|
||||
Expr getExpr(int i) { result = this.getChildExpr(-(i + 1)) }
|
||||
|
||||
/** Gets an expression of this `case` clause. */
|
||||
Expr getAnExpr() { result = getAChildExpr() }
|
||||
Expr getAnExpr() { result = this.getAChildExpr() }
|
||||
|
||||
/** Gets the number of expressions of this `case` clause. */
|
||||
int getNumExpr() { result = getNumChildExpr() }
|
||||
int getNumExpr() { result = this.getNumChildExpr() }
|
||||
|
||||
/** Gets the `i`th statement of this `case` clause (0-based). */
|
||||
Stmt getStmt(int i) { result = getChildStmt(i) }
|
||||
Stmt getStmt(int i) { result = this.getChildStmt(i) }
|
||||
|
||||
/** Gets a statement of this `case` clause. */
|
||||
Stmt getAStmt() { result = getAChildStmt() }
|
||||
Stmt getAStmt() { result = this.getAChildStmt() }
|
||||
|
||||
/** Gets the number of statements of this `case` clause. */
|
||||
int getNumStmt() { result = getNumChildStmt() }
|
||||
int getNumStmt() { result = this.getNumChildStmt() }
|
||||
|
||||
override predicate mayHaveSideEffects() {
|
||||
getAnExpr().mayHaveSideEffects() or
|
||||
getAStmt().mayHaveSideEffects()
|
||||
this.getAnExpr().mayHaveSideEffects() or
|
||||
this.getAStmt().mayHaveSideEffects()
|
||||
}
|
||||
|
||||
override string toString() { result = "case clause" }
|
||||
|
@ -801,34 +803,38 @@ class CaseClause extends @caseclause, Stmt, ScopeNode {
|
|||
*/
|
||||
class SwitchStmt extends @switchstmt, Stmt, ScopeNode {
|
||||
/** Gets the init statement of this `switch` statement, if any. */
|
||||
Stmt getInit() { result = getChildStmt(0) }
|
||||
Stmt getInit() { result = this.getChildStmt(0) }
|
||||
|
||||
/** Gets the body of this `switch` statement. */
|
||||
BlockStmt getBody() { result = getChildStmt(2) }
|
||||
BlockStmt getBody() { result = this.getChildStmt(2) }
|
||||
|
||||
/** Gets the `i`th case clause of this `switch` statement (0-based). */
|
||||
CaseClause getCase(int i) { result = getBody().getStmt(i) }
|
||||
CaseClause getCase(int i) { result = this.getBody().getStmt(i) }
|
||||
|
||||
/** Gets a case clause of this `switch` statement. */
|
||||
CaseClause getACase() { result = getCase(_) }
|
||||
CaseClause getACase() { result = this.getCase(_) }
|
||||
|
||||
/** Gets the number of case clauses in this `switch` statement. */
|
||||
int getNumCase() { result = count(getACase()) }
|
||||
int getNumCase() { result = count(this.getACase()) }
|
||||
|
||||
/** Gets the `i`th non-default case clause of this `switch` statement (0-based). */
|
||||
CaseClause getNonDefaultCase(int i) {
|
||||
result =
|
||||
rank[i + 1](CaseClause cc, int j | cc = getCase(j) and exists(cc.getExpr(_)) | cc order by j)
|
||||
rank[i + 1](CaseClause cc, int j |
|
||||
cc = this.getCase(j) and exists(cc.getExpr(_))
|
||||
|
|
||||
cc order by j
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets a non-default case clause of this `switch` statement. */
|
||||
CaseClause getANonDefaultCase() { result = getNonDefaultCase(_) }
|
||||
CaseClause getANonDefaultCase() { result = this.getNonDefaultCase(_) }
|
||||
|
||||
/** Gets the number of non-default case clauses in this `switch` statement. */
|
||||
int getNumNonDefaultCase() { result = count(getANonDefaultCase()) }
|
||||
int getNumNonDefaultCase() { result = count(this.getANonDefaultCase()) }
|
||||
|
||||
/** Gets the default case clause of this `switch` statement, if any. */
|
||||
CaseClause getDefault() { result = getACase() and not exists(result.getExpr(_)) }
|
||||
CaseClause getDefault() { result = this.getACase() and not exists(result.getExpr(_)) }
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -848,11 +854,11 @@ class SwitchStmt extends @switchstmt, Stmt, ScopeNode {
|
|||
*/
|
||||
class ExpressionSwitchStmt extends @exprswitchstmt, SwitchStmt {
|
||||
/** Gets the switch expression of this `switch` statement. */
|
||||
Expr getExpr() { result = getChildExpr(1) }
|
||||
Expr getExpr() { result = this.getChildExpr(1) }
|
||||
|
||||
override predicate mayHaveSideEffects() {
|
||||
getInit().mayHaveSideEffects() or
|
||||
getBody().mayHaveSideEffects()
|
||||
this.getInit().mayHaveSideEffects() or
|
||||
this.getBody().mayHaveSideEffects()
|
||||
}
|
||||
|
||||
override string toString() { result = "expression-switch statement" }
|
||||
|
@ -880,13 +886,15 @@ class ExpressionSwitchStmt extends @exprswitchstmt, SwitchStmt {
|
|||
*/
|
||||
class TypeSwitchStmt extends @typeswitchstmt, SwitchStmt {
|
||||
/** Gets the assign statement of this type-switch statement. */
|
||||
SimpleAssignStmt getAssign() { result = getChildStmt(1) }
|
||||
SimpleAssignStmt getAssign() { result = this.getChildStmt(1) }
|
||||
|
||||
/** Gets the test statement of this type-switch statement. This is a `SimpleAssignStmt` or `ExprStmt`. */
|
||||
Stmt getTest() { result = getChildStmt(1) }
|
||||
Stmt getTest() { result = this.getChildStmt(1) }
|
||||
|
||||
/** Gets the expression whose type is examined by this `switch` statement. */
|
||||
Expr getExpr() { result = getAssign().getRhs() or result = getChildStmt(1).(ExprStmt).getExpr() }
|
||||
Expr getExpr() {
|
||||
result = this.getAssign().getRhs() or result = this.getChildStmt(1).(ExprStmt).getExpr()
|
||||
}
|
||||
|
||||
override predicate mayHaveSideEffects() { any() }
|
||||
|
||||
|
@ -920,18 +928,18 @@ class TypeSwitchStmt extends @typeswitchstmt, SwitchStmt {
|
|||
*/
|
||||
class CommClause extends @commclause, Stmt, ScopeNode {
|
||||
/** Gets the comm statement of this clause, if any. */
|
||||
Stmt getComm() { result = getChildStmt(0) }
|
||||
Stmt getComm() { result = this.getChildStmt(0) }
|
||||
|
||||
/** Gets the `i`th statement of this clause (0-based). */
|
||||
Stmt getStmt(int i) { i >= 0 and result = getChildStmt(i + 1) }
|
||||
Stmt getStmt(int i) { i >= 0 and result = this.getChildStmt(i + 1) }
|
||||
|
||||
/** Gets a statement of this clause. */
|
||||
Stmt getAStmt() { result = getStmt(_) }
|
||||
Stmt getAStmt() { result = this.getStmt(_) }
|
||||
|
||||
/** Gets the number of statements of this clause. */
|
||||
int getNumStmt() { result = count(getAStmt()) }
|
||||
int getNumStmt() { result = count(this.getAStmt()) }
|
||||
|
||||
override predicate mayHaveSideEffects() { getAStmt().mayHaveSideEffects() }
|
||||
override predicate mayHaveSideEffects() { this.getAStmt().mayHaveSideEffects() }
|
||||
|
||||
override string toString() { result = "comm clause" }
|
||||
|
||||
|
@ -956,7 +964,7 @@ class RecvStmt extends Stmt {
|
|||
Expr getLhs(int i) { result = this.(Assignment).getLhs(i) }
|
||||
|
||||
/** Gets the number of left-hand-side expressions of this receive statement. */
|
||||
int getNumLhs() { result = count(getLhs(_)) }
|
||||
int getNumLhs() { result = count(this.getLhs(_)) }
|
||||
|
||||
/** Gets the receive expression of this receive statement. */
|
||||
RecvExpr getExpr() {
|
||||
|
@ -991,34 +999,34 @@ class RecvStmt extends Stmt {
|
|||
*/
|
||||
class SelectStmt extends @selectstmt, Stmt {
|
||||
/** Gets the body of this `select` statement. */
|
||||
BlockStmt getBody() { result = getChildStmt(0) }
|
||||
BlockStmt getBody() { result = this.getChildStmt(0) }
|
||||
|
||||
/**
|
||||
* Gets the `i`th comm clause (that is, `case` or `default` clause) in this `select` statement.
|
||||
*/
|
||||
CommClause getCommClause(int i) { result = getBody().getStmt(i) }
|
||||
CommClause getCommClause(int i) { result = this.getBody().getStmt(i) }
|
||||
|
||||
/**
|
||||
* Gets a comm clause in this `select` statement.
|
||||
*/
|
||||
CommClause getACommClause() { result = getCommClause(_) }
|
||||
CommClause getACommClause() { result = this.getCommClause(_) }
|
||||
|
||||
/** Gets the `i`th `case` clause in this `select` statement. */
|
||||
CommClause getNonDefaultCommClause(int i) {
|
||||
result =
|
||||
rank[i + 1](CommClause cc, int j |
|
||||
cc = getCommClause(j) and exists(cc.getComm())
|
||||
cc = this.getCommClause(j) and exists(cc.getComm())
|
||||
|
|
||||
cc order by j
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets the number of `case` clauses in this `select` statement. */
|
||||
int getNumNonDefaultCommClause() { result = count(getNonDefaultCommClause(_)) }
|
||||
int getNumNonDefaultCommClause() { result = count(this.getNonDefaultCommClause(_)) }
|
||||
|
||||
/** Gets the `default` clause in this `select` statement, if any. */
|
||||
CommClause getDefaultCommClause() {
|
||||
result = getCommClause(_) and
|
||||
result = this.getCommClause(_) and
|
||||
not exists(result.getComm())
|
||||
}
|
||||
|
||||
|
@ -1070,21 +1078,21 @@ class LoopStmt extends @loopstmt, Stmt, ScopeNode {
|
|||
*/
|
||||
class ForStmt extends @forstmt, LoopStmt {
|
||||
/** Gets the init statement of this `for` statement, if any. */
|
||||
Stmt getInit() { result = getChildStmt(0) }
|
||||
Stmt getInit() { result = this.getChildStmt(0) }
|
||||
|
||||
/** Gets the condition of this `for` statement. */
|
||||
Expr getCond() { result = getChildExpr(1) }
|
||||
Expr getCond() { result = this.getChildExpr(1) }
|
||||
|
||||
/** Gets the post statement of this `for` statement. */
|
||||
Stmt getPost() { result = getChildStmt(2) }
|
||||
Stmt getPost() { result = this.getChildStmt(2) }
|
||||
|
||||
override BlockStmt getBody() { result = getChildStmt(3) }
|
||||
override BlockStmt getBody() { result = this.getChildStmt(3) }
|
||||
|
||||
override predicate mayHaveSideEffects() {
|
||||
getInit().mayHaveSideEffects() or
|
||||
getCond().mayHaveSideEffects() or
|
||||
getPost().mayHaveSideEffects() or
|
||||
getBody().mayHaveSideEffects()
|
||||
this.getInit().mayHaveSideEffects() or
|
||||
this.getCond().mayHaveSideEffects() or
|
||||
this.getPost().mayHaveSideEffects() or
|
||||
this.getBody().mayHaveSideEffects()
|
||||
}
|
||||
|
||||
override string toString() { result = "for statement" }
|
||||
|
@ -1117,15 +1125,15 @@ class ForStmt extends @forstmt, LoopStmt {
|
|||
*/
|
||||
class RangeStmt extends @rangestmt, LoopStmt {
|
||||
/** Gets the expression denoting the key of this `range` statement. */
|
||||
Expr getKey() { result = getChildExpr(0) }
|
||||
Expr getKey() { result = this.getChildExpr(0) }
|
||||
|
||||
/** Get the expression denoting the value of this `range` statement. */
|
||||
Expr getValue() { result = getChildExpr(1) }
|
||||
Expr getValue() { result = this.getChildExpr(1) }
|
||||
|
||||
/** Gets the domain of this `range` statement. */
|
||||
Expr getDomain() { result = getChildExpr(2) }
|
||||
Expr getDomain() { result = this.getChildExpr(2) }
|
||||
|
||||
override BlockStmt getBody() { result = getChildStmt(3) }
|
||||
override BlockStmt getBody() { result = this.getChildStmt(3) }
|
||||
|
||||
override predicate mayHaveSideEffects() { any() }
|
||||
|
||||
|
|
|
@ -91,7 +91,7 @@ class BasicBlock extends TControlFlowNode {
|
|||
BasicBlock getAPredecessor() { result.getASuccessor() = this }
|
||||
|
||||
/** Gets a node in this block. */
|
||||
ControlFlow::Node getANode() { result = getNode(_) }
|
||||
ControlFlow::Node getANode() { result = this.getNode(_) }
|
||||
|
||||
/** Gets the node at the given position in this block. */
|
||||
ControlFlow::Node getNode(int pos) { bbIndex(this, result, pos) }
|
||||
|
@ -100,7 +100,7 @@ class BasicBlock extends TControlFlowNode {
|
|||
ControlFlow::Node getFirstNode() { result = this }
|
||||
|
||||
/** Gets the last node in this block. */
|
||||
ControlFlow::Node getLastNode() { result = getNode(length() - 1) }
|
||||
ControlFlow::Node getLastNode() { result = this.getNode(this.length() - 1) }
|
||||
|
||||
/** Gets the length of this block. */
|
||||
int length() { result = bbLength(this) }
|
||||
|
@ -109,7 +109,7 @@ class BasicBlock extends TControlFlowNode {
|
|||
ReachableBasicBlock getImmediateDominator() { bbIDominates(result, this) }
|
||||
|
||||
/** Gets the innermost function or file to which this basic block belongs. */
|
||||
ControlFlow::Root getRoot() { result = getFirstNode().getRoot() }
|
||||
ControlFlow::Root getRoot() { result = this.getFirstNode().getRoot() }
|
||||
|
||||
/** Gets a textual representation of this basic block. */
|
||||
string toString() { result = "basic block" }
|
||||
|
@ -124,8 +124,8 @@ class BasicBlock extends TControlFlowNode {
|
|||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) {
|
||||
getFirstNode().hasLocationInfo(filepath, startline, startcolumn, _, _) and
|
||||
getLastNode().hasLocationInfo(_, _, _, endline, endcolumn)
|
||||
this.getFirstNode().hasLocationInfo(filepath, startline, startcolumn, _, _) and
|
||||
this.getLastNode().hasLocationInfo(_, _, _, endline, endcolumn)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -155,7 +155,7 @@ class ReachableBasicBlock extends BasicBlock {
|
|||
*/
|
||||
predicate dominates(ReachableBasicBlock bb) {
|
||||
bb = this or
|
||||
strictlyDominates(bb)
|
||||
this.strictlyDominates(bb)
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -171,7 +171,7 @@ class ReachableBasicBlock extends BasicBlock {
|
|||
*/
|
||||
predicate postDominates(ReachableBasicBlock bb) {
|
||||
bb = this or
|
||||
strictlyPostDominates(bb)
|
||||
this.strictlyPostDominates(bb)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -179,7 +179,7 @@ class ReachableBasicBlock extends BasicBlock {
|
|||
* A reachable basic block with more than one predecessor.
|
||||
*/
|
||||
class ReachableJoinBlock extends ReachableBasicBlock {
|
||||
ReachableJoinBlock() { getFirstNode().isJoin() }
|
||||
ReachableJoinBlock() { this.getFirstNode().isJoin() }
|
||||
|
||||
/**
|
||||
* Holds if this basic block belongs to the dominance frontier of `b`, that is
|
||||
|
@ -190,11 +190,11 @@ class ReachableJoinBlock extends ReachableBasicBlock {
|
|||
* its use in optimization".
|
||||
*/
|
||||
predicate inDominanceFrontierOf(ReachableBasicBlock b) {
|
||||
b = getAPredecessor() and not b = getImmediateDominator()
|
||||
b = this.getAPredecessor() and not b = this.getImmediateDominator()
|
||||
or
|
||||
exists(ReachableBasicBlock prev | inDominanceFrontierOf(prev) |
|
||||
exists(ReachableBasicBlock prev | this.inDominanceFrontierOf(prev) |
|
||||
b = prev.getImmediateDominator() and
|
||||
not b = getImmediateDominator()
|
||||
not b = this.getImmediateDominator()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -44,10 +44,10 @@ module ControlFlow {
|
|||
Node getAPredecessor() { this = result.getASuccessor() }
|
||||
|
||||
/** Holds if this is a node with more than one successor. */
|
||||
predicate isBranch() { strictcount(getASuccessor()) > 1 }
|
||||
predicate isBranch() { strictcount(this.getASuccessor()) > 1 }
|
||||
|
||||
/** Holds if this is a node with more than one predecessor. */
|
||||
predicate isJoin() { strictcount(getAPredecessor()) > 1 }
|
||||
predicate isJoin() { strictcount(this.getAPredecessor()) > 1 }
|
||||
|
||||
/** Holds if this is the first control-flow node in `subtree`. */
|
||||
predicate isFirstNodeOf(AstNode subtree) { CFG::firstNode(subtree, this) }
|
||||
|
@ -77,7 +77,7 @@ module ControlFlow {
|
|||
Root getRoot() { none() }
|
||||
|
||||
/** Gets the file to which this node belongs. */
|
||||
File getFile() { hasLocationInfo(result.getAbsolutePath(), _, _, _, _) }
|
||||
File getFile() { this.hasLocationInfo(result.getAbsolutePath(), _, _, _, _) }
|
||||
|
||||
/**
|
||||
* Gets a textual representation of this control flow node.
|
||||
|
@ -166,7 +166,7 @@ module ControlFlow {
|
|||
* Holds if this node sets any field or element of `base` to `rhs`.
|
||||
*/
|
||||
predicate writesComponent(DataFlow::Node base, DataFlow::Node rhs) {
|
||||
writesElement(base, _, rhs) or writesField(base, _, rhs)
|
||||
this.writesElement(base, _, rhs) or this.writesField(base, _, rhs)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -183,37 +183,37 @@ module ControlFlow {
|
|||
private predicate ensuresAux(Expr expr, boolean b) {
|
||||
expr = cond and b = outcome
|
||||
or
|
||||
expr = any(ParenExpr par | ensuresAux(par, b)).getExpr()
|
||||
expr = any(ParenExpr par | this.ensuresAux(par, b)).getExpr()
|
||||
or
|
||||
expr = any(NotExpr ne | ensuresAux(ne, b.booleanNot())).getOperand()
|
||||
expr = any(NotExpr ne | this.ensuresAux(ne, b.booleanNot())).getOperand()
|
||||
or
|
||||
expr = any(LandExpr land | ensuresAux(land, true)).getAnOperand() and
|
||||
expr = any(LandExpr land | this.ensuresAux(land, true)).getAnOperand() and
|
||||
b = true
|
||||
or
|
||||
expr = any(LorExpr lor | ensuresAux(lor, false)).getAnOperand() and
|
||||
expr = any(LorExpr lor | this.ensuresAux(lor, false)).getAnOperand() and
|
||||
b = false
|
||||
}
|
||||
|
||||
/** Holds if this guard ensures that the result of `nd` is `b`. */
|
||||
predicate ensures(DataFlow::Node nd, boolean b) {
|
||||
ensuresAux(any(Expr e | nd = DataFlow::exprNode(e)), b)
|
||||
this.ensuresAux(any(Expr e | nd = DataFlow::exprNode(e)), b)
|
||||
}
|
||||
|
||||
/** Holds if this guard ensures that `lesser <= greater + bias` holds. */
|
||||
predicate ensuresLeq(DataFlow::Node lesser, DataFlow::Node greater, int bias) {
|
||||
exists(DataFlow::RelationalComparisonNode rel, boolean b |
|
||||
ensures(rel, b) and
|
||||
this.ensures(rel, b) and
|
||||
rel.leq(b, lesser, greater, bias)
|
||||
)
|
||||
or
|
||||
ensuresEq(lesser, greater) and
|
||||
this.ensuresEq(lesser, greater) and
|
||||
bias = 0
|
||||
}
|
||||
|
||||
/** Holds if this guard ensures that `i = j` holds. */
|
||||
predicate ensuresEq(DataFlow::Node i, DataFlow::Node j) {
|
||||
exists(DataFlow::EqualityTestNode eq, boolean b |
|
||||
ensures(eq, b) and
|
||||
this.ensures(eq, b) and
|
||||
eq.eq(b, i, j)
|
||||
)
|
||||
}
|
||||
|
@ -221,7 +221,7 @@ module ControlFlow {
|
|||
/** Holds if this guard ensures that `i != j` holds. */
|
||||
predicate ensuresNeq(DataFlow::Node i, DataFlow::Node j) {
|
||||
exists(DataFlow::EqualityTestNode eq, boolean b |
|
||||
ensures(eq, b.booleanNot()) and
|
||||
this.ensures(eq, b.booleanNot()) and
|
||||
eq.eq(b, i, j)
|
||||
)
|
||||
}
|
||||
|
@ -232,7 +232,7 @@ module ControlFlow {
|
|||
*/
|
||||
predicate dominates(ReachableBasicBlock bb) {
|
||||
this = bb.getANode() or
|
||||
dominates(bb.getImmediateDominator())
|
||||
this.dominates(bb.getImmediateDominator())
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -39,7 +39,7 @@ class FunctionInput extends TFunctionInput {
|
|||
predicate isResult(int i) { none() }
|
||||
|
||||
/** Gets the data-flow node corresponding to this input for the call `c`. */
|
||||
final DataFlow::Node getNode(DataFlow::CallNode c) { result = getEntryNode(c) }
|
||||
final DataFlow::Node getNode(DataFlow::CallNode c) { result = this.getEntryNode(c) }
|
||||
|
||||
/** Gets the data-flow node through which data is passed into this input for the call `c`. */
|
||||
abstract DataFlow::Node getEntryNode(DataFlow::CallNode c);
|
||||
|
@ -116,7 +116,7 @@ private class ResultInput extends FunctionInput, TInResult {
|
|||
override predicate isResult() { index = -1 }
|
||||
|
||||
override predicate isResult(int i) {
|
||||
i = 0 and isResult()
|
||||
i = 0 and this.isResult()
|
||||
or
|
||||
i = index and i >= 0
|
||||
}
|
||||
|
@ -180,7 +180,7 @@ class FunctionOutput extends TFunctionOutput {
|
|||
predicate isParameter(int i) { none() }
|
||||
|
||||
/** Gets the data-flow node corresponding to this output for the call `c`. */
|
||||
final DataFlow::Node getNode(DataFlow::CallNode c) { result = getExitNode(c) }
|
||||
final DataFlow::Node getNode(DataFlow::CallNode c) { result = this.getExitNode(c) }
|
||||
|
||||
/** Gets the data-flow node through which data is passed into this output for the function `f`. */
|
||||
abstract DataFlow::Node getEntryNode(FuncDef f);
|
||||
|
@ -216,7 +216,7 @@ private class OutResult extends FunctionOutput, TOutResult {
|
|||
override predicate isResult() { index = -1 }
|
||||
|
||||
override predicate isResult(int i) {
|
||||
i = 0 and isResult()
|
||||
i = 0 and this.isResult()
|
||||
or
|
||||
i = index and i >= 0
|
||||
}
|
||||
|
|
|
@ -300,14 +300,14 @@ class GVN extends GvnBase {
|
|||
// just an arbitrary way to pick an expression with this `GVN`.
|
||||
result =
|
||||
min(DataFlow::Node e, string f, int l, int c, string k |
|
||||
e = getANode() and e.hasLocationInfo(f, l, c, _, _) and k = e.getNodeKind()
|
||||
e = this.getANode() and e.hasLocationInfo(f, l, c, _, _) and k = e.getNodeKind()
|
||||
|
|
||||
e order by f, l, c, k
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = exampleNode().toString() }
|
||||
string toString() { result = this.exampleNode().toString() }
|
||||
|
||||
/**
|
||||
* Holds if this element is at the specified location.
|
||||
|
@ -319,7 +319,7 @@ class GVN extends GvnBase {
|
|||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) {
|
||||
exampleNode().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
this.exampleNode().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -23,16 +23,16 @@ module TestCase {
|
|||
/** A `go test` style test (including benchmarks and examples). */
|
||||
private class GoTestFunction extends Range, FuncDef {
|
||||
GoTestFunction() {
|
||||
getName().regexpMatch("Test(?![a-z]).*") and
|
||||
getNumParameter() = 1 and
|
||||
getParameter(0).getType().(PointerType).getBaseType().hasQualifiedName("testing", "T")
|
||||
this.getName().regexpMatch("Test(?![a-z]).*") and
|
||||
this.getNumParameter() = 1 and
|
||||
this.getParameter(0).getType().(PointerType).getBaseType().hasQualifiedName("testing", "T")
|
||||
or
|
||||
getName().regexpMatch("Benchmark(?![a-z]).*") and
|
||||
getNumParameter() = 1 and
|
||||
getParameter(0).getType().(PointerType).getBaseType().hasQualifiedName("testing", "B")
|
||||
this.getName().regexpMatch("Benchmark(?![a-z]).*") and
|
||||
this.getNumParameter() = 1 and
|
||||
this.getParameter(0).getType().(PointerType).getBaseType().hasQualifiedName("testing", "B")
|
||||
or
|
||||
getName().regexpMatch("Example(?![a-z]).*") and
|
||||
getNumParameter() = 0
|
||||
this.getName().regexpMatch("Example(?![a-z]).*") and
|
||||
this.getNumParameter() = 0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -86,7 +86,7 @@ module Ginkgo {
|
|||
|
||||
/** The Ginkgo `Fail` function, which always panics. */
|
||||
private class FailFunction extends Function {
|
||||
FailFunction() { hasQualifiedName(packagePath(), "Fail") }
|
||||
FailFunction() { this.hasQualifiedName(packagePath(), "Fail") }
|
||||
|
||||
override predicate mustPanic() { any() }
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ module ArchiveTar {
|
|||
|
||||
FunctionModels() {
|
||||
// signature: func NewWriter(w io.Writer) *Writer
|
||||
hasQualifiedName("archive/tar", "NewWriter") and
|
||||
this.hasQualifiedName("archive/tar", "NewWriter") and
|
||||
(inp.isResult() and outp.isParameter(0))
|
||||
}
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ module ArchiveZip {
|
|||
|
||||
FunctionModels() {
|
||||
// signature: func NewWriter(w io.Writer) *Writer
|
||||
hasQualifiedName("archive/zip", "NewWriter") and
|
||||
this.hasQualifiedName("archive/zip", "NewWriter") and
|
||||
(inp.isResult() and outp.isParameter(0))
|
||||
}
|
||||
|
||||
|
@ -28,15 +28,15 @@ module ArchiveZip {
|
|||
|
||||
MethodModels() {
|
||||
// signature: func (*Writer) Create(name string) (io.Writer, error)
|
||||
hasQualifiedName("archive/zip", "Writer", "Create") and
|
||||
this.hasQualifiedName("archive/zip", "Writer", "Create") and
|
||||
(inp.isResult(0) and outp.isReceiver())
|
||||
or
|
||||
// signature: func (*Writer) CreateRaw(fh *FileHeader) (io.Writer, error)
|
||||
hasQualifiedName("archive/zip", "Writer", "CreateRaw") and
|
||||
this.hasQualifiedName("archive/zip", "Writer", "CreateRaw") and
|
||||
(inp.isResult(0) and outp.isReceiver())
|
||||
or
|
||||
// signature: func (*Writer) CreateHeader(fh *FileHeader) (io.Writer, error)
|
||||
hasQualifiedName("archive/zip", "Writer", "CreateHeader") and
|
||||
this.hasQualifiedName("archive/zip", "Writer", "CreateHeader") and
|
||||
(inp.isResult(0) and outp.isReceiver())
|
||||
}
|
||||
|
||||
|
|
|
@ -10,7 +10,7 @@ module Bufio {
|
|||
* The function `bufio.NewScanner`.
|
||||
*/
|
||||
class NewScanner extends Function {
|
||||
NewScanner() { hasQualifiedName("bufio", "NewScanner") }
|
||||
NewScanner() { this.hasQualifiedName("bufio", "NewScanner") }
|
||||
|
||||
/**
|
||||
* Gets the input corresponding to the `io.Reader`
|
||||
|
@ -26,15 +26,15 @@ module Bufio {
|
|||
|
||||
FunctionModels() {
|
||||
// signature: func NewReadWriter(r *Reader, w *Writer) *ReadWriter
|
||||
hasQualifiedName("bufio", "NewReadWriter") and
|
||||
this.hasQualifiedName("bufio", "NewReadWriter") and
|
||||
(inp.isResult() and outp.isParameter(1))
|
||||
or
|
||||
// signature: func NewWriter(w io.Writer) *Writer
|
||||
hasQualifiedName("bufio", "NewWriter") and
|
||||
this.hasQualifiedName("bufio", "NewWriter") and
|
||||
(inp.isResult() and outp.isParameter(0))
|
||||
or
|
||||
// signature: func NewWriterSize(w io.Writer, size int) *Writer
|
||||
hasQualifiedName("bufio", "NewWriterSize") and
|
||||
this.hasQualifiedName("bufio", "NewWriterSize") and
|
||||
(inp.isResult() and outp.isParameter(0))
|
||||
}
|
||||
|
||||
|
|
|
@ -13,11 +13,11 @@ module CompressFlate {
|
|||
|
||||
FunctionModels() {
|
||||
// signature: func NewWriter(w io.Writer, level int) (*Writer, error)
|
||||
hasQualifiedName("compress/flate", "NewWriter") and
|
||||
this.hasQualifiedName("compress/flate", "NewWriter") and
|
||||
(inp.isResult(0) and outp.isParameter(0))
|
||||
or
|
||||
// signature: func NewWriterDict(w io.Writer, level int, dict []byte) (*Writer, error)
|
||||
hasQualifiedName("compress/flate", "NewWriterDict") and
|
||||
this.hasQualifiedName("compress/flate", "NewWriterDict") and
|
||||
(inp.isResult(0) and outp.isParameter(0))
|
||||
}
|
||||
|
||||
|
|
|
@ -13,11 +13,11 @@ module CompressGzip {
|
|||
|
||||
FunctionModels() {
|
||||
// signature: func NewWriter(w io.Writer) *Writer
|
||||
hasQualifiedName("compress/gzip", "NewWriter") and
|
||||
this.hasQualifiedName("compress/gzip", "NewWriter") and
|
||||
(inp.isResult() and outp.isParameter(0))
|
||||
or
|
||||
// signature: func NewWriterLevel(w io.Writer, level int) (*Writer, error)
|
||||
hasQualifiedName("compress/gzip", "NewWriterLevel") and
|
||||
this.hasQualifiedName("compress/gzip", "NewWriterLevel") and
|
||||
(inp.isResult(0) and outp.isParameter(0))
|
||||
}
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ module CompressLzw {
|
|||
|
||||
FunctionModels() {
|
||||
// signature: func NewWriter(w io.Writer, order Order, litWidth int) io.WriteCloser
|
||||
hasQualifiedName("compress/lzw", "NewWriter") and
|
||||
this.hasQualifiedName("compress/lzw", "NewWriter") and
|
||||
(inp.isResult() and outp.isParameter(0))
|
||||
}
|
||||
|
||||
|
|
|
@ -13,15 +13,15 @@ module CompressZlib {
|
|||
|
||||
FunctionModels() {
|
||||
// signature: func NewWriter(w io.Writer) *Writer
|
||||
hasQualifiedName("compress/zlib", "NewWriter") and
|
||||
this.hasQualifiedName("compress/zlib", "NewWriter") and
|
||||
(inp.isResult() and outp.isParameter(0))
|
||||
or
|
||||
// signature: func NewWriterLevel(w io.Writer, level int) (*Writer, error)
|
||||
hasQualifiedName("compress/zlib", "NewWriterLevel") and
|
||||
this.hasQualifiedName("compress/zlib", "NewWriterLevel") and
|
||||
(inp.isResult(0) and outp.isParameter(0))
|
||||
or
|
||||
// signature: func NewWriterLevelDict(w io.Writer, level int, dict []byte) (*Writer, error)
|
||||
hasQualifiedName("compress/zlib", "NewWriterLevelDict") and
|
||||
this.hasQualifiedName("compress/zlib", "NewWriterLevelDict") and
|
||||
(inp.isResult(0) and outp.isParameter(0))
|
||||
}
|
||||
|
||||
|
|
|
@ -13,11 +13,11 @@ module CryptoTls {
|
|||
|
||||
FunctionModels() {
|
||||
// signature: func Client(conn net.Conn, config *Config) *Conn
|
||||
hasQualifiedName("crypto/tls", "Client") and
|
||||
this.hasQualifiedName("crypto/tls", "Client") and
|
||||
(inp.isResult() and outp.isParameter(0))
|
||||
or
|
||||
// signature: func Server(conn net.Conn, config *Config) *Conn
|
||||
hasQualifiedName("crypto/tls", "Server") and
|
||||
this.hasQualifiedName("crypto/tls", "Server") and
|
||||
(inp.isResult() and outp.isParameter(0))
|
||||
}
|
||||
|
||||
|
|
|
@ -9,8 +9,8 @@ module EncodingAsn1 {
|
|||
/** The `Marshal` or `MarshalWithParams` function in the `encoding/asn1` package. */
|
||||
private class MarshalFunction extends MarshalingFunction::Range {
|
||||
MarshalFunction() {
|
||||
hasQualifiedName("encoding/asn1", "Marshal") or
|
||||
hasQualifiedName("encoding/asn1", "MarshalWithParams")
|
||||
this.hasQualifiedName("encoding/asn1", "Marshal") or
|
||||
this.hasQualifiedName("encoding/asn1", "MarshalWithParams")
|
||||
}
|
||||
|
||||
override FunctionInput getAnInput() { result.isParameter(0) }
|
||||
|
@ -23,8 +23,8 @@ module EncodingAsn1 {
|
|||
/** The `Unmarshal` or `UnmarshalWithParams` function in the `encoding/asn1` package. */
|
||||
private class UnmarshalFunction extends UnmarshalingFunction::Range {
|
||||
UnmarshalFunction() {
|
||||
hasQualifiedName("encoding/asn1", "Unmarshal") or
|
||||
hasQualifiedName("encoding/asn1", "UnmarshalWithParams")
|
||||
this.hasQualifiedName("encoding/asn1", "Unmarshal") or
|
||||
this.hasQualifiedName("encoding/asn1", "UnmarshalWithParams")
|
||||
}
|
||||
|
||||
override FunctionInput getAnInput() { result.isParameter(0) }
|
||||
|
|
|
@ -13,7 +13,7 @@ module EncodingCsv {
|
|||
|
||||
FunctionModels() {
|
||||
// signature: func NewWriter(w io.Writer) *Writer
|
||||
hasQualifiedName("encoding/csv", "NewWriter") and
|
||||
this.hasQualifiedName("encoding/csv", "NewWriter") and
|
||||
(inp.isResult() and outp.isParameter(0))
|
||||
}
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ module EncodingGob {
|
|||
|
||||
FunctionModels() {
|
||||
// signature: func NewEncoder(w io.Writer) *Encoder
|
||||
hasQualifiedName("encoding/gob", "NewEncoder") and
|
||||
this.hasQualifiedName("encoding/gob", "NewEncoder") and
|
||||
(inp.isResult() and outp.isParameter(0))
|
||||
}
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@ import go
|
|||
module EncodingPem {
|
||||
/** The `Encode` function in the `encoding/pem` package. */
|
||||
private class EncodeFunction extends MarshalingFunction::Range {
|
||||
EncodeFunction() { hasQualifiedName("encoding/pem", "Encode") }
|
||||
EncodeFunction() { this.hasQualifiedName("encoding/pem", "Encode") }
|
||||
|
||||
override FunctionInput getAnInput() { result.isParameter(1) }
|
||||
|
||||
|
@ -19,7 +19,7 @@ module EncodingPem {
|
|||
|
||||
/** The `EncodeToMemory` function in the `encoding/pem` package. */
|
||||
private class EncodeToMemoryFunction extends MarshalingFunction::Range {
|
||||
EncodeToMemoryFunction() { hasQualifiedName("encoding/pem", "EncodeToMemory") }
|
||||
EncodeToMemoryFunction() { this.hasQualifiedName("encoding/pem", "EncodeToMemory") }
|
||||
|
||||
override FunctionInput getAnInput() { result.isParameter(0) }
|
||||
|
||||
|
@ -30,7 +30,7 @@ module EncodingPem {
|
|||
|
||||
/** The `Decode` function in the `encoding/pem` package. */
|
||||
private class UnmarshalFunction extends UnmarshalingFunction::Range {
|
||||
UnmarshalFunction() { hasQualifiedName("encoding/pem", "Decode") }
|
||||
UnmarshalFunction() { this.hasQualifiedName("encoding/pem", "Decode") }
|
||||
|
||||
override FunctionInput getAnInput() { result.isParameter(0) }
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ module Errors {
|
|||
|
||||
FunctionModels() {
|
||||
// signature: func Join(errs ...error) error
|
||||
hasQualifiedName("errors", "Join") and
|
||||
this.hasQualifiedName("errors", "Join") and
|
||||
(inp.isParameter(_) and outp.isResult())
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ import go
|
|||
/** Provides models of commonly used functions in the `html` package. */
|
||||
module Html {
|
||||
private class Escape extends EscapeFunction::Range {
|
||||
Escape() { hasQualifiedName("html", "EscapeString") }
|
||||
Escape() { this.hasQualifiedName("html", "EscapeString") }
|
||||
|
||||
override string kind() { result = "html" }
|
||||
}
|
||||
|
|
|
@ -13,15 +13,15 @@ module Io {
|
|||
|
||||
FunctionModels() {
|
||||
// signature: func MultiReader(readers ...Reader) Reader
|
||||
hasQualifiedName("io", "MultiReader") and
|
||||
this.hasQualifiedName("io", "MultiReader") and
|
||||
(inp.isParameter(_) and outp.isResult())
|
||||
or
|
||||
// signature: func MultiWriter(writers ...Writer) Writer
|
||||
hasQualifiedName("io", "MultiWriter") and
|
||||
this.hasQualifiedName("io", "MultiWriter") and
|
||||
(inp.isResult() and outp.isParameter(_))
|
||||
or
|
||||
// signature: func Pipe() (*PipeReader, *PipeWriter)
|
||||
hasQualifiedName("io", "Pipe") and
|
||||
this.hasQualifiedName("io", "Pipe") and
|
||||
(inp.isResult(1) and outp.isResult(0))
|
||||
}
|
||||
|
||||
|
|
|
@ -8,11 +8,11 @@ import go
|
|||
module IoIoutil {
|
||||
private class IoUtilFileSystemAccess extends FileSystemAccess::Range, DataFlow::CallNode {
|
||||
IoUtilFileSystemAccess() {
|
||||
exists(string fn | getTarget().hasQualifiedName("io/ioutil", fn) |
|
||||
exists(string fn | this.getTarget().hasQualifiedName("io/ioutil", fn) |
|
||||
fn = ["ReadDir", "ReadFile", "TempDir", "TempFile", "WriteFile"]
|
||||
)
|
||||
}
|
||||
|
||||
override DataFlow::Node getAPathArgument() { result = getAnArgument() }
|
||||
override DataFlow::Node getAPathArgument() { result = this.getAnArgument() }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@ module MimeMultipart {
|
|||
|
||||
FunctionModels() {
|
||||
// signature: func NewWriter(w io.Writer) *Writer
|
||||
hasQualifiedName("mime/multipart", "NewWriter") and
|
||||
this.hasQualifiedName("mime/multipart", "NewWriter") and
|
||||
(inp.isResult() and outp.isParameter(0))
|
||||
}
|
||||
|
||||
|
@ -28,15 +28,15 @@ module MimeMultipart {
|
|||
|
||||
MethodModels() {
|
||||
// signature: func (*Writer) CreateFormField(fieldname string) (io.Writer, error)
|
||||
hasQualifiedName("mime/multipart", "Writer", "CreateFormField") and
|
||||
this.hasQualifiedName("mime/multipart", "Writer", "CreateFormField") and
|
||||
(inp.isResult(0) and outp.isReceiver())
|
||||
or
|
||||
// signature: func (*Writer) CreateFormFile(fieldname string, filename string) (io.Writer, error)
|
||||
hasQualifiedName("mime/multipart", "Writer", "CreateFormFile") and
|
||||
this.hasQualifiedName("mime/multipart", "Writer", "CreateFormFile") and
|
||||
(inp.isResult(0) and outp.isReceiver())
|
||||
or
|
||||
// signature: func (*Writer) CreatePart(header net/textproto.MIMEHeader) (io.Writer, error)
|
||||
hasQualifiedName("mime/multipart", "Writer", "CreatePart") and
|
||||
this.hasQualifiedName("mime/multipart", "Writer", "CreatePart") and
|
||||
(inp.isResult(0) and outp.isReceiver())
|
||||
}
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ module MimeQuotedprintable {
|
|||
|
||||
FunctionModels() {
|
||||
// signature: func NewWriter(w io.Writer) *Writer
|
||||
hasQualifiedName("mime/quotedprintable", "NewWriter") and
|
||||
this.hasQualifiedName("mime/quotedprintable", "NewWriter") and
|
||||
(inp.isResult() and outp.isParameter(0))
|
||||
}
|
||||
|
||||
|
|
|
@ -13,15 +13,15 @@ module Net {
|
|||
|
||||
FunctionModels() {
|
||||
// signature: func FileConn(f *os.File) (c Conn, err error)
|
||||
hasQualifiedName("net", "FileConn") and
|
||||
this.hasQualifiedName("net", "FileConn") and
|
||||
(inp.isResult(0) and outp.isParameter(0))
|
||||
or
|
||||
// signature: func FilePacketConn(f *os.File) (c PacketConn, err error)
|
||||
hasQualifiedName("net", "FilePacketConn") and
|
||||
this.hasQualifiedName("net", "FilePacketConn") and
|
||||
(inp.isResult(0) and outp.isParameter(0))
|
||||
or
|
||||
// signature: func Pipe() (Conn, Conn)
|
||||
hasQualifiedName("net", "Pipe") and
|
||||
this.hasQualifiedName("net", "Pipe") and
|
||||
(
|
||||
inp.isResult(0) and outp.isResult(1)
|
||||
or
|
||||
|
@ -40,35 +40,35 @@ module Net {
|
|||
|
||||
MethodModels() {
|
||||
// signature: func (*IPConn) SyscallConn() (syscall.RawConn, error)
|
||||
hasQualifiedName("net", "IPConn", "SyscallConn") and
|
||||
this.hasQualifiedName("net", "IPConn", "SyscallConn") and
|
||||
(inp.isResult(0) and outp.isReceiver())
|
||||
or
|
||||
// signature: func (*TCPConn) SyscallConn() (syscall.RawConn, error)
|
||||
hasQualifiedName("net", "TCPConn", "SyscallConn") and
|
||||
this.hasQualifiedName("net", "TCPConn", "SyscallConn") and
|
||||
(inp.isResult(0) and outp.isReceiver())
|
||||
or
|
||||
// signature: func (*TCPListener) File() (f *os.File, err error)
|
||||
hasQualifiedName("net", "TCPListener", "File") and
|
||||
this.hasQualifiedName("net", "TCPListener", "File") and
|
||||
(inp.isResult(0) and outp.isReceiver())
|
||||
or
|
||||
// signature: func (*TCPListener) SyscallConn() (syscall.RawConn, error)
|
||||
hasQualifiedName("net", "TCPListener", "SyscallConn") and
|
||||
this.hasQualifiedName("net", "TCPListener", "SyscallConn") and
|
||||
(inp.isResult(0) and outp.isReceiver())
|
||||
or
|
||||
// signature: func (*UDPConn) SyscallConn() (syscall.RawConn, error)
|
||||
hasQualifiedName("net", "UDPConn", "SyscallConn") and
|
||||
this.hasQualifiedName("net", "UDPConn", "SyscallConn") and
|
||||
(inp.isResult(0) and outp.isReceiver())
|
||||
or
|
||||
// signature: func (*UnixConn) SyscallConn() (syscall.RawConn, error)
|
||||
hasQualifiedName("net", "UnixConn", "SyscallConn") and
|
||||
this.hasQualifiedName("net", "UnixConn", "SyscallConn") and
|
||||
(inp.isResult(0) and outp.isReceiver())
|
||||
or
|
||||
// signature: func (*UnixListener) File() (f *os.File, err error)
|
||||
hasQualifiedName("net", "UnixListener", "File") and
|
||||
this.hasQualifiedName("net", "UnixListener", "File") and
|
||||
(inp.isResult(0) and outp.isReceiver())
|
||||
or
|
||||
// signature: func (*UnixListener) SyscallConn() (syscall.RawConn, error)
|
||||
hasQualifiedName("net", "UnixListener", "SyscallConn") and
|
||||
this.hasQualifiedName("net", "UnixListener", "SyscallConn") and
|
||||
(inp.isResult(0) and outp.isReceiver())
|
||||
}
|
||||
|
||||
|
|
|
@ -13,15 +13,15 @@ module NetHttpHttputil {
|
|||
|
||||
FunctionModels() {
|
||||
// signature: func NewChunkedWriter(w io.Writer) io.WriteCloser
|
||||
hasQualifiedName("net/http/httputil", "NewChunkedWriter") and
|
||||
this.hasQualifiedName("net/http/httputil", "NewChunkedWriter") and
|
||||
(inp.isResult() and outp.isParameter(0))
|
||||
or
|
||||
// signature: func NewClientConn(c net.Conn, r *bufio.Reader) *ClientConn
|
||||
hasQualifiedName("net/http/httputil", "NewClientConn") and
|
||||
this.hasQualifiedName("net/http/httputil", "NewClientConn") and
|
||||
(inp.isResult() and outp.isParameter(0))
|
||||
or
|
||||
// signature: func NewProxyClientConn(c net.Conn, r *bufio.Reader) *ClientConn
|
||||
hasQualifiedName("net/http/httputil", "NewProxyClientConn") and
|
||||
this.hasQualifiedName("net/http/httputil", "NewProxyClientConn") and
|
||||
(inp.isResult() and outp.isParameter(0))
|
||||
}
|
||||
|
||||
|
@ -36,11 +36,11 @@ module NetHttpHttputil {
|
|||
|
||||
MethodModels() {
|
||||
// signature: func (*ClientConn) Hijack() (c net.Conn, r *bufio.Reader)
|
||||
hasQualifiedName("net/http/httputil", "ClientConn", "Hijack") and
|
||||
this.hasQualifiedName("net/http/httputil", "ClientConn", "Hijack") and
|
||||
(inp.isResult(0) and outp.isReceiver())
|
||||
or
|
||||
// signature: func (*ServerConn) Hijack() (net.Conn, *bufio.Reader)
|
||||
hasQualifiedName("net/http/httputil", "ServerConn", "Hijack") and
|
||||
this.hasQualifiedName("net/http/httputil", "ServerConn", "Hijack") and
|
||||
(inp.isResult(0) and outp.isReceiver())
|
||||
}
|
||||
|
||||
|
|
|
@ -13,11 +13,11 @@ module NetTextproto {
|
|||
|
||||
FunctionModels() {
|
||||
// signature: func NewConn(conn io.ReadWriteCloser) *Conn
|
||||
hasQualifiedName("net/textproto", "NewConn") and
|
||||
this.hasQualifiedName("net/textproto", "NewConn") and
|
||||
(inp.isResult() and outp.isParameter(0))
|
||||
or
|
||||
// signature: func NewWriter(w *bufio.Writer) *Writer
|
||||
hasQualifiedName("net/textproto", "NewWriter") and
|
||||
this.hasQualifiedName("net/textproto", "NewWriter") and
|
||||
(inp.isResult() and outp.isParameter(0))
|
||||
}
|
||||
|
||||
|
@ -32,11 +32,11 @@ module NetTextproto {
|
|||
|
||||
MethodModels() {
|
||||
// signature: func (*Writer) DotWriter() io.WriteCloser
|
||||
hasQualifiedName("net/textproto", "Writer", "DotWriter") and
|
||||
this.hasQualifiedName("net/textproto", "Writer", "DotWriter") and
|
||||
(inp.isResult() and outp.isReceiver())
|
||||
or
|
||||
// signature: func (*Writer) PrintfLine(format string, args ...interface{}) error
|
||||
hasQualifiedName("net/textproto", "Writer", "PrintfLine") and
|
||||
this.hasQualifiedName("net/textproto", "Writer", "PrintfLine") and
|
||||
(inp.isParameter(_) and outp.isReceiver())
|
||||
}
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ module Os {
|
|||
int pathidx;
|
||||
|
||||
OsFileSystemAccess() {
|
||||
exists(string fn | getTarget().hasQualifiedName("os", fn) |
|
||||
exists(string fn | this.getTarget().hasQualifiedName("os", fn) |
|
||||
fn = "Chdir" and pathidx = 0
|
||||
or
|
||||
fn = "Chmod" and pathidx = 0
|
||||
|
@ -68,12 +68,12 @@ module Os {
|
|||
)
|
||||
}
|
||||
|
||||
override DataFlow::Node getAPathArgument() { result = getArgument(pathidx) }
|
||||
override DataFlow::Node getAPathArgument() { result = this.getArgument(pathidx) }
|
||||
}
|
||||
|
||||
/** The `os.Exit` function, which ends the process. */
|
||||
private class Exit extends Function {
|
||||
Exit() { hasQualifiedName("os", "Exit") }
|
||||
Exit() { this.hasQualifiedName("os", "Exit") }
|
||||
|
||||
override predicate mayReturnNormally() { none() }
|
||||
}
|
||||
|
@ -85,7 +85,7 @@ module Os {
|
|||
|
||||
FunctionModels() {
|
||||
// signature: func Pipe() (r *File, w *File, err error)
|
||||
hasQualifiedName("os", "Pipe") and
|
||||
this.hasQualifiedName("os", "Pipe") and
|
||||
(inp.isResult(1) and outp.isResult(0))
|
||||
}
|
||||
|
||||
|
@ -100,7 +100,7 @@ module Os {
|
|||
|
||||
MethodModels() {
|
||||
// signature: func (*File) SyscallConn() (syscall.RawConn, error)
|
||||
hasQualifiedName("os", "File", "SyscallConn") and
|
||||
this.hasQualifiedName("os", "File", "SyscallConn") and
|
||||
(inp.isResult(0) and outp.isReceiver())
|
||||
}
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ module Path {
|
|||
|
||||
FunctionModels() {
|
||||
// signature: func Join(elem ...string) string
|
||||
hasQualifiedName("path", "Join") and
|
||||
this.hasQualifiedName("path", "Join") and
|
||||
(inp.isParameter(_) and outp.isResult())
|
||||
}
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ module PathFilepath {
|
|||
|
||||
FunctionModels() {
|
||||
// signature: func Join(elem ...string) string
|
||||
hasQualifiedName("path/filepath", "Join") and
|
||||
this.hasQualifiedName("path/filepath", "Join") and
|
||||
(inp.isParameter(_) and outp.isResult())
|
||||
}
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ module Reflect {
|
|||
|
||||
FunctionModels() {
|
||||
// signature: func Append(s Value, x ...Value) Value
|
||||
hasQualifiedName("reflect", "Append") and
|
||||
this.hasQualifiedName("reflect", "Append") and
|
||||
(inp.isParameter(_) and outp.isResult())
|
||||
}
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ module Strings {
|
|||
|
||||
FunctionModels() {
|
||||
// signature: func NewReplacer(oldnew ...string) *Replacer
|
||||
hasQualifiedName("strings", "NewReplacer") and
|
||||
this.hasQualifiedName("strings", "NewReplacer") and
|
||||
(inp.isParameter(_) and outp.isResult())
|
||||
}
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ module Syscall {
|
|||
|
||||
MethodModels() {
|
||||
// signature: func (Conn) SyscallConn() (RawConn, error)
|
||||
implements("syscall", "Conn", "SyscallConn") and
|
||||
this.implements("syscall", "Conn", "SyscallConn") and
|
||||
(inp.isResult(0) and outp.isReceiver())
|
||||
}
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ module TextTabwriter {
|
|||
|
||||
FunctionModels() {
|
||||
// signature: func NewWriter(output io.Writer, minwidth int, tabwidth int, padding int, padchar byte, flags uint) *Writer
|
||||
hasQualifiedName("text/tabwriter", "NewWriter") and
|
||||
this.hasQualifiedName("text/tabwriter", "NewWriter") and
|
||||
(inp.isResult() and outp.isParameter(0))
|
||||
}
|
||||
|
||||
|
@ -28,7 +28,7 @@ module TextTabwriter {
|
|||
|
||||
MethodModels() {
|
||||
// signature: func (*Writer) Init(output io.Writer, minwidth int, tabwidth int, padding int, padchar byte, flags uint) *Writer
|
||||
hasQualifiedName("text/tabwriter", "Writer", "Init") and
|
||||
this.hasQualifiedName("text/tabwriter", "Writer", "Init") and
|
||||
(
|
||||
inp.isResult() and
|
||||
outp.isParameter(0)
|
||||
|
|
|
@ -11,7 +11,7 @@ module Unsafe {
|
|||
FunctionOutput outp;
|
||||
|
||||
FunctionModels() {
|
||||
hasQualifiedName("unsafe", ["String", "StringData", "Slice", "SliceData"]) and
|
||||
this.hasQualifiedName("unsafe", ["String", "StringData", "Slice", "SliceData"]) and
|
||||
(inp.isParameter(0) and outp.isResult())
|
||||
}
|
||||
|
||||
|
|
|
@ -52,7 +52,7 @@ module AllocationSizeOverflow {
|
|||
nd.(Sink).getAllocationSize() = allocsz
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node nd) { isSinkWithAllocationSize(nd, _) }
|
||||
override predicate isSink(DataFlow::Node nd) { this.isSinkWithAllocationSize(nd, _) }
|
||||
|
||||
override predicate isAdditionalTaintStep(DataFlow::Node pred, DataFlow::Node succ) {
|
||||
additionalStep(pred, succ)
|
||||
|
|
|
@ -24,22 +24,22 @@ module InsecureFeatureFlag {
|
|||
/** Gets a global value number representing a (likely) security flag. */
|
||||
GVN getAFlag() {
|
||||
// a call like `cfg.disableVerification()`
|
||||
exists(DataFlow::CallNode c | c.getTarget().getName() = getAFlagName() |
|
||||
exists(DataFlow::CallNode c | c.getTarget().getName() = this.getAFlagName() |
|
||||
result = globalValueNumber(c)
|
||||
)
|
||||
or
|
||||
// a variable or field like `insecure`
|
||||
exists(ValueEntity flag | flag.getName() = getAFlagName() |
|
||||
exists(ValueEntity flag | flag.getName() = this.getAFlagName() |
|
||||
result = globalValueNumber(flag.getARead())
|
||||
)
|
||||
or
|
||||
// a string constant such as `"insecure"` or `"skipVerification"`
|
||||
exists(DataFlow::Node const | const.getStringValue() = getAFlagName() |
|
||||
exists(DataFlow::Node const | const.getStringValue() = this.getAFlagName() |
|
||||
result = globalValueNumber(const)
|
||||
)
|
||||
or
|
||||
// track feature flags through various operations
|
||||
exists(DataFlow::Node flag | flag = getAFlag().getANode() |
|
||||
exists(DataFlow::Node flag | flag = this.getAFlag().getANode() |
|
||||
// tuple destructurings
|
||||
result = globalValueNumber(DataFlow::extractTupleElement(flag, _))
|
||||
or
|
||||
|
|
|
@ -69,8 +69,8 @@ module UnsafeUnzipSymlink {
|
|||
/** A file name from a zip or tar entry, as a source for unsafe unzipping of symlinks. */
|
||||
class FileNameSource extends FilenameWithSymlinks, DataFlow::FieldReadNode {
|
||||
FileNameSource() {
|
||||
getField().hasQualifiedName("archive/zip", "File", ["Name", "Data"]) or
|
||||
getField().hasQualifiedName("archive/tar", "Header", ["Name", "Linkname"])
|
||||
this.getField().hasQualifiedName("archive/zip", "File", ["Name", "Data"]) or
|
||||
this.getField().hasQualifiedName("archive/tar", "Header", ["Name", "Linkname"])
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ abstract class HashRoot extends AstNode { }
|
|||
class HashableNode extends AstNode {
|
||||
HashableNode() {
|
||||
this instanceof HashRoot or
|
||||
getParent() instanceof HashableNode
|
||||
this.getParent() instanceof HashableNode
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -72,13 +72,15 @@ class HashableNode extends AstNode {
|
|||
* An AST node without any children.
|
||||
*/
|
||||
class HashableNullaryNode extends HashableNode {
|
||||
HashableNullaryNode() { not exists(getAChild()) }
|
||||
HashableNullaryNode() { not exists(this.getAChild()) }
|
||||
|
||||
/** Holds if this node has the given `kind` and `value`. */
|
||||
predicate unpack(int kind, string value) { kind = getKind() and value = getValue() }
|
||||
predicate unpack(int kind, string value) { kind = this.getKind() and value = this.getValue() }
|
||||
|
||||
override HashedNode hash() {
|
||||
exists(int kind, string value | unpack(kind, value) | result = MkHashedNullaryNode(kind, value))
|
||||
exists(int kind, string value | this.unpack(kind, value) |
|
||||
result = MkHashedNullaryNode(kind, value)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -86,15 +88,17 @@ class HashableNullaryNode extends HashableNode {
|
|||
* An AST node with exactly one child, which is at position zero.
|
||||
*/
|
||||
class HashableUnaryNode extends HashableNode {
|
||||
HashableUnaryNode() { getNumChild() = 1 and exists(getChild(0)) }
|
||||
HashableUnaryNode() { this.getNumChild() = 1 and exists(this.getChild(0)) }
|
||||
|
||||
/** Holds if this node has the given `kind` and `value`, and `child` is its only child. */
|
||||
predicate unpack(int kind, string value, HashedNode child) {
|
||||
kind = getKind() and value = getValue() and child = getChild(0).(HashableNode).hash()
|
||||
kind = this.getKind() and
|
||||
value = this.getValue() and
|
||||
child = this.getChild(0).(HashableNode).hash()
|
||||
}
|
||||
|
||||
override HashedNode hash() {
|
||||
exists(int kind, string value, HashedNode child | unpack(kind, value, child) |
|
||||
exists(int kind, string value, HashedNode child | this.unpack(kind, value, child) |
|
||||
result = MkHashedUnaryNode(kind, value, child)
|
||||
)
|
||||
}
|
||||
|
@ -104,19 +108,21 @@ class HashableUnaryNode extends HashableNode {
|
|||
* An AST node with exactly two children, which are at positions zero and one.
|
||||
*/
|
||||
class HashableBinaryNode extends HashableNode {
|
||||
HashableBinaryNode() { getNumChild() = 2 and exists(getChild(0)) and exists(getChild(1)) }
|
||||
HashableBinaryNode() {
|
||||
this.getNumChild() = 2 and exists(this.getChild(0)) and exists(this.getChild(1))
|
||||
}
|
||||
|
||||
/** Holds if this node has the given `kind` and `value`, and `left` and `right` are its children. */
|
||||
predicate unpack(int kind, string value, HashedNode left, HashedNode right) {
|
||||
kind = getKind() and
|
||||
value = getValue() and
|
||||
left = getChild(0).(HashableNode).hash() and
|
||||
right = getChild(1).(HashableNode).hash()
|
||||
kind = this.getKind() and
|
||||
value = this.getValue() and
|
||||
left = this.getChild(0).(HashableNode).hash() and
|
||||
right = this.getChild(1).(HashableNode).hash()
|
||||
}
|
||||
|
||||
override HashedNode hash() {
|
||||
exists(int kind, string value, HashedNode left, HashedNode right |
|
||||
unpack(kind, value, left, right)
|
||||
this.unpack(kind, value, left, right)
|
||||
|
|
||||
result = MkHashedBinaryNode(kind, value, left, right)
|
||||
)
|
||||
|
@ -128,33 +134,35 @@ class HashableBinaryNode extends HashableNode {
|
|||
*/
|
||||
class HashableNAryNode extends HashableNode {
|
||||
HashableNAryNode() {
|
||||
exists(int n | n = strictcount(getAChild()) | n > 2 or not exists(getChild([0 .. n - 1])))
|
||||
exists(int n | n = strictcount(this.getAChild()) |
|
||||
n > 2 or not exists(this.getChild([0 .. n - 1]))
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if this node has the given `kind`, `value`, and `children`. */
|
||||
predicate unpack(int kind, string value, HashedChildren children) {
|
||||
kind = getKind() and value = getValue() and children = hashChildren()
|
||||
kind = this.getKind() and value = this.getValue() and children = this.hashChildren()
|
||||
}
|
||||
|
||||
/** Holds if `child` is the `i`th child of this node, and `rest` are its subsequent children. */
|
||||
predicate childAt(int i, HashedNode child, HashedChildren rest) {
|
||||
child = getChild(i).(HashableNode).hash() and rest = hashChildren(i + 1)
|
||||
child = this.getChild(i).(HashableNode).hash() and rest = this.hashChildren(i + 1)
|
||||
}
|
||||
|
||||
override HashedNode hash() {
|
||||
exists(int kind, string value, HashedChildren children | unpack(kind, value, children) |
|
||||
exists(int kind, string value, HashedChildren children | this.unpack(kind, value, children) |
|
||||
result = MkHashedNAryNode(kind, value, children)
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets the hash of this node's children. */
|
||||
private HashedChildren hashChildren() { result = hashChildren(0) }
|
||||
private HashedChildren hashChildren() { result = this.hashChildren(0) }
|
||||
|
||||
/** Gets the hash of this node's children, starting with the `i`th child. */
|
||||
private HashedChildren hashChildren(int i) {
|
||||
i = max(int n | exists(getChild(n))) + 1 and result = Nil()
|
||||
i = max(int n | exists(this.getChild(n))) + 1 and result = Nil()
|
||||
or
|
||||
exists(HashedNode child, HashedChildren rest | childAt(i, child, rest) |
|
||||
exists(HashedNode child, HashedChildren rest | this.childAt(i, child, rest) |
|
||||
result = AHashedChild(i, child, rest)
|
||||
)
|
||||
}
|
||||
|
|
|
@ -19,7 +19,7 @@ import Clones
|
|||
*/
|
||||
abstract class PotentiallyRedundantExpr extends BinaryExpr, HashRoot {
|
||||
predicate operands(Expr left, Expr right) {
|
||||
left = getLeftOperand() and right = getRightOperand()
|
||||
left = this.getLeftOperand() and right = this.getRightOperand()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -40,9 +40,9 @@ class IdemnecantExpr extends PotentiallyRedundantExpr {
|
|||
this instanceof XorExpr or
|
||||
this instanceof AndNotExpr
|
||||
) and
|
||||
getLeftOperand().getKind() = getRightOperand().getKind() and
|
||||
this.getLeftOperand().getKind() = this.getRightOperand().getKind() and
|
||||
// exclude trivial cases like `1-1`
|
||||
not getLeftOperand().stripParens() instanceof BasicLit
|
||||
not this.getLeftOperand().stripParens() instanceof BasicLit
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -56,7 +56,7 @@ class IdempotentExpr extends PotentiallyRedundantExpr {
|
|||
this instanceof BitAndExpr or
|
||||
this instanceof BitOrExpr
|
||||
) and
|
||||
getLeftOperand().getKind() = getRightOperand().getKind()
|
||||
this.getLeftOperand().getKind() = this.getRightOperand().getKind()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -68,12 +68,12 @@ class AverageExpr extends PotentiallyRedundantExpr, AddExpr {
|
|||
exists(DivExpr div |
|
||||
this = div.getLeftOperand().stripParens() and
|
||||
div.getRightOperand().getNumericValue() = 2 and
|
||||
getLeftOperand().getKind() = getRightOperand().getKind()
|
||||
this.getLeftOperand().getKind() = this.getRightOperand().getKind()
|
||||
)
|
||||
}
|
||||
|
||||
override predicate operands(Expr left, Expr right) {
|
||||
left = getLeftOperand() and right = getRightOperand()
|
||||
left = this.getLeftOperand() and right = this.getRightOperand()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@ import Clones
|
|||
* An assignment that may be a self assignment.
|
||||
*/
|
||||
class PotentialSelfAssignment extends HashRoot, AssignStmt {
|
||||
PotentialSelfAssignment() { getLhs().getKind() = getRhs().getKind() }
|
||||
PotentialSelfAssignment() { this.getLhs().getKind() = this.getRhs().getKind() }
|
||||
}
|
||||
|
||||
from PotentialSelfAssignment assgn, HashableNode rhs
|
||||
|
|
|
@ -95,7 +95,7 @@ class Config extends DataFlow::Configuration {
|
|||
)
|
||||
}
|
||||
|
||||
override predicate isSource(DataFlow::Node source) { isSourceString(source, _) }
|
||||
override predicate isSource(DataFlow::Node source) { this.isSourceString(source, _) }
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) {
|
||||
sink instanceof RegexpPattern and
|
||||
|
|
|
@ -71,7 +71,7 @@ class Config extends DataFlow::Configuration {
|
|||
)
|
||||
}
|
||||
|
||||
override predicate isSource(DataFlow::Node source) { isSourceString(source, _) }
|
||||
override predicate isSource(DataFlow::Node source) { this.isSourceString(source, _) }
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) { sink instanceof RegexpPattern }
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@ class Config extends DataFlow::Configuration {
|
|||
report = "a literal backspace \\b; did you mean \\\\b, a word boundary?"
|
||||
}
|
||||
|
||||
override predicate isSource(DataFlow::Node source) { isSourceString(source, _) }
|
||||
override predicate isSource(DataFlow::Node source) { this.isSourceString(source, _) }
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) { sink instanceof RegexpPattern }
|
||||
}
|
||||
|
|
|
@ -75,9 +75,9 @@ class TlsVersionFlowConfig extends TaintTracking::Configuration {
|
|||
fieldWrite.writesField(base, fld, sink)
|
||||
}
|
||||
|
||||
override predicate isSource(DataFlow::Node source) { intIsSource(source, _) }
|
||||
override predicate isSource(DataFlow::Node source) { this.intIsSource(source, _) }
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) { isSink(sink, _, _, _) }
|
||||
override predicate isSink(DataFlow::Node sink) { this.isSink(sink, _, _, _) }
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -188,9 +188,9 @@ class TlsInsecureCipherSuitesFlowConfig extends TaintTracking::Configuration {
|
|||
}
|
||||
|
||||
override predicate isSource(DataFlow::Node source) {
|
||||
isSourceInsecureCipherSuites(source)
|
||||
this.isSourceInsecureCipherSuites(source)
|
||||
or
|
||||
isSourceValueEntity(source, _)
|
||||
this.isSourceValueEntity(source, _)
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -201,7 +201,7 @@ class TlsInsecureCipherSuitesFlowConfig extends TaintTracking::Configuration {
|
|||
fieldWrite.writesField(base, fld, sink)
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) { isSink(sink, _, _, _) }
|
||||
override predicate isSink(DataFlow::Node sink) { this.isSink(sink, _, _, _) }
|
||||
|
||||
/**
|
||||
* Declare sinks as out-sanitizers in order to avoid producing superfluous paths where a cipher
|
||||
|
@ -209,7 +209,7 @@ class TlsInsecureCipherSuitesFlowConfig extends TaintTracking::Configuration {
|
|||
* suites.
|
||||
*/
|
||||
override predicate isSanitizerOut(DataFlow::Node node) {
|
||||
super.isSanitizerOut(node) or isSink(node)
|
||||
super.isSanitizerOut(node) or this.isSink(node)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -63,7 +63,7 @@ class FlowConfFromUntrustedToPassthroughTypeConversion extends TaintTracking::Co
|
|||
)
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) { isSinkToPassthroughType(sink, dstTypeName) }
|
||||
override predicate isSink(DataFlow::Node sink) { this.isSinkToPassthroughType(sink, dstTypeName) }
|
||||
|
||||
override predicate isSanitizer(DataFlow::Node sanitizer) {
|
||||
sanitizer instanceof SharedXss::Sanitizer or sanitizer.getType() instanceof NumericType
|
||||
|
@ -104,7 +104,7 @@ class FlowConfPassthroughTypeConversionToTemplateExecutionCall extends TaintTrac
|
|||
PassthroughTypeName getDstTypeName() { result = dstTypeName }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) {
|
||||
isSourceConversionToPassthroughType(source, dstTypeName)
|
||||
this.isSourceConversionToPassthroughType(source, dstTypeName)
|
||||
}
|
||||
|
||||
private predicate isSourceConversionToPassthroughType(
|
||||
|
|
|
@ -35,7 +35,7 @@ Type getBaseType(Type typ) {
|
|||
|
||||
/* A conversion to a `unsafe.Pointer` */
|
||||
class ConversionToUnsafePointer extends DataFlow::TypeCastNode {
|
||||
ConversionToUnsafePointer() { getFinalType(getResultType()) instanceof UnsafePointerType }
|
||||
ConversionToUnsafePointer() { getFinalType(this.getResultType()) instanceof UnsafePointerType }
|
||||
}
|
||||
|
||||
/* Type casting from a `unsafe.Pointer`.*/
|
||||
|
@ -51,9 +51,9 @@ class UnsafeTypeCastingConf extends TaintTracking::Configuration {
|
|||
sink = ca
|
||||
}
|
||||
|
||||
override predicate isSource(DataFlow::Node source) { conversionIsSource(source, _) }
|
||||
override predicate isSource(DataFlow::Node source) { this.conversionIsSource(source, _) }
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) { typeCastNodeIsSink(sink, _) }
|
||||
override predicate isSink(DataFlow::Node sink) { this.typeCastNodeIsSink(sink, _) }
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -6,7 +6,7 @@ import go
|
|||
|
||||
/* A special helper function used inside the test code */
|
||||
class Link extends TaintTracking::FunctionModel {
|
||||
Link() { hasQualifiedName(_, "link") }
|
||||
Link() { this.hasQualifiedName(_, "link") }
|
||||
|
||||
override predicate hasTaintFlow(FunctionInput inp, FunctionOutput outp) {
|
||||
inp.isParameter(0) and outp.isParameter(1)
|
||||
|
|
|
@ -26,9 +26,9 @@ class TaintTransitsFunctionConfig extends TaintTracking::Configuration {
|
|||
)
|
||||
}
|
||||
|
||||
override predicate isSource(DataFlow::Node n) { isSourceSinkPair(n, _) }
|
||||
override predicate isSource(DataFlow::Node n) { this.isSourceSinkPair(n, _) }
|
||||
|
||||
override predicate isSink(DataFlow::Node n) { isSourceSinkPair(_, n) }
|
||||
override predicate isSink(DataFlow::Node n) { this.isSourceSinkPair(_, n) }
|
||||
}
|
||||
|
||||
class TaintFunctionModelTest extends InlineExpectationsTest {
|
||||
|
|
Загрузка…
Ссылка в новой задаче