mirror of
https://github.com/github/codeql.git
synced 2026-04-22 23:35:14 +02:00
QL: Add codeql-go sources (4cae4b23fc)
This commit is contained in:
@@ -1 +1 @@
|
||||
abe3f2148b92b1a94a0a3676cb4dab7d9211076f
|
||||
4cae4b23fc1b2b1760e259b660996e9bb5573279
|
||||
|
||||
@@ -223,6 +223,8 @@ errors(unique int id: @error, int kind: int ref, string msg: string ref, string
|
||||
|
||||
has_ellipsis(int id: @callorconversionexpr ref);
|
||||
|
||||
variadic(int id: @signaturetype ref);
|
||||
|
||||
@container = @file | @folder;
|
||||
|
||||
@locatable = @xmllocatable | @node | @localscope;
|
||||
|
||||
@@ -60,10 +60,10 @@ class CommentGroup extends @comment_group, AstNode {
|
||||
Comment getComment(int i) { comments(result, _, this, i, _) }
|
||||
|
||||
/** Gets a comment in this group. */
|
||||
Comment getAComment() { result = getComment(_) }
|
||||
Comment getAComment() { result = this.getComment(_) }
|
||||
|
||||
/** Gets the number of comments in this group. */
|
||||
int getNumComment() { result = count(getAComment()) }
|
||||
int getNumComment() { result = count(this.getAComment()) }
|
||||
|
||||
override string toString() { result = "comment group" }
|
||||
|
||||
@@ -219,8 +219,8 @@ class BuildConstraintComment extends LineComment {
|
||||
override string getAPrimaryQlClass() { result = "BuildConstraintComment" }
|
||||
|
||||
/** Gets the body of this build constraint. */
|
||||
string getConstraintBody() { result = getText().splitAt("build ", 1) }
|
||||
string getConstraintBody() { result = this.getText().splitAt("build ", 1) }
|
||||
|
||||
/** Gets a disjunct of this build constraint. */
|
||||
string getADisjunct() { result = getConstraintBody().splitAt(" ") }
|
||||
string getADisjunct() { result = this.getConstraintBody().splitAt(" ") }
|
||||
}
|
||||
|
||||
@@ -42,12 +42,12 @@ class GenDecl extends @gendecl, Decl, Documentable {
|
||||
Spec getSpec(int i) { specs(result, _, this, i) }
|
||||
|
||||
/** Gets a declaration specifier in this declaration. */
|
||||
Spec getASpec() { result = getSpec(_) }
|
||||
Spec getASpec() { result = this.getSpec(_) }
|
||||
|
||||
/** Gets the number of declaration specifiers in this declaration. */
|
||||
int getNumSpec() { result = count(getASpec()) }
|
||||
int getNumSpec() { result = count(this.getASpec()) }
|
||||
|
||||
override predicate mayHaveSideEffects() { getASpec().mayHaveSideEffects() }
|
||||
override predicate mayHaveSideEffects() { this.getASpec().mayHaveSideEffects() }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "GenDecl" }
|
||||
}
|
||||
@@ -130,13 +130,15 @@ class FuncDef extends @funcdef, StmtParent, ExprParent {
|
||||
/**
|
||||
* Gets the number of parameters of this function.
|
||||
*/
|
||||
int getNumParameter() { result = count(getAParameter()) }
|
||||
int getNumParameter() { result = count(this.getAParameter()) }
|
||||
|
||||
/**
|
||||
* Gets a call to this function.
|
||||
*/
|
||||
DataFlow::CallNode getACall() { result.getACallee() = this }
|
||||
|
||||
predicate isVariadic() { getType().isVariadic() }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "FuncDef" }
|
||||
}
|
||||
|
||||
@@ -145,16 +147,16 @@ class FuncDef extends @funcdef, StmtParent, ExprParent {
|
||||
*/
|
||||
class FuncDecl extends @funcdecl, Decl, Documentable, FuncDef {
|
||||
/** Gets the identifier denoting the name of this function. */
|
||||
Ident getNameExpr() { result = getChildExpr(0) }
|
||||
Ident getNameExpr() { result = this.getChildExpr(0) }
|
||||
|
||||
override string getName() { result = getNameExpr().getName() }
|
||||
override string getName() { result = this.getNameExpr().getName() }
|
||||
|
||||
override FuncTypeExpr getTypeExpr() { result = getChildExpr(1) }
|
||||
override FuncTypeExpr getTypeExpr() { result = this.getChildExpr(1) }
|
||||
|
||||
override SignatureType getType() { result = getNameExpr().getType() }
|
||||
override SignatureType getType() { result = this.getNameExpr().getType() }
|
||||
|
||||
/** Gets the body of this function, if any. */
|
||||
override BlockStmt getBody() { result = getChildStmt(2) }
|
||||
override BlockStmt getBody() { result = this.getChildStmt(2) }
|
||||
|
||||
/** Gets the function declared by this function declaration. */
|
||||
DeclaredFunction getFunction() { this = result.getFuncDecl() }
|
||||
@@ -196,7 +198,7 @@ class MethodDecl extends FuncDecl {
|
||||
*
|
||||
* is `*Rectangle`.
|
||||
*/
|
||||
Type getReceiverType() { result = getReceiverDecl().getType() }
|
||||
Type getReceiverType() { result = this.getReceiverDecl().getType() }
|
||||
|
||||
/**
|
||||
* Gets the receiver base type of this method.
|
||||
@@ -210,8 +212,8 @@ class MethodDecl extends FuncDecl {
|
||||
* is `Rectangle`.
|
||||
*/
|
||||
NamedType getReceiverBaseType() {
|
||||
result = getReceiverType() or
|
||||
result = getReceiverType().(PointerType).getBaseType()
|
||||
result = this.getReceiverType() or
|
||||
result = this.getReceiverType().(PointerType).getBaseType()
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -261,16 +263,16 @@ class Spec extends @spec, ExprParent, Documentable {
|
||||
*/
|
||||
class ImportSpec extends @importspec, Spec {
|
||||
/** Gets the identifier denoting the imported name. */
|
||||
Ident getNameExpr() { result = getChildExpr(0) }
|
||||
Ident getNameExpr() { result = this.getChildExpr(0) }
|
||||
|
||||
/** Gets the imported name. */
|
||||
string getName() { result = getNameExpr().getName() }
|
||||
string getName() { result = this.getNameExpr().getName() }
|
||||
|
||||
/** Gets the string literal denoting the imported path. */
|
||||
StringLit getPathExpr() { result = getChildExpr(1) }
|
||||
StringLit getPathExpr() { result = this.getChildExpr(1) }
|
||||
|
||||
/** Gets the imported path. */
|
||||
string getPath() { result = getPathExpr().getValue() }
|
||||
string getPath() { result = this.getPathExpr().getValue() }
|
||||
|
||||
override string toString() { result = "import specifier" }
|
||||
|
||||
@@ -284,41 +286,41 @@ class ValueSpec extends @valuespec, Spec {
|
||||
/** Gets the identifier denoting the `i`th name declared by this specifier (0-based). */
|
||||
Ident getNameExpr(int i) {
|
||||
i >= 0 and
|
||||
result = getChildExpr(-(i + 1))
|
||||
result = this.getChildExpr(-(i + 1))
|
||||
}
|
||||
|
||||
/** Holds if this specifier is a part of a constant declaration. */
|
||||
predicate isConstSpec() { this.getParentDecl() instanceof ConstDecl }
|
||||
|
||||
/** Gets an identifier denoting a name declared by this specifier. */
|
||||
Ident getANameExpr() { result = getNameExpr(_) }
|
||||
Ident getANameExpr() { result = this.getNameExpr(_) }
|
||||
|
||||
/** Gets the `i`th name declared by this specifier (0-based). */
|
||||
string getName(int i) { result = getNameExpr(i).getName() }
|
||||
string getName(int i) { result = this.getNameExpr(i).getName() }
|
||||
|
||||
/** Gets a name declared by this specifier. */
|
||||
string getAName() { result = getName(_) }
|
||||
string getAName() { result = this.getName(_) }
|
||||
|
||||
/** Gets the number of names declared by this specifier. */
|
||||
int getNumName() { result = count(getANameExpr()) }
|
||||
int getNumName() { result = count(this.getANameExpr()) }
|
||||
|
||||
/** Gets the expression denoting the type of the symbols declared by this specifier. */
|
||||
Expr getTypeExpr() { result = getChildExpr(0) }
|
||||
Expr getTypeExpr() { result = this.getChildExpr(0) }
|
||||
|
||||
/** Gets the `i`th initializer of this specifier (0-based). */
|
||||
Expr getInit(int i) {
|
||||
i >= 0 and
|
||||
result = getChildExpr(i + 1)
|
||||
result = this.getChildExpr(i + 1)
|
||||
}
|
||||
|
||||
/** Gets an initializer of this specifier. */
|
||||
Expr getAnInit() { result = getInit(_) }
|
||||
Expr getAnInit() { result = this.getInit(_) }
|
||||
|
||||
/** Gets the number of initializers of this specifier. */
|
||||
int getNumInit() { result = count(getAnInit()) }
|
||||
int getNumInit() { result = count(this.getAnInit()) }
|
||||
|
||||
/** Gets the unique initializer of this specifier, if there is only one. */
|
||||
Expr getInit() { getNumInit() = 1 and result = getInit(0) }
|
||||
Expr getInit() { this.getNumInit() = 1 and result = this.getInit(0) }
|
||||
|
||||
/**
|
||||
* Gets the specifier that contains the initializers for this specifier.
|
||||
@@ -349,12 +351,12 @@ class ValueSpec extends @valuespec, Spec {
|
||||
/** Holds if this specifier initializes `name` to the value of `init`. */
|
||||
predicate initializes(string name, Expr init) {
|
||||
exists(int i |
|
||||
name = getName(i) and
|
||||
init = getEffectiveInit(i)
|
||||
name = this.getName(i) and
|
||||
init = this.getEffectiveInit(i)
|
||||
)
|
||||
}
|
||||
|
||||
override predicate mayHaveSideEffects() { getAnInit().mayHaveSideEffects() }
|
||||
override predicate mayHaveSideEffects() { this.getAnInit().mayHaveSideEffects() }
|
||||
|
||||
override string toString() { result = "value declaration specifier" }
|
||||
|
||||
@@ -375,15 +377,15 @@ class ValueSpec extends @valuespec, Spec {
|
||||
*/
|
||||
class TypeSpec extends @typespec, Spec {
|
||||
/** Gets the identifier denoting the name of the declared type. */
|
||||
Ident getNameExpr() { result = getChildExpr(0) }
|
||||
Ident getNameExpr() { result = this.getChildExpr(0) }
|
||||
|
||||
/** Gets the name of the declared type. */
|
||||
string getName() { result = getNameExpr().getName() }
|
||||
string getName() { result = this.getNameExpr().getName() }
|
||||
|
||||
/**
|
||||
* Gets the expression denoting the underlying type to which the newly declared type is bound.
|
||||
*/
|
||||
Expr getTypeExpr() { result = getChildExpr(1) }
|
||||
Expr getTypeExpr() { result = this.getChildExpr(1) }
|
||||
|
||||
override string toString() { result = "type declaration specifier" }
|
||||
|
||||
@@ -420,12 +422,12 @@ class FieldBase extends @field, ExprParent {
|
||||
/**
|
||||
* Gets the expression representing the type of the fields declared in this declaration.
|
||||
*/
|
||||
Expr getTypeExpr() { result = getChildExpr(0) }
|
||||
Expr getTypeExpr() { result = this.getChildExpr(0) }
|
||||
|
||||
/**
|
||||
* Gets the type of the fields declared in this declaration.
|
||||
*/
|
||||
Type getType() { result = getTypeExpr().getType() }
|
||||
Type getType() { result = this.getTypeExpr().getType() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -442,17 +444,17 @@ class FieldDecl extends FieldBase, Documentable, ExprParent {
|
||||
*/
|
||||
Expr getNameExpr(int i) {
|
||||
i >= 0 and
|
||||
result = getChildExpr(i + 1)
|
||||
result = this.getChildExpr(i + 1)
|
||||
}
|
||||
|
||||
/** Gets the tag expression of this field declaration, if any. */
|
||||
Expr getTag() { result = getChildExpr(-1) }
|
||||
Expr getTag() { result = this.getChildExpr(-1) }
|
||||
|
||||
/** Gets the struct type expression to which this field declaration belongs. */
|
||||
StructTypeExpr getDeclaringStructTypeExpr() { result = st }
|
||||
|
||||
/** Gets the struct type to which this field declaration belongs. */
|
||||
StructType getDeclaringType() { result = getDeclaringStructTypeExpr().getType() }
|
||||
StructType getDeclaringType() { result = this.getDeclaringStructTypeExpr().getType() }
|
||||
|
||||
override string toString() { result = "field declaration" }
|
||||
|
||||
@@ -485,7 +487,7 @@ class ParameterOrResultDecl extends FieldBase, Documentable, ExprParent {
|
||||
/**
|
||||
* Gets the function to which this declaration belongs.
|
||||
*/
|
||||
FuncDef getFunction() { result.getTypeExpr() = getFunctionTypeExpr() }
|
||||
FuncDef getFunction() { result.getTypeExpr() = this.getFunctionTypeExpr() }
|
||||
|
||||
/**
|
||||
* Gets the expression representing the name of the `i`th variable declared in this declaration
|
||||
@@ -493,13 +495,13 @@ class ParameterOrResultDecl extends FieldBase, Documentable, ExprParent {
|
||||
*/
|
||||
Expr getNameExpr(int i) {
|
||||
i >= 0 and
|
||||
result = getChildExpr(i + 1)
|
||||
result = this.getChildExpr(i + 1)
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an expression representing the name of a variable declared in this declaration.
|
||||
*/
|
||||
Expr getANameExpr() { result = getNameExpr(_) }
|
||||
Expr getANameExpr() { result = this.getNameExpr(_) }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -535,7 +537,7 @@ class ReceiverDecl extends FieldBase, Documentable, ExprParent {
|
||||
/**
|
||||
* Gets the expression representing the name of the receiver declared in this declaration.
|
||||
*/
|
||||
Expr getNameExpr() { result = getChildExpr(1) }
|
||||
Expr getNameExpr() { result = this.getChildExpr(1) }
|
||||
|
||||
override string toString() { result = "receiver declaration" }
|
||||
|
||||
@@ -586,7 +588,7 @@ class InterfaceMemberSpec extends FieldBase, Documentable, ExprParent {
|
||||
class MethodSpec extends InterfaceMemberSpec {
|
||||
Expr name;
|
||||
|
||||
MethodSpec() { name = getChildExpr(1) }
|
||||
MethodSpec() { name = this.getChildExpr(1) }
|
||||
|
||||
/**
|
||||
* Gets the expression representing the name of the method declared in this specification.
|
||||
@@ -602,7 +604,7 @@ class MethodSpec extends InterfaceMemberSpec {
|
||||
* An embedding specification in an interface.
|
||||
*/
|
||||
class EmbeddingSpec extends InterfaceMemberSpec {
|
||||
EmbeddingSpec() { not exists(getChildExpr(1)) }
|
||||
EmbeddingSpec() { not exists(this.getChildExpr(1)) }
|
||||
|
||||
override string toString() { result = "interface embedding" }
|
||||
|
||||
|
||||
@@ -138,7 +138,9 @@ class Expr extends @expr, ExprParent {
|
||||
*
|
||||
* Memory allocation is not considered an observable side effect.
|
||||
*/
|
||||
predicate mayHaveSideEffects() { mayHaveOwnSideEffects() or getAChildExpr().mayHaveSideEffects() }
|
||||
predicate mayHaveSideEffects() {
|
||||
this.mayHaveOwnSideEffects() or this.getAChildExpr().mayHaveSideEffects()
|
||||
}
|
||||
|
||||
override string toString() { result = "expression" }
|
||||
}
|
||||
@@ -179,9 +181,9 @@ class Ident extends @ident, Expr {
|
||||
predicate declares(Entity e) { defs(this, e) }
|
||||
|
||||
/** Holds if this identifier refers to (that is, uses, defines or declares) `e`. */
|
||||
predicate refersTo(Entity e) { uses(e) or declares(e) }
|
||||
predicate refersTo(Entity e) { this.uses(e) or this.declares(e) }
|
||||
|
||||
override string toString() { result = getName() }
|
||||
override string toString() { result = this.getName() }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "Ident" }
|
||||
}
|
||||
@@ -196,7 +198,7 @@ class Ident extends @ident, Expr {
|
||||
* ```
|
||||
*/
|
||||
class BlankIdent extends Ident {
|
||||
BlankIdent() { getName() = "_" }
|
||||
BlankIdent() { this.getName() = "_" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "BlankIdent" }
|
||||
}
|
||||
@@ -213,7 +215,7 @@ class BlankIdent extends Ident {
|
||||
*/
|
||||
class Ellipsis extends @ellipsis, Expr {
|
||||
/** Gets the operand of this ellipsis expression. */
|
||||
Expr getOperand() { result = getChildExpr(0) }
|
||||
Expr getOperand() { result = this.getChildExpr(0) }
|
||||
|
||||
override string toString() { result = "..." }
|
||||
|
||||
@@ -263,7 +265,7 @@ class BasicLit extends @basiclit, Literal {
|
||||
|
||||
override predicate isPlatformIndependentConstant() { any() }
|
||||
|
||||
override string toString() { result = getText() }
|
||||
override string toString() { result = this.getText() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -358,12 +360,12 @@ class StringLit extends @stringlit, BasicLit {
|
||||
* ```
|
||||
*/
|
||||
class FuncLit extends @funclit, Literal, StmtParent, FuncDef {
|
||||
override FuncTypeExpr getTypeExpr() { result = getChildExpr(0) }
|
||||
override FuncTypeExpr getTypeExpr() { result = this.getChildExpr(0) }
|
||||
|
||||
override SignatureType getType() { result = Literal.super.getType() }
|
||||
|
||||
/** Gets the body of this function literal. */
|
||||
override BlockStmt getBody() { result = getChildStmt(1) }
|
||||
override BlockStmt getBody() { result = this.getChildStmt(1) }
|
||||
|
||||
override predicate isPlatformIndependentConstant() { any() }
|
||||
|
||||
@@ -384,32 +386,32 @@ class FuncLit extends @funclit, Literal, StmtParent, FuncDef {
|
||||
*/
|
||||
class CompositeLit extends @compositelit, Literal {
|
||||
/** Gets the expression representing the type of this composite literal. */
|
||||
Expr getTypeExpr() { result = getChildExpr(0) }
|
||||
Expr getTypeExpr() { result = this.getChildExpr(0) }
|
||||
|
||||
/** Gets the `i`th element of this composite literal (0-based). */
|
||||
Expr getElement(int i) {
|
||||
i >= 0 and
|
||||
result = getChildExpr(i + 1)
|
||||
result = this.getChildExpr(i + 1)
|
||||
}
|
||||
|
||||
/** Gets an element of this composite literal. */
|
||||
Expr getAnElement() { result = getElement(_) }
|
||||
Expr getAnElement() { result = this.getElement(_) }
|
||||
|
||||
/** Gets the number of elements in this composite literal. */
|
||||
int getNumElement() { result = count(getAnElement()) }
|
||||
int getNumElement() { result = count(this.getAnElement()) }
|
||||
|
||||
/**
|
||||
* Gets the `i`th key expression in this literal.
|
||||
*
|
||||
* If the `i`th element of this literal has no key, this predicate is undefined for `i`.
|
||||
*/
|
||||
Expr getKey(int i) { result = getElement(i).(KeyValueExpr).getKey() }
|
||||
Expr getKey(int i) { result = this.getElement(i).(KeyValueExpr).getKey() }
|
||||
|
||||
/**
|
||||
* Gets the `i`th value expression in this literal.
|
||||
*/
|
||||
Expr getValue(int i) {
|
||||
exists(Expr elt | elt = getElement(i) |
|
||||
exists(Expr elt | elt = this.getElement(i) |
|
||||
result = elt.(KeyValueExpr).getValue()
|
||||
or
|
||||
not elt instanceof KeyValueExpr and result = elt
|
||||
@@ -433,7 +435,7 @@ class CompositeLit extends @compositelit, Literal {
|
||||
class MapLit extends CompositeLit {
|
||||
MapType mt;
|
||||
|
||||
MapLit() { mt = getType().getUnderlyingType() }
|
||||
MapLit() { mt = this.getType().getUnderlyingType() }
|
||||
|
||||
/** Gets the key type of this literal. */
|
||||
Type getKeyType() { result = mt.getKeyType() }
|
||||
@@ -460,7 +462,7 @@ class MapLit extends CompositeLit {
|
||||
class StructLit extends CompositeLit {
|
||||
StructType st;
|
||||
|
||||
StructLit() { st = getType().getUnderlyingType() }
|
||||
StructLit() { st = this.getType().getUnderlyingType() }
|
||||
|
||||
/** Gets the struct type underlying this literal. */
|
||||
StructType getStructType() { result = st }
|
||||
@@ -487,7 +489,7 @@ class ArrayOrSliceLit extends CompositeLit {
|
||||
CompositeType type;
|
||||
|
||||
ArrayOrSliceLit() {
|
||||
type = getType().getUnderlyingType() and
|
||||
type = this.getType().getUnderlyingType() and
|
||||
(
|
||||
type instanceof ArrayType
|
||||
or
|
||||
@@ -550,11 +552,13 @@ class SliceLit extends ArrayOrSliceLit {
|
||||
*/
|
||||
class ParenExpr extends @parenexpr, Expr {
|
||||
/** Gets the expression between parentheses. */
|
||||
Expr getExpr() { result = getChildExpr(0) }
|
||||
Expr getExpr() { result = this.getChildExpr(0) }
|
||||
|
||||
override Expr stripParens() { result = getExpr().stripParens() }
|
||||
override Expr stripParens() { result = this.getExpr().stripParens() }
|
||||
|
||||
override predicate isPlatformIndependentConstant() { getExpr().isPlatformIndependentConstant() }
|
||||
override predicate isPlatformIndependentConstant() {
|
||||
this.getExpr().isPlatformIndependentConstant()
|
||||
}
|
||||
|
||||
override string toString() { result = "(...)" }
|
||||
|
||||
@@ -572,23 +576,23 @@ class ParenExpr extends @parenexpr, Expr {
|
||||
*/
|
||||
class SelectorExpr extends @selectorexpr, Expr {
|
||||
/** Gets the base of this selector expression. */
|
||||
Expr getBase() { result = getChildExpr(0) }
|
||||
Expr getBase() { result = this.getChildExpr(0) }
|
||||
|
||||
/** Gets the selector of this selector expression. */
|
||||
Ident getSelector() { result = getChildExpr(1) }
|
||||
Ident getSelector() { result = this.getChildExpr(1) }
|
||||
|
||||
/** Holds if this selector is a use of `e`. */
|
||||
predicate uses(Entity e) { getSelector().uses(e) }
|
||||
predicate uses(Entity e) { this.getSelector().uses(e) }
|
||||
|
||||
/** Holds if this selector is a definition of `e` */
|
||||
predicate declares(Entity e) { getSelector().declares(e) }
|
||||
predicate declares(Entity e) { this.getSelector().declares(e) }
|
||||
|
||||
/** Holds if this selector refers to (that is, uses, defines or declares) `e`. */
|
||||
predicate refersTo(Entity e) { getSelector().refersTo(e) }
|
||||
predicate refersTo(Entity e) { this.getSelector().refersTo(e) }
|
||||
|
||||
override predicate mayHaveOwnSideEffects() { any() }
|
||||
|
||||
override string toString() { result = "selection of " + getSelector() }
|
||||
override string toString() { result = "selection of " + this.getSelector() }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "SelectorExpr" }
|
||||
}
|
||||
@@ -631,10 +635,10 @@ class PromotedSelector extends SelectorExpr {
|
||||
*/
|
||||
class IndexExpr extends @indexexpr, Expr {
|
||||
/** Gets the base of this index expression. */
|
||||
Expr getBase() { result = getChildExpr(0) }
|
||||
Expr getBase() { result = this.getChildExpr(0) }
|
||||
|
||||
/** Gets the index of this index expression. */
|
||||
Expr getIndex() { result = getChildExpr(1) }
|
||||
Expr getIndex() { result = this.getChildExpr(1) }
|
||||
|
||||
override predicate mayHaveOwnSideEffects() { any() }
|
||||
|
||||
@@ -655,16 +659,16 @@ class IndexExpr extends @indexexpr, Expr {
|
||||
*/
|
||||
class SliceExpr extends @sliceexpr, Expr {
|
||||
/** Gets the base of this slice expression. */
|
||||
Expr getBase() { result = getChildExpr(0) }
|
||||
Expr getBase() { result = this.getChildExpr(0) }
|
||||
|
||||
/** Gets the lower bound of this slice expression. */
|
||||
Expr getLow() { result = getChildExpr(1) }
|
||||
Expr getLow() { result = this.getChildExpr(1) }
|
||||
|
||||
/** Gets the upper bound of this slice expression. */
|
||||
Expr getHigh() { result = getChildExpr(2) }
|
||||
Expr getHigh() { result = this.getChildExpr(2) }
|
||||
|
||||
/** Gets the maximum of this slice expression, if any. */
|
||||
Expr getMax() { result = getChildExpr(3) }
|
||||
Expr getMax() { result = this.getChildExpr(3) }
|
||||
|
||||
override string toString() { result = "slice expression" }
|
||||
|
||||
@@ -682,14 +686,16 @@ class SliceExpr extends @sliceexpr, Expr {
|
||||
*/
|
||||
class TypeAssertExpr extends @typeassertexpr, Expr {
|
||||
/** Gets the base expression whose type is being asserted. */
|
||||
Expr getExpr() { result = getChildExpr(0) }
|
||||
Expr getExpr() { result = this.getChildExpr(0) }
|
||||
|
||||
/** Gets the expression representing the asserted type. */
|
||||
Expr getTypeExpr() { result = getChildExpr(1) }
|
||||
Expr getTypeExpr() { result = this.getChildExpr(1) }
|
||||
|
||||
override predicate mayHaveOwnSideEffects() { any() }
|
||||
|
||||
override predicate isPlatformIndependentConstant() { getExpr().isPlatformIndependentConstant() }
|
||||
override predicate isPlatformIndependentConstant() {
|
||||
this.getExpr().isPlatformIndependentConstant()
|
||||
}
|
||||
|
||||
override string toString() { result = "type assertion" }
|
||||
|
||||
@@ -725,16 +731,16 @@ class CallOrConversionExpr extends @callorconversionexpr, Expr {
|
||||
* ```
|
||||
*/
|
||||
class ConversionExpr extends CallOrConversionExpr {
|
||||
ConversionExpr() { isTypeExprBottomUp(getChildExpr(0)) }
|
||||
ConversionExpr() { isTypeExprBottomUp(this.getChildExpr(0)) }
|
||||
|
||||
/** Gets the type expression representing the target type of the conversion. */
|
||||
Expr getTypeExpr() { result = getChildExpr(0) }
|
||||
Expr getTypeExpr() { result = this.getChildExpr(0) }
|
||||
|
||||
/** Gets the operand of the type conversion. */
|
||||
Expr getOperand() { result = getChildExpr(1) }
|
||||
Expr getOperand() { result = this.getChildExpr(1) }
|
||||
|
||||
override predicate isPlatformIndependentConstant() {
|
||||
getOperand().isPlatformIndependentConstant()
|
||||
this.getOperand().isPlatformIndependentConstant()
|
||||
}
|
||||
|
||||
override string toString() { result = "type conversion" }
|
||||
@@ -757,30 +763,30 @@ class ConversionExpr extends CallOrConversionExpr {
|
||||
*/
|
||||
class CallExpr extends CallOrConversionExpr {
|
||||
CallExpr() {
|
||||
exists(Expr callee | callee = getChildExpr(0) | not isTypeExprBottomUp(callee))
|
||||
exists(Expr callee | callee = this.getChildExpr(0) | not isTypeExprBottomUp(callee))
|
||||
or
|
||||
// only calls can have an ellipsis after their last argument
|
||||
has_ellipsis(this)
|
||||
}
|
||||
|
||||
/** Gets the expression representing the function being called. */
|
||||
Expr getCalleeExpr() { result = getChildExpr(0) }
|
||||
Expr getCalleeExpr() { result = this.getChildExpr(0) }
|
||||
|
||||
/** Gets the `i`th argument expression of this call (0-based). */
|
||||
Expr getArgument(int i) {
|
||||
i >= 0 and
|
||||
result = getChildExpr(i + 1)
|
||||
result = this.getChildExpr(i + 1)
|
||||
}
|
||||
|
||||
/** Gets an argument expression of this call. */
|
||||
Expr getAnArgument() { result = getArgument(_) }
|
||||
Expr getAnArgument() { result = this.getArgument(_) }
|
||||
|
||||
/** Gets the number of argument expressions of this call. */
|
||||
int getNumArgument() { result = count(getAnArgument()) }
|
||||
int getNumArgument() { result = count(this.getAnArgument()) }
|
||||
|
||||
/** Gets the name of the invoked function or method if it can be determined syntactically. */
|
||||
string getCalleeName() {
|
||||
exists(Expr callee | callee = getCalleeExpr().stripParens() |
|
||||
exists(Expr callee | callee = this.getCalleeExpr().stripParens() |
|
||||
result = callee.(Ident).getName()
|
||||
or
|
||||
result = callee.(SelectorExpr).getSelector().getName()
|
||||
@@ -788,20 +794,20 @@ class CallExpr extends CallOrConversionExpr {
|
||||
}
|
||||
|
||||
/** Gets the declared target of this call. */
|
||||
Function getTarget() { getCalleeExpr() = result.getAReference() }
|
||||
Function getTarget() { this.getCalleeExpr() = result.getAReference() }
|
||||
|
||||
/** Holds if this call has an ellipsis after its last argument. */
|
||||
predicate hasEllipsis() { has_ellipsis(this) }
|
||||
|
||||
override predicate mayHaveOwnSideEffects() {
|
||||
getTarget().mayHaveSideEffects() or
|
||||
not exists(getTarget())
|
||||
this.getTarget().mayHaveSideEffects() or
|
||||
not exists(this.getTarget())
|
||||
}
|
||||
|
||||
override string toString() {
|
||||
result = "call to " + getCalleeName()
|
||||
result = "call to " + this.getCalleeName()
|
||||
or
|
||||
not exists(getCalleeName()) and
|
||||
not exists(this.getCalleeName()) and
|
||||
result = "function call"
|
||||
}
|
||||
|
||||
@@ -819,7 +825,7 @@ class CallExpr extends CallOrConversionExpr {
|
||||
*/
|
||||
class StarExpr extends @starexpr, Expr {
|
||||
/** Gets the base expression of this star expression. */
|
||||
Expr getBase() { result = getChildExpr(0) }
|
||||
Expr getBase() { result = this.getChildExpr(0) }
|
||||
|
||||
override predicate mayHaveOwnSideEffects() { any() }
|
||||
|
||||
@@ -839,10 +845,10 @@ class StarExpr extends @starexpr, Expr {
|
||||
*/
|
||||
class KeyValueExpr extends @keyvalueexpr, Expr {
|
||||
/** Gets the key expression of this key-value pair. */
|
||||
Expr getKey() { result = getChildExpr(0) }
|
||||
Expr getKey() { result = this.getChildExpr(0) }
|
||||
|
||||
/** Gets the value expression of this key-value pair. */
|
||||
Expr getValue() { result = getChildExpr(1) }
|
||||
Expr getValue() { result = this.getChildExpr(1) }
|
||||
|
||||
/** Gets the composite literal to which this key-value pair belongs. */
|
||||
CompositeLit getLiteral() { this = result.getElement(_) }
|
||||
@@ -863,10 +869,10 @@ class KeyValueExpr extends @keyvalueexpr, Expr {
|
||||
*/
|
||||
class ArrayTypeExpr extends @arraytypeexpr, TypeExpr {
|
||||
/** Gets the length expression of this array type. */
|
||||
Expr getLength() { result = getChildExpr(0) }
|
||||
Expr getLength() { result = this.getChildExpr(0) }
|
||||
|
||||
/** Gets the expression representing the element type of this array type. */
|
||||
Expr getElement() { result = getChildExpr(1) }
|
||||
Expr getElement() { result = this.getChildExpr(1) }
|
||||
|
||||
override string toString() { result = "array type" }
|
||||
|
||||
@@ -899,25 +905,25 @@ class StructTypeExpr extends @structtypeexpr, TypeExpr, FieldParent {
|
||||
*/
|
||||
class FuncTypeExpr extends @functypeexpr, TypeExpr, ScopeNode, FieldParent {
|
||||
/** Gets the `i`th parameter of this function type (0-based). */
|
||||
ParameterDecl getParameterDecl(int i) { result = getField(i) and i >= 0 }
|
||||
ParameterDecl getParameterDecl(int i) { result = this.getField(i) and i >= 0 }
|
||||
|
||||
/** Gets a parameter of this function type. */
|
||||
ParameterDecl getAParameterDecl() { result = getParameterDecl(_) }
|
||||
ParameterDecl getAParameterDecl() { result = this.getParameterDecl(_) }
|
||||
|
||||
/** Gets the number of parameters of this function type. */
|
||||
int getNumParameter() { result = count(getAParameterDecl()) }
|
||||
int getNumParameter() { result = count(this.getAParameterDecl()) }
|
||||
|
||||
/** Gets the `i`th result of this function type (0-based). */
|
||||
ResultVariableDecl getResultDecl(int i) { result = getField(-(i + 1)) }
|
||||
ResultVariableDecl getResultDecl(int i) { result = this.getField(-(i + 1)) }
|
||||
|
||||
/** Gets a result of this function type. */
|
||||
ResultVariableDecl getAResultDecl() { result = getResultDecl(_) }
|
||||
ResultVariableDecl getAResultDecl() { result = this.getResultDecl(_) }
|
||||
|
||||
/** Gets the number of results of this function type. */
|
||||
int getNumResult() { result = count(getAResultDecl()) }
|
||||
int getNumResult() { result = count(this.getAResultDecl()) }
|
||||
|
||||
/** Gets the result of this function type, if there is only one. */
|
||||
ResultVariableDecl getResultDecl() { getNumResult() = 1 and result = getAResultDecl() }
|
||||
ResultVariableDecl getResultDecl() { this.getNumResult() = 1 and result = this.getAResultDecl() }
|
||||
|
||||
override string toString() { result = "function type" }
|
||||
|
||||
@@ -925,9 +931,9 @@ class FuncTypeExpr extends @functypeexpr, TypeExpr, ScopeNode, FieldParent {
|
||||
|
||||
/** Gets the `i`th child of this node, parameters first followed by results. */
|
||||
override AstNode getUniquelyNumberedChild(int i) {
|
||||
if i < getNumParameter()
|
||||
then result = getParameterDecl(i)
|
||||
else result = getResultDecl(i - getNumParameter())
|
||||
if i < this.getNumParameter()
|
||||
then result = this.getParameterDecl(i)
|
||||
else result = this.getResultDecl(i - this.getNumParameter())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -942,13 +948,13 @@ class FuncTypeExpr extends @functypeexpr, TypeExpr, ScopeNode, FieldParent {
|
||||
*/
|
||||
class InterfaceTypeExpr extends @interfacetypeexpr, TypeExpr, FieldParent {
|
||||
/** Gets the `i`th method specification of this interface type. */
|
||||
MethodSpec getMethod(int i) { result = getField(i) }
|
||||
MethodSpec getMethod(int i) { result = this.getField(i) }
|
||||
|
||||
/** Gets a method of this interface type. */
|
||||
MethodSpec getAMethod() { result = getMethod(_) }
|
||||
MethodSpec getAMethod() { result = this.getMethod(_) }
|
||||
|
||||
/** Gets the number of methods of this interface type. */
|
||||
int getNumMethod() { result = count(getAMethod()) }
|
||||
int getNumMethod() { result = count(this.getAMethod()) }
|
||||
|
||||
override string toString() { result = "interface type" }
|
||||
|
||||
@@ -966,16 +972,16 @@ class InterfaceTypeExpr extends @interfacetypeexpr, TypeExpr, FieldParent {
|
||||
*/
|
||||
class MapTypeExpr extends @maptypeexpr, TypeExpr {
|
||||
/** Gets the expression representing the key type of this map type. */
|
||||
Expr getKeyTypeExpr() { result = getChildExpr(0) }
|
||||
Expr getKeyTypeExpr() { result = this.getChildExpr(0) }
|
||||
|
||||
/** Gets the key type of this map type. */
|
||||
Type getKeyType() { result = getKeyTypeExpr().getType() }
|
||||
Type getKeyType() { result = this.getKeyTypeExpr().getType() }
|
||||
|
||||
/** Gets the expression representing the value type of this map type. */
|
||||
Expr getValueTypeExpr() { result = getChildExpr(1) }
|
||||
Expr getValueTypeExpr() { result = this.getChildExpr(1) }
|
||||
|
||||
/** Gets the value type of this map type. */
|
||||
Type getValueType() { result = getValueTypeExpr().getType() }
|
||||
Type getValueType() { result = this.getValueTypeExpr().getType() }
|
||||
|
||||
override string toString() { result = "map type" }
|
||||
|
||||
@@ -1049,15 +1055,15 @@ class BitwiseExpr extends @bitwiseexpr, OperatorExpr { }
|
||||
*/
|
||||
class UnaryExpr extends @unaryexpr, OperatorExpr {
|
||||
/** Gets the operand of this unary expression. */
|
||||
Expr getOperand() { result = getChildExpr(0) }
|
||||
Expr getOperand() { result = this.getChildExpr(0) }
|
||||
|
||||
override Expr getAnOperand() { result = this.getOperand() }
|
||||
|
||||
override predicate isPlatformIndependentConstant() {
|
||||
getOperand().isPlatformIndependentConstant()
|
||||
this.getOperand().isPlatformIndependentConstant()
|
||||
}
|
||||
|
||||
override string toString() { result = getOperator() + "..." }
|
||||
override string toString() { result = this.getOperator() + "..." }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1214,26 +1220,26 @@ class RecvExpr extends @arrowexpr, UnaryExpr {
|
||||
*/
|
||||
class BinaryExpr extends @binaryexpr, OperatorExpr {
|
||||
/** Gets the left operand of this binary expression. */
|
||||
Expr getLeftOperand() { result = getChildExpr(0) }
|
||||
Expr getLeftOperand() { result = this.getChildExpr(0) }
|
||||
|
||||
/** Gets the right operand of this binary expression. */
|
||||
Expr getRightOperand() { result = getChildExpr(1) }
|
||||
Expr getRightOperand() { result = this.getChildExpr(1) }
|
||||
|
||||
override Expr getAnOperand() { result = getChildExpr([0 .. 1]) }
|
||||
override Expr getAnOperand() { result = this.getChildExpr([0 .. 1]) }
|
||||
|
||||
/** Holds if `e` and `f` (in either order) are the two operands of this binary expression. */
|
||||
predicate hasOperands(Expr e, Expr f) {
|
||||
e = getAnOperand() and
|
||||
f = getAnOperand() and
|
||||
e = this.getAnOperand() and
|
||||
f = this.getAnOperand() and
|
||||
e != f
|
||||
}
|
||||
|
||||
override predicate isPlatformIndependentConstant() {
|
||||
getLeftOperand().isPlatformIndependentConstant() and
|
||||
getRightOperand().isPlatformIndependentConstant()
|
||||
this.getLeftOperand().isPlatformIndependentConstant() and
|
||||
this.getRightOperand().isPlatformIndependentConstant()
|
||||
}
|
||||
|
||||
override string toString() { result = "..." + getOperator() + "..." }
|
||||
override string toString() { result = "..." + this.getOperator() + "..." }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1417,9 +1423,9 @@ class LssExpr extends @lssexpr, RelationalComparisonExpr {
|
||||
|
||||
override predicate isStrict() { any() }
|
||||
|
||||
override Expr getLesserOperand() { result = getLeftOperand() }
|
||||
override Expr getLesserOperand() { result = this.getLeftOperand() }
|
||||
|
||||
override Expr getGreaterOperand() { result = getRightOperand() }
|
||||
override Expr getGreaterOperand() { result = this.getRightOperand() }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "LssExpr" }
|
||||
}
|
||||
@@ -1438,9 +1444,9 @@ class LTExpr = LssExpr;
|
||||
class LeqExpr extends @leqexpr, RelationalComparisonExpr {
|
||||
override string getOperator() { result = "<=" }
|
||||
|
||||
override Expr getLesserOperand() { result = getLeftOperand() }
|
||||
override Expr getLesserOperand() { result = this.getLeftOperand() }
|
||||
|
||||
override Expr getGreaterOperand() { result = getRightOperand() }
|
||||
override Expr getGreaterOperand() { result = this.getRightOperand() }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "LeqExpr" }
|
||||
}
|
||||
@@ -1461,9 +1467,9 @@ class GtrExpr extends @gtrexpr, RelationalComparisonExpr {
|
||||
|
||||
override predicate isStrict() { any() }
|
||||
|
||||
override Expr getLesserOperand() { result = getRightOperand() }
|
||||
override Expr getLesserOperand() { result = this.getRightOperand() }
|
||||
|
||||
override Expr getGreaterOperand() { result = getLeftOperand() }
|
||||
override Expr getGreaterOperand() { result = this.getLeftOperand() }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "GtrExpr" }
|
||||
}
|
||||
@@ -1482,9 +1488,9 @@ class GTExpr = GtrExpr;
|
||||
class GeqExpr extends @geqexpr, RelationalComparisonExpr {
|
||||
override string getOperator() { result = ">=" }
|
||||
|
||||
override Expr getLesserOperand() { result = getRightOperand() }
|
||||
override Expr getLesserOperand() { result = this.getRightOperand() }
|
||||
|
||||
override Expr getGreaterOperand() { result = getLeftOperand() }
|
||||
override Expr getGreaterOperand() { result = this.getLeftOperand() }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "GeqExpr" }
|
||||
}
|
||||
@@ -1685,7 +1691,7 @@ class ChanTypeExpr extends @chantypeexpr, TypeExpr {
|
||||
/**
|
||||
* Gets the expression representing the type of values flowing through the channel.
|
||||
*/
|
||||
Expr getValueTypeExpr() { result = getChildExpr(0) }
|
||||
Expr getValueTypeExpr() { result = this.getChildExpr(0) }
|
||||
|
||||
/** Holds if this channel can send data. */
|
||||
predicate canSend() { none() }
|
||||
|
||||
@@ -47,7 +47,7 @@ abstract 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 @@ abstract class Container extends @container {
|
||||
* </table>
|
||||
*/
|
||||
string getBaseName() {
|
||||
result = getAbsolutePath().regexpCapture(".*/(([^/]*?)(?:\\.([^.]*))?)", 1)
|
||||
result = this.getAbsolutePath().regexpCapture(".*/(([^/]*?)(?:\\.([^.]*))?)", 1)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -100,7 +100,9 @@ abstract 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 @@ abstract 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,20 +132,20 @@ abstract 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
|
||||
}
|
||||
|
||||
@@ -150,7 +154,7 @@ abstract class Container extends @container {
|
||||
*
|
||||
* This is the absolute path of the container.
|
||||
*/
|
||||
string toString() { result = getAbsolutePath() }
|
||||
string toString() { result = this.getAbsolutePath() }
|
||||
}
|
||||
|
||||
/** A folder. */
|
||||
@@ -159,22 +163,22 @@ class Folder extends Container, @folder {
|
||||
|
||||
/** Gets the file or subfolder in this folder 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 folder 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 subfolder contained in this folder. */
|
||||
Folder getASubFolder() { result = getAChildContainer() }
|
||||
Folder getASubFolder() { result = this.getAChildContainer() }
|
||||
|
||||
/** Gets the URL of this folder. */
|
||||
override string getURL() { result = "folder://" + getAbsolutePath() }
|
||||
override string getURL() { result = "folder://" + this.getAbsolutePath() }
|
||||
}
|
||||
|
||||
/** Any file, including files that have not been extracted but are referred to as locations for errors. */
|
||||
@@ -194,10 +198,10 @@ class ExtractedOrExternalFile extends Container, @file, Documentable, ExprParent
|
||||
int getNumberOfLinesOfComments() { numlines(this, _, _, result) }
|
||||
|
||||
/** Gets the package name as specified in the package clause of this file. */
|
||||
Ident getPackageNameExpr() { result = getChildExpr(0) }
|
||||
Ident getPackageNameExpr() { result = this.getChildExpr(0) }
|
||||
|
||||
/** Gets the name of the package to which this file belongs. */
|
||||
string getPackageName() { result = getPackageNameExpr().getName() }
|
||||
string getPackageName() { result = this.getPackageNameExpr().getName() }
|
||||
|
||||
/** Holds if this file contains at least one build constraint. */
|
||||
pragma[noinline]
|
||||
@@ -209,8 +213,8 @@ class ExtractedOrExternalFile extends Container, @file, Documentable, ExprParent
|
||||
* 32 or 64.
|
||||
*/
|
||||
predicate constrainsIntBitSize(int bitSize) {
|
||||
explicitlyConstrainsIntBitSize(bitSize) or
|
||||
implicitlyConstrainsIntBitSize(bitSize)
|
||||
this.explicitlyConstrainsIntBitSize(bitSize) or
|
||||
this.implicitlyConstrainsIntBitSize(bitSize)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -248,12 +252,12 @@ class ExtractedOrExternalFile extends Container, @file, Documentable, ExprParent
|
||||
CommentGroup getCommentGroup(int i) { comment_groups(result, this, i) }
|
||||
|
||||
/** Gets a child comment group. */
|
||||
CommentGroup getACommentGroup() { result = getCommentGroup(_) }
|
||||
CommentGroup getACommentGroup() { result = this.getCommentGroup(_) }
|
||||
|
||||
/** Gets the number of child comment groups of this file. */
|
||||
int getNumCommentGroups() { result = count(getACommentGroup()) }
|
||||
int getNumCommentGroups() { result = count(this.getACommentGroup()) }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "File" }
|
||||
override string getAPrimaryQlClass() { result = "ExtractedOrExternalFile" }
|
||||
}
|
||||
|
||||
/** A file that has been extracted. */
|
||||
@@ -265,14 +269,20 @@ class File extends ExtractedOrExternalFile {
|
||||
or
|
||||
exists(this.getAChild())
|
||||
}
|
||||
|
||||
override string getAPrimaryQlClass() { result = "File" }
|
||||
}
|
||||
|
||||
/** A Go file. */
|
||||
class GoFile extends File {
|
||||
GoFile() { this.getExtension() = "go" }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "GoFile" }
|
||||
}
|
||||
|
||||
/** An HTML file. */
|
||||
class HtmlFile extends File {
|
||||
HtmlFile() { this.getExtension().regexpMatch("x?html?") }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "HtmlFile" }
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ class LocalScope extends @localscope, Scope, Locatable {
|
||||
* For function scopes, this is the scope itself.
|
||||
*/
|
||||
FunctionScope getEnclosingFunctionScope() {
|
||||
result = getOuterScope().(LocalScope).getEnclosingFunctionScope()
|
||||
result = this.getOuterScope().(LocalScope).getEnclosingFunctionScope()
|
||||
}
|
||||
|
||||
override string toString() { result = "local scope" }
|
||||
@@ -64,14 +64,14 @@ class LocalScope extends @localscope, Scope, Locatable {
|
||||
|
||||
/** A local scope induced by a file. */
|
||||
class FileScope extends LocalScope {
|
||||
FileScope() { getNode() instanceof File }
|
||||
FileScope() { this.getNode() instanceof File }
|
||||
}
|
||||
|
||||
/** A local scope induced by a function definition. */
|
||||
class FunctionScope extends LocalScope {
|
||||
FuncDef f;
|
||||
|
||||
FunctionScope() { getNode() = f.getTypeExpr() }
|
||||
FunctionScope() { this.getNode() = f.getTypeExpr() }
|
||||
|
||||
/** Gets the function inducing this scope. */
|
||||
FuncDef getFunction() { result = f }
|
||||
@@ -97,13 +97,13 @@ class Entity extends @object {
|
||||
|
||||
/** Holds if this entity is declared in a package with path `pkg` and has the given `name`. */
|
||||
predicate hasQualifiedName(string pkg, string name) {
|
||||
pkg = getPackage().getPath() and
|
||||
name = getName()
|
||||
pkg = this.getPackage().getPath() and
|
||||
name = this.getName()
|
||||
}
|
||||
|
||||
/** Gets the qualified name of this entity, if any. */
|
||||
string getQualifiedName() {
|
||||
exists(string pkg, string name | hasQualifiedName(pkg, name) | result = pkg + "." + name)
|
||||
exists(string pkg, string name | this.hasQualifiedName(pkg, name) | result = pkg + "." + name)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -123,7 +123,7 @@ class Entity extends @object {
|
||||
Type getType() { objecttypes(this, result) }
|
||||
|
||||
/** Gets a textual representation of this entity. */
|
||||
string toString() { result = getName() }
|
||||
string toString() { result = this.getName() }
|
||||
|
||||
/**
|
||||
* Holds if this element is at the specified location.
|
||||
@@ -136,10 +136,10 @@ class Entity extends @object {
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) {
|
||||
// take the location of the declaration if there is one
|
||||
getDeclaration().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
this.getDeclaration().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
or
|
||||
// otherwise fall back on dummy location
|
||||
not exists(getDeclaration()) and
|
||||
not exists(this.getDeclaration()) and
|
||||
filepath = "" and
|
||||
startline = 0 and
|
||||
startcolumn = 0 and
|
||||
@@ -153,7 +153,7 @@ class DeclaredEntity extends Entity, @declobject {
|
||||
/** Gets the expression to which this entity is initialized, if any. */
|
||||
Expr getInit() {
|
||||
exists(ValueSpec spec, int i |
|
||||
spec.getNameExpr(i) = getDeclaration() and
|
||||
spec.getNameExpr(i) = this.getDeclaration() and
|
||||
spec.getInit(i) = result
|
||||
)
|
||||
}
|
||||
@@ -214,15 +214,17 @@ class DeclaredVariable extends Variable, DeclaredEntity, @declvarobject {
|
||||
|
||||
/** A variable declared in a local scope (as opposed to a package scope or the universal scope). */
|
||||
class LocalVariable extends DeclaredVariable {
|
||||
LocalVariable() { getScope() instanceof LocalScope }
|
||||
LocalVariable() { this.getScope() instanceof LocalScope }
|
||||
|
||||
/** Gets the innermost function containing the scope of this variable, if any. */
|
||||
FuncDef getDeclaringFunction() {
|
||||
result = getScope().(LocalScope).getEnclosingFunctionScope().getFunction()
|
||||
result = this.getScope().(LocalScope).getEnclosingFunctionScope().getFunction()
|
||||
}
|
||||
|
||||
/** Holds if this variable is referenced inside a nested function. */
|
||||
predicate isCaptured() { getDeclaringFunction() != getAReference().getEnclosingFunction() }
|
||||
predicate isCaptured() {
|
||||
this.getDeclaringFunction() != this.getAReference().getEnclosingFunction()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -375,6 +377,12 @@ class Function extends ValueEntity, @functionobject {
|
||||
/** Gets the declaration of this function, if any. */
|
||||
FuncDecl getFuncDecl() { none() }
|
||||
|
||||
predicate isVariadic() {
|
||||
this.(BuiltinFunction).getName() = ["append", "make", "print", "println"]
|
||||
or
|
||||
this.(DeclaredFunction).getFuncDecl().isVariadic()
|
||||
}
|
||||
|
||||
/** Holds if this function has no observable side effects. */
|
||||
predicate mayHaveSideEffects() { none() }
|
||||
|
||||
@@ -388,8 +396,8 @@ class Function extends ValueEntity, @functionobject {
|
||||
* by extending `Function` rather than having to remember to extend `DeclaredFunction`.
|
||||
*/
|
||||
predicate mayReturnNormally() {
|
||||
not mustPanic() and
|
||||
(ControlFlow::mayReturnNormally(getFuncDecl()) or not exists(getBody()))
|
||||
not this.mustPanic() and
|
||||
(ControlFlow::mayReturnNormally(this.getFuncDecl()) or not exists(this.getBody()))
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -409,31 +417,31 @@ class Function extends ValueEntity, @functionobject {
|
||||
predicate mustPanic() { none() }
|
||||
|
||||
/** Gets the number of parameters of this function. */
|
||||
int getNumParameter() { result = getType().(SignatureType).getNumParameter() }
|
||||
int getNumParameter() { result = this.getType().(SignatureType).getNumParameter() }
|
||||
|
||||
/** Gets the type of the `i`th parameter of this function. */
|
||||
Type getParameterType(int i) { result = getType().(SignatureType).getParameterType(i) }
|
||||
Type getParameterType(int i) { result = this.getType().(SignatureType).getParameterType(i) }
|
||||
|
||||
/** Gets the number of results of this function. */
|
||||
int getNumResult() { result = getType().(SignatureType).getNumResult() }
|
||||
int getNumResult() { result = this.getType().(SignatureType).getNumResult() }
|
||||
|
||||
/** Gets the type of the `i`th result of this function. */
|
||||
Type getResultType(int i) { result = getType().(SignatureType).getResultType(i) }
|
||||
Type getResultType(int i) { result = this.getType().(SignatureType).getResultType(i) }
|
||||
|
||||
/** Gets the body of this function, if any. */
|
||||
BlockStmt getBody() { result = getFuncDecl().getBody() }
|
||||
BlockStmt getBody() { result = this.getFuncDecl().getBody() }
|
||||
|
||||
/** Gets the `i`th parameter of this function. */
|
||||
Parameter getParameter(int i) { result.isParameterOf(getFuncDecl(), i) }
|
||||
Parameter getParameter(int i) { result.isParameterOf(this.getFuncDecl(), i) }
|
||||
|
||||
/** Gets a parameter of this function. */
|
||||
Parameter getAParameter() { result = getParameter(_) }
|
||||
Parameter getAParameter() { result = this.getParameter(_) }
|
||||
|
||||
/** Gets the `i`th reslt variable of this function. */
|
||||
ResultVariable getResult(int i) { result.isResultOf(getFuncDecl(), i) }
|
||||
ResultVariable getResult(int i) { result.isResultOf(this.getFuncDecl(), i) }
|
||||
|
||||
/** Gets a result variable of this function. */
|
||||
ResultVariable getAResult() { result = getResult(_) }
|
||||
ResultVariable getAResult() { result = this.getResult(_) }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -455,7 +463,9 @@ class Method extends Function {
|
||||
}
|
||||
|
||||
/** Holds if this method is declared in an interface. */
|
||||
predicate isInterfaceMethod() { getReceiverType().getUnderlyingType() instanceof InterfaceType }
|
||||
predicate isInterfaceMethod() {
|
||||
this.getReceiverType().getUnderlyingType() instanceof InterfaceType
|
||||
}
|
||||
|
||||
/** Gets the receiver variable of this method. */
|
||||
Variable getReceiver() { result = receiver }
|
||||
@@ -468,7 +478,7 @@ class Method extends Function {
|
||||
* if it is a pointer type, or the receiver type itself if it is not a pointer type.
|
||||
*/
|
||||
Type getReceiverBaseType() {
|
||||
exists(Type recv | recv = getReceiverType() |
|
||||
exists(Type recv | recv = this.getReceiverType() |
|
||||
if recv instanceof PointerType
|
||||
then result = recv.(PointerType).getBaseType()
|
||||
else result = recv
|
||||
@@ -522,7 +532,7 @@ class Method extends Function {
|
||||
predicate implements(Method m) {
|
||||
this = m
|
||||
or
|
||||
not isInterfaceMethod() and
|
||||
not this.isInterfaceMethod() and
|
||||
exists(Type t |
|
||||
this = t.getMethod(m.getName()) and
|
||||
t.implements(m.getReceiverType().getUnderlyingType())
|
||||
@@ -553,9 +563,9 @@ class DeclaredFunction extends Function, DeclaredEntity, @declfunctionobject {
|
||||
override FuncDecl getFuncDecl() { result.getNameExpr() = this.getDeclaration() }
|
||||
|
||||
override predicate mayHaveSideEffects() {
|
||||
not exists(getBody())
|
||||
not exists(this.getBody())
|
||||
or
|
||||
exists(BlockStmt body | body = getBody() |
|
||||
exists(BlockStmt body | body = this.getBody() |
|
||||
body.mayHaveSideEffects()
|
||||
or
|
||||
// functions declared in files with build constraints may be defined differently
|
||||
@@ -567,17 +577,17 @@ class DeclaredFunction extends Function, DeclaredEntity, @declfunctionobject {
|
||||
|
||||
/** A built-in function. */
|
||||
class BuiltinFunction extends Function, BuiltinEntity, @builtinfunctionobject {
|
||||
override predicate mayHaveSideEffects() { builtinFunction(getName(), false, _, _) }
|
||||
override predicate mayHaveSideEffects() { builtinFunction(this.getName(), false, _, _) }
|
||||
|
||||
override predicate mayPanic() { builtinFunction(getName(), _, true, _) }
|
||||
override predicate mayPanic() { builtinFunction(this.getName(), _, true, _) }
|
||||
|
||||
override predicate mustPanic() { builtinFunction(getName(), _, _, true) }
|
||||
override predicate mustPanic() { builtinFunction(this.getName(), _, _, true) }
|
||||
|
||||
/**
|
||||
* Holds if this function is pure, that is, it has no observable side effects and
|
||||
* no non-determinism.
|
||||
*/
|
||||
predicate isPure() { not mayHaveSideEffects() }
|
||||
predicate isPure() { not this.mayHaveSideEffects() }
|
||||
}
|
||||
|
||||
/** A statement label. */
|
||||
|
||||
@@ -70,11 +70,11 @@ module StringOps {
|
||||
* An expression of the form `strings.HasPrefix(A, B)`.
|
||||
*/
|
||||
private class StringsHasPrefix extends Range, DataFlow::CallNode {
|
||||
StringsHasPrefix() { getTarget().hasQualifiedName("strings", "HasPrefix") }
|
||||
StringsHasPrefix() { this.getTarget().hasQualifiedName("strings", "HasPrefix") }
|
||||
|
||||
override DataFlow::Node getBaseString() { result = getArgument(0) }
|
||||
override DataFlow::Node getBaseString() { result = this.getArgument(0) }
|
||||
|
||||
override DataFlow::Node getSubstring() { result = getArgument(1) }
|
||||
override DataFlow::Node getSubstring() { result = this.getArgument(1) }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -145,7 +145,7 @@ module StringOps {
|
||||
DataFlow::Node substring;
|
||||
|
||||
HasPrefix_Substring() {
|
||||
eq(_, slice, substring) and
|
||||
this.eq(_, slice, substring) and
|
||||
slice.getLow().getIntValue() = 0 and
|
||||
(
|
||||
exists(DataFlow::CallNode len |
|
||||
@@ -211,25 +211,25 @@ module StringOps {
|
||||
* Gets the string value of the `n`th operand of this string concatenation, if it is
|
||||
* a constant.
|
||||
*/
|
||||
string getOperandStringValue(int n) { result = getOperand(n).getStringValue() }
|
||||
string getOperandStringValue(int n) { result = this.getOperand(n).getStringValue() }
|
||||
|
||||
/**
|
||||
* Gets the number of operands of this string concatenation.
|
||||
*/
|
||||
int getNumOperand() { result = count(getOperand(_)) }
|
||||
int getNumOperand() { result = count(this.getOperand(_)) }
|
||||
}
|
||||
|
||||
/** A string concatenation using the `+` or `+=` operator. */
|
||||
private class PlusConcat extends Range, DataFlow::BinaryOperationNode {
|
||||
PlusConcat() {
|
||||
getType() instanceof StringType and
|
||||
getOperator() = "+"
|
||||
this.getType() instanceof StringType and
|
||||
this.getOperator() = "+"
|
||||
}
|
||||
|
||||
override DataFlow::Node getOperand(int n) {
|
||||
n = 0 and result = getLeftOperand()
|
||||
n = 0 and result = this.getLeftOperand()
|
||||
or
|
||||
n = 1 and result = getRightOperand()
|
||||
n = 1 and result = this.getRightOperand()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -278,7 +278,7 @@ module StringOps {
|
||||
SprintfConcat() {
|
||||
exists(Function sprintf | sprintf.hasQualifiedName("fmt", "Sprintf") |
|
||||
this = sprintf.getACall() and
|
||||
fmt = getArgument(0).getStringValue() and
|
||||
fmt = this.getArgument(0).getStringValue() and
|
||||
fmt.regexpMatch(getFormatComponentRegex() + "*")
|
||||
)
|
||||
}
|
||||
@@ -292,22 +292,22 @@ module StringOps {
|
||||
|
||||
override DataFlow::Node getOperand(int n) {
|
||||
exists(int i, string part | part = "%s" or part = "%v" |
|
||||
part = getComponent(n) and
|
||||
part = this.getComponent(n) and
|
||||
i = n / 2 and
|
||||
result = getArgument(i + 1)
|
||||
result = this.getArgument(i + 1)
|
||||
)
|
||||
}
|
||||
|
||||
override string getOperandStringValue(int n) {
|
||||
result = Range.super.getOperandStringValue(n)
|
||||
or
|
||||
exists(string cmp | cmp = getComponent(n) |
|
||||
exists(string cmp | cmp = this.getComponent(n) |
|
||||
(cmp.charAt(0) != "%" or cmp.charAt(1) = "%") and
|
||||
result = cmp.replaceAll("%%", "%")
|
||||
)
|
||||
}
|
||||
|
||||
override int getNumOperand() { result = max(int i | exists(getComponent(i))) + 1 }
|
||||
override int getNumOperand() { result = max(int i | exists(this.getComponent(i))) + 1 }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -357,7 +357,7 @@ module StringOps {
|
||||
* Gets the string value of this concatenation element if it is a constant.
|
||||
*/
|
||||
string getStringValue() {
|
||||
result = asNode().getStringValue()
|
||||
result = this.asNode().getStringValue()
|
||||
or
|
||||
exists(Concatenation parent, int i | this = MkConcatenationOperand(parent, i) |
|
||||
result = parent.getOperandStringValue(i)
|
||||
@@ -367,7 +367,7 @@ module StringOps {
|
||||
/**
|
||||
* Gets the `n`th operand of this string concatenation.
|
||||
*/
|
||||
ConcatenationOperand getOperand(int n) { result = MkConcatenationOperand(asNode(), n) }
|
||||
ConcatenationOperand getOperand(int n) { result = MkConcatenationOperand(this.asNode(), n) }
|
||||
|
||||
/**
|
||||
* Gets an operand of this string concatenation.
|
||||
@@ -384,14 +384,14 @@ module StringOps {
|
||||
*
|
||||
* For example, the first operand of `(x + y) + z` is `(x + y)`.
|
||||
*/
|
||||
ConcatenationOperand getFirstOperand() { result = getOperand(0) }
|
||||
ConcatenationOperand getFirstOperand() { result = this.getOperand(0) }
|
||||
|
||||
/**
|
||||
* Gets the last operand of this string concatenation.
|
||||
*
|
||||
* For example, the last operand of `x + (y + z)` is `(y + z)`.
|
||||
*/
|
||||
ConcatenationOperand getLastOperand() { result = getOperand(getNumOperand() - 1) }
|
||||
ConcatenationOperand getLastOperand() { result = this.getOperand(this.getNumOperand() - 1) }
|
||||
|
||||
/**
|
||||
* Gets the root of the concatenation tree to which this element belongs.
|
||||
@@ -408,22 +408,22 @@ module StringOps {
|
||||
*
|
||||
* For example, the first leaf of `(x + y) + z` is `x`.
|
||||
*/
|
||||
ConcatenationLeaf getFirstLeaf() { result = getFirstOperand*() }
|
||||
ConcatenationLeaf getFirstLeaf() { result = this.getFirstOperand*() }
|
||||
|
||||
/**
|
||||
* Gets the last leaf in this concatenation tree.
|
||||
*
|
||||
* For example, the last leaf of `x + (y + z)` is `z`.
|
||||
*/
|
||||
ConcatenationLeaf getLastLeaf() { result = getLastOperand*() }
|
||||
ConcatenationLeaf getLastLeaf() { result = this.getLastOperand*() }
|
||||
|
||||
/** Gets a textual representation of this concatenation element. */
|
||||
string toString() {
|
||||
if exists(asNode())
|
||||
then result = asNode().toString()
|
||||
if exists(this.asNode())
|
||||
then result = this.asNode().toString()
|
||||
else
|
||||
if exists(getStringValue())
|
||||
then result = getStringValue()
|
||||
if exists(this.getStringValue())
|
||||
then result = this.getStringValue()
|
||||
else result = "concatenation element"
|
||||
}
|
||||
|
||||
@@ -437,10 +437,10 @@ module StringOps {
|
||||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) {
|
||||
asNode().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
this.asNode().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
or
|
||||
// use dummy location for elements that don't have a corresponding node
|
||||
not exists(asNode()) and
|
||||
not exists(this.asNode()) and
|
||||
filepath = "" and
|
||||
startline = 0 and
|
||||
startcolumn = 0 and
|
||||
@@ -470,7 +470,7 @@ module StringOps {
|
||||
* See `ConcatenationElement` for more information.
|
||||
*/
|
||||
class ConcatenationLeaf extends ConcatenationOperand {
|
||||
ConcatenationLeaf() { not exists(getAnOperand()) }
|
||||
ConcatenationLeaf() { not exists(this.getAnOperand()) }
|
||||
|
||||
/**
|
||||
* Gets the operand immediately preceding this one in its parent concatenation.
|
||||
|
||||
@@ -29,7 +29,7 @@ class Type extends @type {
|
||||
* Only (defined) named types like `io.Writer` have a qualified name. Basic types like `int`,
|
||||
* pointer types like `*io.Writer`, and other composite types do not have a qualified name.
|
||||
*/
|
||||
string getQualifiedName() { result = getEntity().getQualifiedName() }
|
||||
string getQualifiedName() { result = this.getEntity().getQualifiedName() }
|
||||
|
||||
/**
|
||||
* Holds if this type is declared in a package with path `pkg` and has name `name`.
|
||||
@@ -37,12 +37,14 @@ class Type extends @type {
|
||||
* Only (defined) named types like `io.Writer` have a qualified name. Basic types like `int`,
|
||||
* pointer types like `*io.Writer`, and other composite types do not have a qualified name.
|
||||
*/
|
||||
predicate hasQualifiedName(string pkg, string name) { getEntity().hasQualifiedName(pkg, name) }
|
||||
predicate hasQualifiedName(string pkg, string name) {
|
||||
this.getEntity().hasQualifiedName(pkg, name)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the method set of this type contains a method named `m` of type `t`.
|
||||
*/
|
||||
predicate hasMethod(string m, SignatureType t) { t = getMethod(m).getType() }
|
||||
predicate hasMethod(string m, SignatureType t) { t = this.getMethod(m).getType() }
|
||||
|
||||
/**
|
||||
* Gets the method `m` belonging to the method set of this type, if any.
|
||||
@@ -60,7 +62,7 @@ class Type extends @type {
|
||||
*
|
||||
* This includes fields promoted from an embedded field.
|
||||
*/
|
||||
Field getField(string f) { result = getUnderlyingType().getField(f) }
|
||||
Field getField(string f) { result = this.getUnderlyingType().getField(f) }
|
||||
|
||||
/**
|
||||
* Holds if this type implements interface `i`, that is, the method set of `i`
|
||||
@@ -89,12 +91,12 @@ class Type extends @type {
|
||||
/**
|
||||
* Gets a pretty-printed representation of this type, including its structure where applicable.
|
||||
*/
|
||||
string pp() { result = toString() }
|
||||
string pp() { result = this.toString() }
|
||||
|
||||
/**
|
||||
* Gets a basic textual representation of this type.
|
||||
*/
|
||||
string toString() { result = getName() }
|
||||
string toString() { result = this.getName() }
|
||||
}
|
||||
|
||||
/** An invalid type. */
|
||||
@@ -129,7 +131,7 @@ class NumericType extends @numerictype, BasicType {
|
||||
* This predicate is not defined for `uintptr` since the language specification says nothing
|
||||
* about its size.
|
||||
*/
|
||||
int getASize() { result = getSize() }
|
||||
int getASize() { result = this.getSize() }
|
||||
}
|
||||
|
||||
/** An integer type such as `int` or `uint64`. */
|
||||
@@ -313,11 +315,11 @@ class ArrayType extends @arraytype, CompositeType {
|
||||
string getLengthString() { array_length(this, result) }
|
||||
|
||||
/** Gets the length of this array type if it can be represented as a QL integer. */
|
||||
int getLength() { result = getLengthString().toInt() }
|
||||
int getLength() { result = this.getLengthString().toInt() }
|
||||
|
||||
override Package getPackage() { result = this.getElementType().getPackage() }
|
||||
|
||||
override string pp() { result = "[" + getLength() + "]" + getElementType().pp() }
|
||||
override string pp() { result = "[" + this.getLength() + "]" + this.getElementType().pp() }
|
||||
|
||||
override string toString() { result = "array type" }
|
||||
}
|
||||
@@ -329,7 +331,7 @@ class SliceType extends @slicetype, CompositeType {
|
||||
|
||||
override Package getPackage() { result = this.getElementType().getPackage() }
|
||||
|
||||
override string pp() { result = "[]" + getElementType().pp() }
|
||||
override string pp() { result = "[]" + this.getElementType().pp() }
|
||||
|
||||
override string toString() { result = "slice type" }
|
||||
}
|
||||
@@ -445,12 +447,12 @@ class StructType extends @structtype, CompositeType {
|
||||
private Field getFieldCand(string name, int depth, boolean isEmbedded) {
|
||||
result = this.getOwnField(name, isEmbedded) and depth = 0
|
||||
or
|
||||
exists(Type embedded | hasEmbeddedField(embedded, depth - 1) |
|
||||
exists(Type embedded | this.hasEmbeddedField(embedded, depth - 1) |
|
||||
result = embedded.getUnderlyingType().(StructType).getOwnField(name, isEmbedded)
|
||||
)
|
||||
}
|
||||
|
||||
override Field getField(string name) { result = getFieldAtDepth(name, _) }
|
||||
override Field getField(string name) { result = this.getFieldAtDepth(name, _) }
|
||||
|
||||
/**
|
||||
* Gets the field `f` with depth `depth` of this type.
|
||||
@@ -461,14 +463,14 @@ class StructType extends @structtype, CompositeType {
|
||||
* The depth of a field `f` declared in this type is zero.
|
||||
*/
|
||||
Field getFieldAtDepth(string name, int depth) {
|
||||
depth = min(int depthCand | exists(getFieldCand(name, depthCand, _))) and
|
||||
result = getFieldCand(name, depth, _) and
|
||||
strictcount(getFieldCand(name, depth, _)) = 1
|
||||
depth = min(int depthCand | exists(this.getFieldCand(name, depthCand, _))) and
|
||||
result = this.getFieldCand(name, depth, _) and
|
||||
strictcount(this.getFieldCand(name, depth, _)) = 1
|
||||
}
|
||||
|
||||
Method getMethodAtDepth(string name, int depth) {
|
||||
depth = min(int depthCand | hasMethodCand(name, _, depthCand)) and
|
||||
result = unique(Method m | hasMethodCand(name, m, depth))
|
||||
depth = min(int depthCand | this.hasMethodCand(name, _, depthCand)) and
|
||||
result = unique(Method m | this.hasMethodCand(name, m, depth))
|
||||
}
|
||||
|
||||
override predicate hasMethod(string name, SignatureType tp) {
|
||||
@@ -504,15 +506,15 @@ class PointerType extends @pointertype, CompositeType {
|
||||
or
|
||||
// https://golang.org/ref/spec#Method_sets: "the method set of a pointer type *T is
|
||||
// the set of all methods declared with receiver *T or T"
|
||||
result = getBaseType().getMethod(m)
|
||||
result = this.getBaseType().getMethod(m)
|
||||
or
|
||||
// promoted methods from embedded types
|
||||
exists(StructType s, Type embedded |
|
||||
s = getBaseType().(NamedType).getUnderlyingType() and
|
||||
s = this.getBaseType().(NamedType).getUnderlyingType() and
|
||||
s.hasOwnField(_, _, embedded, true) and
|
||||
// ensure that `m` can be promoted
|
||||
not s.hasOwnField(_, m, _, _) and
|
||||
not exists(Method m2 | m2.getReceiverBaseType() = getBaseType() and m2.getName() = m)
|
||||
not exists(Method m2 | m2.getReceiverBaseType() = this.getBaseType() and m2.getName() = m)
|
||||
|
|
||||
result = embedded.getMethod(m)
|
||||
or
|
||||
@@ -525,7 +527,7 @@ class PointerType extends @pointertype, CompositeType {
|
||||
)
|
||||
}
|
||||
|
||||
override string pp() { result = "* " + getBaseType().pp() }
|
||||
override string pp() { result = "* " + this.getBaseType().pp() }
|
||||
|
||||
override string toString() { result = "pointer type" }
|
||||
}
|
||||
@@ -535,14 +537,14 @@ class InterfaceType extends @interfacetype, CompositeType {
|
||||
/** Gets the type of method `name` of this interface type. */
|
||||
Type getMethodType(string name) { component_types(this, _, name, result) }
|
||||
|
||||
override predicate hasMethod(string m, SignatureType t) { t = getMethodType(m) }
|
||||
override predicate hasMethod(string m, SignatureType t) { t = this.getMethodType(m) }
|
||||
|
||||
language[monotonicAggregates]
|
||||
override string pp() {
|
||||
result =
|
||||
"interface { " +
|
||||
concat(string name, Type tp |
|
||||
tp = getMethodType(name)
|
||||
tp = this.getMethodType(name)
|
||||
|
|
||||
name + " " + tp.pp(), "; " order by name
|
||||
) + " }"
|
||||
@@ -559,7 +561,7 @@ class TupleType extends @tupletype, CompositeType {
|
||||
language[monotonicAggregates]
|
||||
override string pp() {
|
||||
result =
|
||||
"(" + concat(int i, Type tp | tp = getComponentType(i) | tp.pp(), ", " order by i) + ")"
|
||||
"(" + concat(int i, Type tp | tp = this.getComponentType(i) | tp.pp(), ", " order by i) + ")"
|
||||
}
|
||||
|
||||
override string toString() { result = "tuple type" }
|
||||
@@ -574,16 +576,19 @@ class SignatureType extends @signaturetype, CompositeType {
|
||||
Type getResultType(int i) { i >= 0 and component_types(this, -(i + 1), _, result) }
|
||||
|
||||
/** Gets the number of parameters specified by this signature. */
|
||||
int getNumParameter() { result = count(int i | exists(getParameterType(i))) }
|
||||
int getNumParameter() { result = count(int i | exists(this.getParameterType(i))) }
|
||||
|
||||
/** Gets the number of results specified by this signature. */
|
||||
int getNumResult() { result = count(int i | exists(getResultType(i))) }
|
||||
int getNumResult() { result = count(int i | exists(this.getResultType(i))) }
|
||||
|
||||
/** Holds if this signature type is variadic. */
|
||||
predicate isVariadic() { variadic(this) }
|
||||
|
||||
language[monotonicAggregates]
|
||||
override string pp() {
|
||||
result =
|
||||
"func(" + concat(int i, Type tp | tp = getParameterType(i) | tp.pp(), ", " order by i) + ") " +
|
||||
concat(int i, Type tp | tp = getResultType(i) | tp.pp(), ", " order by i)
|
||||
"func(" + concat(int i, Type tp | tp = this.getParameterType(i) | tp.pp(), ", " order by i) +
|
||||
") " + concat(int i, Type tp | tp = this.getResultType(i) | tp.pp(), ", " order by i)
|
||||
}
|
||||
|
||||
override string toString() { result = "signature type" }
|
||||
@@ -597,7 +602,7 @@ class MapType extends @maptype, CompositeType {
|
||||
/** Gets the value type of this map type. */
|
||||
Type getValueType() { element_type(this, result) }
|
||||
|
||||
override string pp() { result = "[" + getKeyType().pp() + "]" + getValueType().pp() }
|
||||
override string pp() { result = "[" + this.getKeyType().pp() + "]" + this.getValueType().pp() }
|
||||
|
||||
override string toString() { result = "map type" }
|
||||
}
|
||||
@@ -618,7 +623,7 @@ class ChanType extends @chantype, CompositeType {
|
||||
class SendChanType extends @sendchantype, ChanType {
|
||||
override predicate canSend() { any() }
|
||||
|
||||
override string pp() { result = "chan<- " + getElementType().pp() }
|
||||
override string pp() { result = "chan<- " + this.getElementType().pp() }
|
||||
|
||||
override string toString() { result = "send-channel type" }
|
||||
}
|
||||
@@ -627,7 +632,7 @@ class SendChanType extends @sendchantype, ChanType {
|
||||
class RecvChanType extends @recvchantype, ChanType {
|
||||
override predicate canReceive() { any() }
|
||||
|
||||
override string pp() { result = "<-chan " + getElementType().pp() }
|
||||
override string pp() { result = "<-chan " + this.getElementType().pp() }
|
||||
|
||||
override string toString() { result = "receive-channel type" }
|
||||
}
|
||||
@@ -638,7 +643,7 @@ class SendRecvChanType extends @sendrcvchantype, ChanType {
|
||||
|
||||
override predicate canReceive() { any() }
|
||||
|
||||
override string pp() { result = "chan " + getElementType().pp() }
|
||||
override string pp() { result = "chan " + this.getElementType().pp() }
|
||||
|
||||
override string toString() { result = "send-receive-channel type" }
|
||||
}
|
||||
@@ -656,7 +661,7 @@ class NamedType extends @namedtype, CompositeType {
|
||||
or
|
||||
// handle promoted methods
|
||||
exists(StructType s, Type embedded |
|
||||
s = getBaseType() and
|
||||
s = this.getBaseType() and
|
||||
s.hasOwnField(_, _, embedded, true) and
|
||||
// ensure `m` can be promoted
|
||||
not s.hasOwnField(_, m, _, _) and
|
||||
@@ -670,7 +675,7 @@ class NamedType extends @namedtype, CompositeType {
|
||||
)
|
||||
}
|
||||
|
||||
override Type getUnderlyingType() { result = getBaseType().getUnderlyingType() }
|
||||
override Type getUnderlyingType() { result = this.getBaseType().getUnderlyingType() }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -191,17 +191,17 @@ module HTTP {
|
||||
|
||||
/** Gets a content-type associated with this body. */
|
||||
string getAContentType() {
|
||||
exists(HTTP::HeaderWrite hw | hw = getResponseWriter().getAHeaderWrite() |
|
||||
exists(HTTP::HeaderWrite hw | hw = this.getResponseWriter().getAHeaderWrite() |
|
||||
hw.getHeaderName() = "content-type" and
|
||||
result = hw.getHeaderValue()
|
||||
)
|
||||
or
|
||||
result = getAContentTypeNode().getStringValue()
|
||||
result = this.getAContentTypeNode().getStringValue()
|
||||
}
|
||||
|
||||
/** Gets a dataflow node for a content-type associated with this body. */
|
||||
DataFlow::Node getAContentTypeNode() {
|
||||
exists(HTTP::HeaderWrite hw | hw = getResponseWriter().getAHeaderWrite() |
|
||||
exists(HTTP::HeaderWrite hw | hw = this.getResponseWriter().getAHeaderWrite() |
|
||||
hw.getHeaderName() = "content-type" and
|
||||
result = hw.getValue()
|
||||
)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -387,7 +387,7 @@ module IR {
|
||||
Method getMethod() { result = method }
|
||||
|
||||
override predicate readsMethod(Instruction receiver, Method m) {
|
||||
receiver = getReceiver() and m = getMethod()
|
||||
receiver = this.getReceiver() and m = this.getMethod()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -401,7 +401,7 @@ module IR {
|
||||
Instruction getIndex() { result = evalExprInstruction(e.getIndex()) }
|
||||
|
||||
override predicate readsElement(Instruction base, Instruction index) {
|
||||
base = getBase() and index = getIndex()
|
||||
base = this.getBase() and index = this.getIndex()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -454,8 +454,8 @@ module IR {
|
||||
Instruction getRhs() { none() }
|
||||
|
||||
override predicate writes(ValueEntity v, Instruction rhs) {
|
||||
getLhs().refersTo(v) and
|
||||
rhs = getRhs()
|
||||
this.getLhs().refersTo(v) and
|
||||
rhs = this.getRhs()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -506,7 +506,7 @@ module IR {
|
||||
/** Gets the initialized field. */
|
||||
Field getField() {
|
||||
result.getDeclaringType() = lit.getStructType() and
|
||||
result.getName() = getFieldName()
|
||||
result.getName() = this.getFieldName()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -567,9 +567,9 @@ module IR {
|
||||
Field getField() { result = lhs.getField() }
|
||||
|
||||
override predicate writesField(Instruction base, Field f, Instruction rhs) {
|
||||
getBase() = base and
|
||||
getField() = f and
|
||||
getRhs() = rhs
|
||||
this.getBase() = base and
|
||||
this.getField() = f and
|
||||
this.getRhs() = rhs
|
||||
}
|
||||
}
|
||||
|
||||
@@ -586,8 +586,8 @@ module IR {
|
||||
Instruction getIndex() { result = lhs.getIndex() }
|
||||
|
||||
override predicate writesElement(Instruction base, Instruction index) {
|
||||
getBase() = base and
|
||||
getIndex() = index
|
||||
this.getBase() = base and
|
||||
this.getIndex() = index
|
||||
}
|
||||
}
|
||||
|
||||
@@ -635,7 +635,7 @@ module IR {
|
||||
|
||||
override string getStringValue() { none() }
|
||||
|
||||
override string getExactValue() { result = getIntValue().toString() }
|
||||
override string getExactValue() { result = this.getIntValue().toString() }
|
||||
|
||||
override predicate isPlatformIndependentConstant() { any() }
|
||||
|
||||
@@ -681,12 +681,12 @@ module IR {
|
||||
|
||||
override ControlFlow::Root getRoot() { result.isRootOf(assgn) }
|
||||
|
||||
override string toString() { result = "assignment to " + getLhs() }
|
||||
override string toString() { result = "assignment to " + this.getLhs() }
|
||||
|
||||
override predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) {
|
||||
getLhs().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
this.getLhs().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -829,10 +829,10 @@ module IR {
|
||||
}
|
||||
|
||||
override string getExactValue() {
|
||||
result = getIntValue().toString() or
|
||||
result = getFloatValue().toString() or
|
||||
result = getStringValue().toString() or
|
||||
result = getBoolValue().toString()
|
||||
result = this.getIntValue().toString() or
|
||||
result = this.getFloatValue().toString() or
|
||||
result = this.getStringValue().toString() or
|
||||
result = this.getBoolValue().toString()
|
||||
}
|
||||
|
||||
override predicate isConst() { any() }
|
||||
@@ -999,7 +999,7 @@ module IR {
|
||||
|
||||
/** Gets the instruction whose result is the (unique) result returned by this statement. */
|
||||
Instruction getResult() {
|
||||
not returnsMultipleResults() and
|
||||
not this.returnsMultipleResults() and
|
||||
result = evalExprInstruction(ret.getExpr())
|
||||
}
|
||||
|
||||
@@ -1386,7 +1386,7 @@ module IR {
|
||||
|
||||
/** Gets the SSA variable being written to, if any. */
|
||||
SsaVariable asSsaVariable() {
|
||||
getWrite() = result.getDefinition().(SsaExplicitDefinition).getInstruction()
|
||||
this.getWrite() = result.getDefinition().(SsaExplicitDefinition).getInstruction()
|
||||
}
|
||||
|
||||
/** Holds if `e` is the variable or field being written to. */
|
||||
@@ -1451,12 +1451,12 @@ module IR {
|
||||
}
|
||||
|
||||
/** Gets the variable this refers to, if any. */
|
||||
Variable getVariable() { refersTo(result) }
|
||||
Variable getVariable() { this.refersTo(result) }
|
||||
|
||||
/** Gets the constant this refers to, if any. */
|
||||
Constant getConstant() { refersTo(result) }
|
||||
Constant getConstant() { this.refersTo(result) }
|
||||
|
||||
override string toString() { result = getName() }
|
||||
override string toString() { result = this.getName() }
|
||||
|
||||
override predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
@@ -1492,7 +1492,7 @@ module IR {
|
||||
override string getName() { exists(Field f | this.refersTo(f) | result = f.getName()) }
|
||||
|
||||
/** Gets the field this refers to, if it can be determined. */
|
||||
Field getField() { refersTo(result) }
|
||||
Field getField() { this.refersTo(result) }
|
||||
|
||||
override string toString() {
|
||||
exists(SelectorExpr sel | this = MkLhs(_, sel) |
|
||||
|
||||
@@ -55,7 +55,7 @@ class Property extends TProperty {
|
||||
* subexpression of `test`.
|
||||
*/
|
||||
predicate checkOn(DataFlow::Node test, Boolean outcome, DataFlow::Node nd) {
|
||||
checkOnExpr(test.asExpr(), outcome, nd)
|
||||
this.checkOnExpr(test.asExpr(), outcome, nd)
|
||||
}
|
||||
|
||||
/** Holds if this is the property of having the Boolean value `b`. */
|
||||
|
||||
@@ -10,7 +10,7 @@ private import SsaImpl
|
||||
* declared in file scope.
|
||||
*/
|
||||
class SsaSourceVariable extends LocalVariable {
|
||||
SsaSourceVariable() { not getScope() instanceof FileScope }
|
||||
SsaSourceVariable() { not this.getScope() instanceof FileScope }
|
||||
|
||||
/**
|
||||
* Holds if there may be indirect references of this variable that are not covered by `getAReference()`.
|
||||
@@ -20,10 +20,10 @@ class SsaSourceVariable extends LocalVariable {
|
||||
*/
|
||||
predicate mayHaveIndirectReferences() {
|
||||
// variables that have their address taken
|
||||
exists(AddressExpr addr | addr.getOperand().stripParens() = getAReference())
|
||||
exists(AddressExpr addr | addr.getOperand().stripParens() = this.getAReference())
|
||||
or
|
||||
exists(DataFlow::MethodReadNode mrn |
|
||||
mrn.getReceiver() = getARead() and
|
||||
mrn.getReceiver() = this.getARead() and
|
||||
mrn.getMethod().getReceiverType() instanceof PointerType
|
||||
)
|
||||
or
|
||||
@@ -31,7 +31,7 @@ class SsaSourceVariable extends LocalVariable {
|
||||
// scope or a nested scope, suggesting that name resolution information may be incomplete
|
||||
exists(FunctionScope scope, FuncDef inner |
|
||||
scope = this.getScope().(LocalScope).getEnclosingFunctionScope() and
|
||||
unresolvedReference(getName(), inner) and
|
||||
unresolvedReference(this.getName(), inner) and
|
||||
inner.getScope().getOuterScope*() = scope
|
||||
)
|
||||
}
|
||||
@@ -69,21 +69,21 @@ class SsaVariable extends TSsaDefinition {
|
||||
SsaDefinition getDefinition() { result = this }
|
||||
|
||||
/** Gets the type of this SSA variable. */
|
||||
Type getType() { result = getSourceVariable().getType() }
|
||||
Type getType() { result = this.getSourceVariable().getType() }
|
||||
|
||||
/** Gets a use in basic block `bb` that refers to this SSA variable. */
|
||||
IR::Instruction getAUseIn(ReachableBasicBlock bb) {
|
||||
exists(int i, SsaSourceVariable v | v = getSourceVariable() |
|
||||
exists(int i, SsaSourceVariable v | v = this.getSourceVariable() |
|
||||
result = bb.getNode(i) and
|
||||
this = getDefinition(bb, i, v)
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets a use that refers to this SSA variable. */
|
||||
IR::Instruction getAUse() { result = getAUseIn(_) }
|
||||
IR::Instruction getAUse() { result = this.getAUseIn(_) }
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = getDefinition().prettyPrintRef() }
|
||||
string toString() { result = this.getDefinition().prettyPrintRef() }
|
||||
|
||||
/**
|
||||
* Holds if this element is at the specified location.
|
||||
@@ -95,7 +95,7 @@ class SsaVariable extends TSsaDefinition {
|
||||
predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) {
|
||||
getDefinition().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
this.getDefinition().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -139,10 +139,10 @@ class SsaDefinition extends TSsaDefinition {
|
||||
abstract string prettyPrintRef();
|
||||
|
||||
/** Gets the innermost function or file to which this SSA definition belongs. */
|
||||
ControlFlow::Root getRoot() { result = getBasicBlock().getRoot() }
|
||||
ControlFlow::Root getRoot() { result = this.getBasicBlock().getRoot() }
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = prettyPrintDef() }
|
||||
string toString() { result = this.prettyPrintDef() }
|
||||
|
||||
/**
|
||||
* Holds if this element is at the specified location.
|
||||
@@ -166,26 +166,26 @@ class SsaExplicitDefinition extends SsaDefinition, TExplicitDef {
|
||||
}
|
||||
|
||||
/** Gets the right-hand side of the definition. */
|
||||
IR::Instruction getRhs() { getInstruction().writes(_, result) }
|
||||
IR::Instruction getRhs() { this.getInstruction().writes(_, result) }
|
||||
|
||||
override predicate definesAt(ReachableBasicBlock bb, int i, SsaSourceVariable v) {
|
||||
this = TExplicitDef(bb, i, v)
|
||||
}
|
||||
|
||||
override ReachableBasicBlock getBasicBlock() { definesAt(result, _, _) }
|
||||
override ReachableBasicBlock getBasicBlock() { this.definesAt(result, _, _) }
|
||||
|
||||
override SsaSourceVariable getSourceVariable() { this = TExplicitDef(_, _, result) }
|
||||
|
||||
override string prettyPrintRef() {
|
||||
exists(int l, int c | hasLocationInfo(_, l, c, _, _) | result = "def@" + l + ":" + c)
|
||||
exists(int l, int c | this.hasLocationInfo(_, l, c, _, _) | result = "def@" + l + ":" + c)
|
||||
}
|
||||
|
||||
override string prettyPrintDef() { result = "definition of " + getSourceVariable() }
|
||||
override string prettyPrintDef() { result = "definition of " + this.getSourceVariable() }
|
||||
|
||||
override predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) {
|
||||
getInstruction().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
this.getInstruction().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -209,7 +209,9 @@ abstract class SsaImplicitDefinition extends SsaDefinition {
|
||||
abstract string getKind();
|
||||
|
||||
override string prettyPrintRef() {
|
||||
exists(int l, int c | hasLocationInfo(_, l, c, _, _) | result = getKind() + "@" + l + ":" + c)
|
||||
exists(int l, int c | this.hasLocationInfo(_, l, c, _, _) |
|
||||
result = this.getKind() + "@" + l + ":" + c
|
||||
)
|
||||
}
|
||||
|
||||
override predicate hasLocationInfo(
|
||||
@@ -217,7 +219,7 @@ abstract class SsaImplicitDefinition extends SsaDefinition {
|
||||
) {
|
||||
endline = startline and
|
||||
endcolumn = startcolumn and
|
||||
getBasicBlock().hasLocationInfo(filepath, startline, startcolumn, _, _)
|
||||
this.getBasicBlock().hasLocationInfo(filepath, startline, startcolumn, _, _)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -233,18 +235,18 @@ class SsaVariableCapture extends SsaImplicitDefinition, TCapture {
|
||||
this = TCapture(bb, i, v)
|
||||
}
|
||||
|
||||
override ReachableBasicBlock getBasicBlock() { definesAt(result, _, _) }
|
||||
override ReachableBasicBlock getBasicBlock() { this.definesAt(result, _, _) }
|
||||
|
||||
override SsaSourceVariable getSourceVariable() { definesAt(_, _, result) }
|
||||
override SsaSourceVariable getSourceVariable() { this.definesAt(_, _, result) }
|
||||
|
||||
override string getKind() { result = "capture" }
|
||||
|
||||
override string prettyPrintDef() { result = "capture variable " + getSourceVariable() }
|
||||
override string prettyPrintDef() { result = "capture variable " + this.getSourceVariable() }
|
||||
|
||||
override predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) {
|
||||
exists(ReachableBasicBlock bb, int i | definesAt(bb, i, _) |
|
||||
exists(ReachableBasicBlock bb, int i | this.definesAt(bb, i, _) |
|
||||
bb.getNode(i).hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
|
||||
)
|
||||
}
|
||||
@@ -264,7 +266,7 @@ abstract class SsaPseudoDefinition extends SsaImplicitDefinition {
|
||||
* Gets a textual representation of the inputs of this pseudo-definition
|
||||
* in lexicographical order.
|
||||
*/
|
||||
string ppInputs() { result = concat(getAnInput().getDefinition().prettyPrintRef(), ", ") }
|
||||
string ppInputs() { result = concat(this.getAnInput().getDefinition().prettyPrintRef(), ", ") }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -274,11 +276,11 @@ abstract class SsaPseudoDefinition extends SsaImplicitDefinition {
|
||||
*/
|
||||
class SsaPhiNode extends SsaPseudoDefinition, TPhi {
|
||||
override SsaVariable getAnInput() {
|
||||
result = getDefReachingEndOf(getBasicBlock().getAPredecessor(), getSourceVariable())
|
||||
result = getDefReachingEndOf(this.getBasicBlock().getAPredecessor(), this.getSourceVariable())
|
||||
}
|
||||
|
||||
override predicate definesAt(ReachableBasicBlock bb, int i, SsaSourceVariable v) {
|
||||
bb = getBasicBlock() and v = getSourceVariable() and i = -1
|
||||
bb = this.getBasicBlock() and v = this.getSourceVariable() and i = -1
|
||||
}
|
||||
|
||||
override ReachableBasicBlock getBasicBlock() { this = TPhi(result, _) }
|
||||
@@ -287,14 +289,16 @@ class SsaPhiNode extends SsaPseudoDefinition, TPhi {
|
||||
|
||||
override string getKind() { result = "phi" }
|
||||
|
||||
override string prettyPrintDef() { result = getSourceVariable() + " = phi(" + ppInputs() + ")" }
|
||||
override string prettyPrintDef() {
|
||||
result = this.getSourceVariable() + " = phi(" + this.ppInputs() + ")"
|
||||
}
|
||||
|
||||
override predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
) {
|
||||
endline = startline and
|
||||
endcolumn = startcolumn and
|
||||
getBasicBlock().hasLocationInfo(filepath, startline, startcolumn, _, _)
|
||||
this.getBasicBlock().hasLocationInfo(filepath, startline, startcolumn, _, _)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ class RedirectCheckBarrierGuard extends DataFlow::BarrierGuard, DataFlow::CallNo
|
||||
|
||||
override predicate checks(Expr e, boolean outcome) {
|
||||
// `isLocalUrl(e)` is a barrier for `e` if it evaluates to `true`
|
||||
getAnArgument().asExpr() = e and
|
||||
this.getAnArgument().asExpr() = e and
|
||||
outcome = true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -104,12 +104,12 @@ abstract class Configuration extends string {
|
||||
/**
|
||||
* Holds if data may flow from some source to `sink` for this configuration.
|
||||
*/
|
||||
predicate hasFlowTo(Node sink) { hasFlow(_, sink) }
|
||||
predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) }
|
||||
|
||||
/**
|
||||
* Holds if data may flow from some source to `sink` for this configuration.
|
||||
*/
|
||||
predicate hasFlowToExpr(DataFlowExpr sink) { hasFlowTo(exprNode(sink)) }
|
||||
predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) }
|
||||
|
||||
/**
|
||||
* Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev`
|
||||
@@ -2873,7 +2873,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
|
||||
}
|
||||
|
||||
override string toString() {
|
||||
result = "[" + this.toStringImpl(true) + length().toString() + ")]"
|
||||
result = "[" + this.toStringImpl(true) + this.length().toString() + ")]"
|
||||
or
|
||||
result = "[" + this.toStringImpl(false)
|
||||
}
|
||||
@@ -3008,9 +3008,11 @@ abstract private class PathNodeImpl extends PathNode {
|
||||
result = " <" + this.(PathNodeMid).getCallContext().toString() + ">"
|
||||
}
|
||||
|
||||
override string toString() { result = this.getNode().toString() + ppAp() }
|
||||
override string toString() { result = this.getNode().toString() + this.ppAp() }
|
||||
|
||||
override string toStringWithContext() { result = this.getNode().toString() + ppAp() + ppCtx() }
|
||||
override string toStringWithContext() {
|
||||
result = this.getNode().toString() + this.ppAp() + this.ppCtx()
|
||||
}
|
||||
|
||||
override predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
@@ -3070,11 +3072,11 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid {
|
||||
|
||||
override PathNodeImpl getASuccessorImpl() {
|
||||
// an intermediate step to another intermediate node
|
||||
result = getSuccMid()
|
||||
result = this.getSuccMid()
|
||||
or
|
||||
// a final step to a sink via zero steps means we merge the last two steps to prevent trivial-looking edges
|
||||
exists(PathNodeMid mid, PathNodeSink sink |
|
||||
mid = getSuccMid() and
|
||||
mid = this.getSuccMid() and
|
||||
mid.getNode() = sink.getNode() and
|
||||
mid.getAp() instanceof AccessPathNil and
|
||||
sink.getConfiguration() = unbindConf(mid.getConfiguration()) and
|
||||
|
||||
@@ -104,12 +104,12 @@ abstract class Configuration extends string {
|
||||
/**
|
||||
* Holds if data may flow from some source to `sink` for this configuration.
|
||||
*/
|
||||
predicate hasFlowTo(Node sink) { hasFlow(_, sink) }
|
||||
predicate hasFlowTo(Node sink) { this.hasFlow(_, sink) }
|
||||
|
||||
/**
|
||||
* Holds if data may flow from some source to `sink` for this configuration.
|
||||
*/
|
||||
predicate hasFlowToExpr(DataFlowExpr sink) { hasFlowTo(exprNode(sink)) }
|
||||
predicate hasFlowToExpr(DataFlowExpr sink) { this.hasFlowTo(exprNode(sink)) }
|
||||
|
||||
/**
|
||||
* Gets the exploration limit for `hasPartialFlow` and `hasPartialFlowRev`
|
||||
@@ -2873,7 +2873,7 @@ private class AccessPathCons extends AccessPath, TAccessPathCons {
|
||||
}
|
||||
|
||||
override string toString() {
|
||||
result = "[" + this.toStringImpl(true) + length().toString() + ")]"
|
||||
result = "[" + this.toStringImpl(true) + this.length().toString() + ")]"
|
||||
or
|
||||
result = "[" + this.toStringImpl(false)
|
||||
}
|
||||
@@ -3008,9 +3008,11 @@ abstract private class PathNodeImpl extends PathNode {
|
||||
result = " <" + this.(PathNodeMid).getCallContext().toString() + ">"
|
||||
}
|
||||
|
||||
override string toString() { result = this.getNode().toString() + ppAp() }
|
||||
override string toString() { result = this.getNode().toString() + this.ppAp() }
|
||||
|
||||
override string toStringWithContext() { result = this.getNode().toString() + ppAp() + ppCtx() }
|
||||
override string toStringWithContext() {
|
||||
result = this.getNode().toString() + this.ppAp() + this.ppCtx()
|
||||
}
|
||||
|
||||
override predicate hasLocationInfo(
|
||||
string filepath, int startline, int startcolumn, int endline, int endcolumn
|
||||
@@ -3070,11 +3072,11 @@ private class PathNodeMid extends PathNodeImpl, TPathNodeMid {
|
||||
|
||||
override PathNodeImpl getASuccessorImpl() {
|
||||
// an intermediate step to another intermediate node
|
||||
result = getSuccMid()
|
||||
result = this.getSuccMid()
|
||||
or
|
||||
// a final step to a sink via zero steps means we merge the last two steps to prevent trivial-looking edges
|
||||
exists(PathNodeMid mid, PathNodeSink sink |
|
||||
mid = getSuccMid() and
|
||||
mid = this.getSuccMid() and
|
||||
mid.getNode() = sink.getNode() and
|
||||
mid.getAp() instanceof AccessPathNil and
|
||||
sink.getConfiguration() = unbindConf(mid.getConfiguration()) and
|
||||
|
||||
@@ -924,7 +924,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() }
|
||||
@@ -1195,7 +1195,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 {
|
||||
|
||||
@@ -24,7 +24,7 @@ class Node extends TNode {
|
||||
ControlFlow::Root getRoot() { none() } // overridden in subclasses
|
||||
|
||||
/** INTERNAL: Use `getRoot()` instead. */
|
||||
FuncDef getEnclosingCallable() { result = getRoot() }
|
||||
FuncDef getEnclosingCallable() { result = this.getRoot() }
|
||||
|
||||
/** Gets the type of this node. */
|
||||
Type getType() { none() } // overridden in subclasses
|
||||
@@ -42,7 +42,7 @@ class Node extends TNode {
|
||||
string getNodeKind() { none() } // overridden in subclasses
|
||||
|
||||
/** Gets the basic block to which this data-flow node belongs, if any. */
|
||||
BasicBlock getBasicBlock() { result = asInstruction().getBasicBlock() }
|
||||
BasicBlock getBasicBlock() { result = this.asInstruction().getBasicBlock() }
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = "data-flow node" } // overridden in subclasses
|
||||
@@ -65,24 +65,24 @@ class Node extends TNode {
|
||||
}
|
||||
|
||||
/** Gets the file in which this node appears. */
|
||||
File getFile() { hasLocationInfo(result.getAbsolutePath(), _, _, _, _) }
|
||||
File getFile() { this.hasLocationInfo(result.getAbsolutePath(), _, _, _, _) }
|
||||
|
||||
/** Gets the start line of the location of this node. */
|
||||
int getStartLine() { hasLocationInfo(_, result, _, _, _) }
|
||||
int getStartLine() { this.hasLocationInfo(_, result, _, _, _) }
|
||||
|
||||
/** Gets the start column of the location of this node. */
|
||||
int getStartColumn() { hasLocationInfo(_, _, result, _, _) }
|
||||
int getStartColumn() { this.hasLocationInfo(_, _, result, _, _) }
|
||||
|
||||
/** Gets the end line of the location of this node. */
|
||||
int getEndLine() { hasLocationInfo(_, _, _, result, _) }
|
||||
int getEndLine() { this.hasLocationInfo(_, _, _, result, _) }
|
||||
|
||||
/** Gets the end column of the location of this node. */
|
||||
int getEndColumn() { hasLocationInfo(_, _, _, _, result) }
|
||||
int getEndColumn() { this.hasLocationInfo(_, _, _, _, result) }
|
||||
|
||||
/**
|
||||
* Gets an upper bound on the type of this node.
|
||||
*/
|
||||
Type getTypeBound() { result = getType() }
|
||||
Type getTypeBound() { result = this.getType() }
|
||||
|
||||
/** Gets the floating-point value this data-flow node contains, if any. */
|
||||
float getFloatValue() { result = this.asExpr().getFloatValue() }
|
||||
@@ -277,7 +277,7 @@ class FunctionNode extends Node {
|
||||
/**
|
||||
* Gets the data-flow node corresponding to the `i`th result of this function.
|
||||
*/
|
||||
ResultNode getResult(int i) { result = getAResult() and result.getIndex() = i }
|
||||
ResultNode getResult(int i) { result = this.getAResult() and result.getIndex() = i }
|
||||
|
||||
/**
|
||||
* Gets the function entity this node corresponds to.
|
||||
@@ -312,7 +312,7 @@ class GlobalFunctionNode extends FunctionNode::Range, MkGlobalFunctionNode {
|
||||
}
|
||||
|
||||
override ResultNode getAResult() {
|
||||
result.getRoot() = getFunction().(DeclaredFunction).getFuncDecl()
|
||||
result.getRoot() = this.getFunction().(DeclaredFunction).getFuncDecl()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -328,7 +328,7 @@ class FuncLitNode extends FunctionNode::Range, ExprNode {
|
||||
|
||||
override string toString() { result = "function literal" }
|
||||
|
||||
override ResultNode getAResult() { result.getRoot() = getExpr() }
|
||||
override ResultNode getAResult() { result.getRoot() = this.getExpr() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -364,9 +364,9 @@ class CallNode extends ExprNode {
|
||||
* interface type.
|
||||
*/
|
||||
FuncDef getACallee() {
|
||||
result = getTarget().(DeclaredFunction).getFuncDecl()
|
||||
result = this.getTarget().(DeclaredFunction).getFuncDecl()
|
||||
or
|
||||
exists(DataFlow::Node calleeSource | calleeSource = getACalleeSource() |
|
||||
exists(DataFlow::Node calleeSource | calleeSource = this.getACalleeSource() |
|
||||
result = calleeSource.asExpr()
|
||||
or
|
||||
exists(Method declared, Method actual |
|
||||
@@ -418,7 +418,7 @@ class CallNode extends ExprNode {
|
||||
* If there is a single result then it is considered to be the 0th result.
|
||||
*/
|
||||
Node getResult(int i) {
|
||||
i = 0 and result = getResult()
|
||||
i = 0 and result = this.getResult()
|
||||
or
|
||||
result = extractTupleElement(this, i)
|
||||
}
|
||||
@@ -429,13 +429,13 @@ class CallNode extends ExprNode {
|
||||
* Note that this predicate is not defined for calls with multiple results; use the one-argument
|
||||
* variant `getResult(i)` for such calls.
|
||||
*/
|
||||
Node getResult() { not getType() instanceof TupleType and result = this }
|
||||
Node getResult() { not this.getType() instanceof TupleType and result = this }
|
||||
|
||||
/** Gets a result of this call. */
|
||||
Node getAResult() { result = this.getResult(_) }
|
||||
|
||||
/** Gets the data flow node corresponding to the receiver of this call, if any. */
|
||||
Node getReceiver() { result = getACalleeSource().(MethodReadNode).getReceiver() }
|
||||
Node getReceiver() { result = this.getACalleeSource().(MethodReadNode).getReceiver() }
|
||||
|
||||
/** Holds if this call has an ellipsis after its last argument. */
|
||||
predicate hasEllipsis() { expr.hasEllipsis() }
|
||||
@@ -702,7 +702,7 @@ class ElementReadNode extends ComponentReadNode {
|
||||
Node getIndex() { result = instructionNode(insn.getIndex()) }
|
||||
|
||||
/** Holds if this data-flow node reads element `index` of `base`. */
|
||||
predicate reads(Node base, Node index) { readsElement(base, index) }
|
||||
predicate reads(Node base, Node index) { this.readsElement(base, index) }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -734,14 +734,14 @@ class BinaryOperationNode extends Node {
|
||||
string op;
|
||||
|
||||
BinaryOperationNode() {
|
||||
exists(BinaryExpr bin | bin = asExpr() |
|
||||
exists(BinaryExpr bin | bin = this.asExpr() |
|
||||
left = exprNode(bin.getLeftOperand()) and
|
||||
right = exprNode(bin.getRightOperand()) and
|
||||
op = bin.getOperator()
|
||||
)
|
||||
or
|
||||
exists(IR::EvalCompoundAssignRhsInstruction rhs, CompoundAssignStmt assgn, string o |
|
||||
rhs = asInstruction() and assgn = rhs.getAssignment() and o = assgn.getOperator()
|
||||
rhs = this.asInstruction() and assgn = rhs.getAssignment() and o = assgn.getOperator()
|
||||
|
|
||||
left = exprNode(assgn.getLhs()) and
|
||||
right = exprNode(assgn.getRhs()) and
|
||||
@@ -749,7 +749,7 @@ class BinaryOperationNode extends Node {
|
||||
)
|
||||
or
|
||||
exists(IR::EvalIncDecRhsInstruction rhs, IncDecStmt ids |
|
||||
rhs = asInstruction() and ids = rhs.getStmt()
|
||||
rhs = this.asInstruction() and ids = rhs.getStmt()
|
||||
|
|
||||
left = exprNode(ids.getOperand()) and
|
||||
right = instructionNode(any(IR::EvalImplicitOneInstruction one | one.getStmt() = ids)) and
|
||||
@@ -758,7 +758,7 @@ class BinaryOperationNode extends Node {
|
||||
}
|
||||
|
||||
/** Holds if this operation may have observable side effects. */
|
||||
predicate mayHaveSideEffects() { asExpr().mayHaveOwnSideEffects() }
|
||||
predicate mayHaveSideEffects() { this.asExpr().mayHaveOwnSideEffects() }
|
||||
|
||||
/** Gets the left operand of this operation. */
|
||||
Node getLeftOperand() { result = left }
|
||||
@@ -774,8 +774,8 @@ class BinaryOperationNode extends Node {
|
||||
|
||||
/** Holds if `x` and `y` are the operands of this operation, in either order. */
|
||||
predicate hasOperands(Node x, Node y) {
|
||||
x = getAnOperand() and
|
||||
y = getAnOperand() and
|
||||
x = this.getAnOperand() and
|
||||
y = this.getAnOperand() and
|
||||
x != y
|
||||
}
|
||||
}
|
||||
@@ -785,34 +785,34 @@ class BinaryOperationNode extends Node {
|
||||
*/
|
||||
class UnaryOperationNode extends InstructionNode {
|
||||
UnaryOperationNode() {
|
||||
asExpr() instanceof UnaryExpr
|
||||
this.asExpr() instanceof UnaryExpr
|
||||
or
|
||||
asExpr() instanceof StarExpr
|
||||
this.asExpr() instanceof StarExpr
|
||||
or
|
||||
insn instanceof IR::EvalImplicitDerefInstruction
|
||||
}
|
||||
|
||||
/** Holds if this operation may have observable side effects. */
|
||||
predicate mayHaveSideEffects() {
|
||||
asExpr().mayHaveOwnSideEffects()
|
||||
this.asExpr().mayHaveOwnSideEffects()
|
||||
or
|
||||
insn instanceof IR::EvalImplicitDerefInstruction
|
||||
}
|
||||
|
||||
/** Gets the operand of this operation. */
|
||||
Node getOperand() {
|
||||
result = exprNode(asExpr().(UnaryExpr).getOperand())
|
||||
result = exprNode(this.asExpr().(UnaryExpr).getOperand())
|
||||
or
|
||||
result = exprNode(asExpr().(StarExpr).getBase())
|
||||
result = exprNode(this.asExpr().(StarExpr).getBase())
|
||||
or
|
||||
result = exprNode(insn.(IR::EvalImplicitDerefInstruction).getOperand())
|
||||
}
|
||||
|
||||
/** Gets the operator of this operation. */
|
||||
string getOperator() {
|
||||
result = asExpr().(UnaryExpr).getOperator()
|
||||
result = this.asExpr().(UnaryExpr).getOperator()
|
||||
or
|
||||
asExpr() instanceof StarExpr and
|
||||
this.asExpr() instanceof StarExpr and
|
||||
result = "*"
|
||||
or
|
||||
insn instanceof IR::EvalImplicitDerefInstruction and
|
||||
@@ -825,9 +825,9 @@ class UnaryOperationNode extends InstructionNode {
|
||||
*/
|
||||
class PointerDereferenceNode extends UnaryOperationNode {
|
||||
PointerDereferenceNode() {
|
||||
asExpr() instanceof StarExpr
|
||||
this.asExpr() instanceof StarExpr
|
||||
or
|
||||
asExpr() instanceof DerefExpr
|
||||
this.asExpr() instanceof DerefExpr
|
||||
or
|
||||
insn instanceof IR::EvalImplicitDerefInstruction
|
||||
}
|
||||
@@ -1173,7 +1173,7 @@ abstract class BarrierGuard extends Node {
|
||||
Function f, FunctionInput inp, FunctionOutput outp, DataFlow::Property p, CallNode c,
|
||||
Node resNode, Node check, boolean outcome
|
||||
|
|
||||
guardingFunction(f, inp, outp, p) and
|
||||
this.guardingFunction(f, inp, outp, p) and
|
||||
c = f.getACall() and
|
||||
nd = inp.getNode(c) and
|
||||
localFlow(pragma[only_bind_into](outp.getNode(c)), resNode) and
|
||||
|
||||
@@ -23,6 +23,6 @@ private class JsonIteratorUnmarshalFunction extends TaintTracking::FunctionModel
|
||||
override string getFormat() { result = "JSON" }
|
||||
|
||||
override predicate hasTaintFlow(DataFlow::FunctionInput inp, DataFlow::FunctionOutput outp) {
|
||||
inp = getAnInput() and outp = getOutput()
|
||||
inp = this.getAnInput() and outp = this.getOutput()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ module K8sIoApiCoreV1 {
|
||||
override string getFormat() { result = "protobuf" }
|
||||
|
||||
override predicate hasTaintFlow(DataFlow::FunctionInput inp, DataFlow::FunctionOutput outp) {
|
||||
inp = getAnInput() and outp = getOutput()
|
||||
inp = this.getAnInput() and outp = this.getOutput()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,7 +55,7 @@ module K8sIoApiCoreV1 {
|
||||
override string getFormat() { result = "protobuf" }
|
||||
|
||||
override predicate hasTaintFlow(DataFlow::FunctionInput inp, DataFlow::FunctionOutput outp) {
|
||||
inp = getAnInput() and outp = getOutput()
|
||||
inp = this.getAnInput() and outp = this.getOutput()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ module K8sIoApimachineryPkgRuntime {
|
||||
}
|
||||
|
||||
override predicate hasTaintFlow(DataFlow::FunctionInput inp, DataFlow::FunctionOutput outp) {
|
||||
inp = getAnInput() and outp = getOutput()
|
||||
inp = this.getAnInput() and outp = this.getOutput()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,7 +64,7 @@ module K8sIoApimachineryPkgRuntime {
|
||||
}
|
||||
|
||||
override predicate hasTaintFlow(DataFlow::FunctionInput inp, DataFlow::FunctionOutput outp) {
|
||||
inp = getAnInput() and outp = getOutput()
|
||||
inp = this.getAnInput() and outp = this.getOutput()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -100,7 +100,7 @@ module K8sIoApimachineryPkgRuntime {
|
||||
}
|
||||
|
||||
override predicate hasTaintFlow(DataFlow::FunctionInput inp, DataFlow::FunctionOutput outp) {
|
||||
inp = getAnInput() and outp = getOutput()
|
||||
inp = this.getAnInput() and outp = this.getOutput()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,7 +129,7 @@ module K8sIoApimachineryPkgRuntime {
|
||||
}
|
||||
|
||||
override predicate hasTaintFlow(DataFlow::FunctionInput inp, DataFlow::FunctionOutput outp) {
|
||||
inp = getAnInput() and outp = getOutput()
|
||||
inp = this.getAnInput() and outp = this.getOutput()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -150,7 +150,7 @@ module K8sIoApimachineryPkgRuntime {
|
||||
}
|
||||
|
||||
override predicate hasTaintFlow(DataFlow::FunctionInput inp, DataFlow::FunctionOutput outp) {
|
||||
inp = getAnInput() and outp = getOutput()
|
||||
inp = this.getAnInput() and outp = this.getOutput()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -191,7 +191,7 @@ module K8sIoApimachineryPkgRuntime {
|
||||
}
|
||||
|
||||
override predicate hasTaintFlow(DataFlow::FunctionInput inp, DataFlow::FunctionOutput outp) {
|
||||
inp = getAnInput() and outp = getOutput()
|
||||
inp = this.getAnInput() and outp = this.getOutput()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -255,7 +255,7 @@ module K8sIoApimachineryPkgRuntime {
|
||||
}
|
||||
|
||||
override predicate hasTaintFlow(DataFlow::FunctionInput inp, DataFlow::FunctionOutput outp) {
|
||||
inp = getAnInput() and outp = getOutput()
|
||||
inp = this.getAnInput() and outp = this.getOutput()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -275,7 +275,7 @@ module K8sIoApimachineryPkgRuntime {
|
||||
}
|
||||
|
||||
override predicate hasTaintFlow(DataFlow::FunctionInput inp, DataFlow::FunctionOutput outp) {
|
||||
inp = getAnInput() and outp = getOutput()
|
||||
inp = this.getAnInput() and outp = this.getOutput()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -293,7 +293,7 @@ module K8sIoApimachineryPkgRuntime {
|
||||
override string getFormat() { result = "protobuf" }
|
||||
|
||||
override predicate hasTaintFlow(DataFlow::FunctionInput inp, DataFlow::FunctionOutput outp) {
|
||||
inp = getAnInput() and outp = getOutput()
|
||||
inp = this.getAnInput() and outp = this.getOutput()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -326,7 +326,7 @@ module K8sIoApimachineryPkgRuntime {
|
||||
override string getFormat() { result = "protobuf" }
|
||||
|
||||
override predicate hasTaintFlow(DataFlow::FunctionInput inp, DataFlow::FunctionOutput outp) {
|
||||
inp = getAnInput() and outp = getOutput()
|
||||
inp = this.getAnInput() and outp = this.getOutput()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -341,7 +341,7 @@ module K8sIoApimachineryPkgRuntime {
|
||||
override string getFormat() { result = "protobuf" }
|
||||
|
||||
override predicate hasTaintFlow(DataFlow::FunctionInput inp, DataFlow::FunctionOutput outp) {
|
||||
inp = getAnInput() and outp = getOutput()
|
||||
inp = this.getAnInput() and outp = this.getOutput()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -383,7 +383,7 @@ module K8sIoApimachineryPkgRuntime {
|
||||
override string getFormat() { result = "protobuf" }
|
||||
|
||||
override predicate hasTaintFlow(DataFlow::FunctionInput inp, DataFlow::FunctionOutput outp) {
|
||||
inp = getAnInput() and outp = getOutput()
|
||||
inp = this.getAnInput() and outp = this.getOutput()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -398,7 +398,7 @@ module K8sIoApimachineryPkgRuntime {
|
||||
override string getFormat() { result = "protobuf" }
|
||||
|
||||
override predicate hasTaintFlow(DataFlow::FunctionInput inp, DataFlow::FunctionOutput outp) {
|
||||
inp = getAnInput() and outp = getOutput()
|
||||
inp = this.getAnInput() and outp = this.getOutput()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ module Protobuf {
|
||||
}
|
||||
|
||||
override predicate hasTaintFlow(DataFlow::FunctionInput inp, DataFlow::FunctionOutput outp) {
|
||||
inp = getAnInput() and outp = getOutput()
|
||||
inp = this.getAnInput() and outp = this.getOutput()
|
||||
}
|
||||
|
||||
override DataFlow::FunctionInput getAnInput() {
|
||||
@@ -89,7 +89,7 @@ module Protobuf {
|
||||
}
|
||||
|
||||
override predicate hasTaintFlow(DataFlow::FunctionInput inp, DataFlow::FunctionOutput outp) {
|
||||
inp = getAnInput() and outp = getOutput()
|
||||
inp = this.getAnInput() and outp = this.getOutput()
|
||||
}
|
||||
|
||||
override DataFlow::FunctionInput getAnInput() { result.isParameter(0) }
|
||||
|
||||
@@ -165,7 +165,7 @@ module Revel {
|
||||
any(Method m | m.hasQualifiedName(packagePath(), "Controller", "RenderFileName")).getACall()
|
||||
}
|
||||
|
||||
override DataFlow::Node getAPathArgument() { result = getArgument(0) }
|
||||
override DataFlow::Node getAPathArgument() { result = this.getArgument(0) }
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -31,7 +31,7 @@ module Spew {
|
||||
|
||||
/** The `Sprint` function or one of its variants. */
|
||||
class Sprinter extends TaintTracking::FunctionModel {
|
||||
Sprinter() { hasQualifiedName(packagePath(), ["Sdump", "Sprint", "Sprintln", "Sprintf"]) }
|
||||
Sprinter() { this.hasQualifiedName(packagePath(), ["Sdump", "Sprint", "Sprintln", "Sprintf"]) }
|
||||
|
||||
override predicate hasTaintFlow(FunctionInput inp, FunctionOutput outp) {
|
||||
inp.isParameter(_) and outp.isResult()
|
||||
|
||||
@@ -18,7 +18,7 @@ private class ShellOrSudoExecution extends SystemCommandExecution::Range, DataFl
|
||||
not hasSafeSubcommand(shellCommand.getStringValue(), this.getAnArgument().getStringValue())
|
||||
}
|
||||
|
||||
override DataFlow::Node getCommandName() { result = getAnArgument() }
|
||||
override DataFlow::Node getCommandName() { result = this.getAnArgument() }
|
||||
|
||||
override predicate doubleDashIsSanitizing() { shellCommand.getStringValue().matches("%git") }
|
||||
}
|
||||
@@ -70,7 +70,7 @@ private class GoShCommandExecution extends SystemCommandExecution::Range, DataFl
|
||||
)
|
||||
or
|
||||
// Catch calls to the `Command` function:
|
||||
getTarget().hasQualifiedName(packagePath, "Command")
|
||||
this.getTarget().hasQualifiedName(packagePath, "Command")
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -23,10 +23,10 @@ module XNetHtml {
|
||||
}
|
||||
|
||||
private class FunctionModels extends TaintTracking::FunctionModel {
|
||||
FunctionModels() { hasQualifiedName(packagePath(), _) }
|
||||
FunctionModels() { this.hasQualifiedName(packagePath(), _) }
|
||||
|
||||
override predicate hasTaintFlow(DataFlow::FunctionInput input, DataFlow::FunctionOutput output) {
|
||||
getName() =
|
||||
this.getName() =
|
||||
[
|
||||
"UnescapeString", "Parse", "ParseFragment", "ParseFragmentWithOptions",
|
||||
"ParseWithOptions", "NewTokenizer", "NewTokenizerFragment"
|
||||
@@ -34,11 +34,11 @@ module XNetHtml {
|
||||
input.isParameter(0) and
|
||||
output.isResult(0)
|
||||
or
|
||||
getName() = ["AppendChild", "InsertBefore"] and
|
||||
this.getName() = ["AppendChild", "InsertBefore"] and
|
||||
input.isParameter(0) and
|
||||
output.isReceiver()
|
||||
or
|
||||
getName() = "Render" and
|
||||
this.getName() = "Render" and
|
||||
input.isParameter(1) and
|
||||
output.isParameter(0)
|
||||
}
|
||||
@@ -50,9 +50,11 @@ module XNetHtml {
|
||||
// Note that `TagName` and the key part of `TagAttr` are not sources by default under the assumption
|
||||
// that their character-set restrictions usually rule them out as useful attack routes.
|
||||
override predicate hasTaintFlow(DataFlow::FunctionInput input, DataFlow::FunctionOutput output) {
|
||||
getName() = ["Buffered", "Raw", "Text", "Token"] and input.isReceiver() and output.isResult(0)
|
||||
this.getName() = ["Buffered", "Raw", "Text", "Token"] and
|
||||
input.isReceiver() and
|
||||
output.isResult(0)
|
||||
or
|
||||
getName() = "TagAttr" and input.isReceiver() and output.isResult(1)
|
||||
this.getName() = "TagAttr" and input.isReceiver() and output.isResult(1)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ module Zap {
|
||||
|
||||
/** The function `Fields` that creates an `Option` that can be added to the logger out of `Field`s. */
|
||||
class FieldsFunction extends TaintTracking::FunctionModel {
|
||||
FieldsFunction() { hasQualifiedName(packagePath(), "Fields") }
|
||||
FieldsFunction() { this.hasQualifiedName(packagePath(), "Fields") }
|
||||
|
||||
override predicate hasTaintFlow(FunctionInput inp, FunctionOutput outp) {
|
||||
inp.isParameter(_) and outp.isResult()
|
||||
|
||||
@@ -114,7 +114,7 @@ module DatabaseSql {
|
||||
|
||||
SqlFunctionModels() {
|
||||
// signature: func Named(name string, value interface{}) NamedArg
|
||||
hasQualifiedName("database/sql", "Named") and
|
||||
this.hasQualifiedName("database/sql", "Named") and
|
||||
(inp.isParameter(_) and outp.isResult())
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@ import go
|
||||
/** Provides models of commonly used functions in the `encoding/json` package. */
|
||||
module EncodingJson {
|
||||
private class Escape extends EscapeFunction::Range {
|
||||
Escape() { hasQualifiedName("encoding/json", "HTMLEscape") }
|
||||
Escape() { this.hasQualifiedName("encoding/json", "HTMLEscape") }
|
||||
|
||||
override string kind() { result = "html" }
|
||||
}
|
||||
@@ -39,35 +39,35 @@ module EncodingJson {
|
||||
|
||||
FunctionModels() {
|
||||
// signature: func Compact(dst *bytes.Buffer, src []byte) error
|
||||
hasQualifiedName("encoding/json", "Compact") and
|
||||
this.hasQualifiedName("encoding/json", "Compact") and
|
||||
(inp.isParameter(1) and outp.isParameter(0))
|
||||
or
|
||||
// signature: func HTMLEscape(dst *bytes.Buffer, src []byte)
|
||||
hasQualifiedName("encoding/json", "HTMLEscape") and
|
||||
this.hasQualifiedName("encoding/json", "HTMLEscape") and
|
||||
(inp.isParameter(1) and outp.isParameter(0))
|
||||
or
|
||||
// signature: func Indent(dst *bytes.Buffer, src []byte, prefix string, indent string) error
|
||||
hasQualifiedName("encoding/json", "Indent") and
|
||||
this.hasQualifiedName("encoding/json", "Indent") and
|
||||
(inp.isParameter([1, 2, 3]) and outp.isParameter(0))
|
||||
or
|
||||
// signature: func Marshal(v interface{}) ([]byte, error)
|
||||
hasQualifiedName("encoding/json", "Marshal") and
|
||||
this.hasQualifiedName("encoding/json", "Marshal") and
|
||||
(inp.isParameter(0) and outp.isResult(0))
|
||||
or
|
||||
// signature: func MarshalIndent(v interface{}, prefix string, indent string) ([]byte, error)
|
||||
hasQualifiedName("encoding/json", "MarshalIndent") and
|
||||
this.hasQualifiedName("encoding/json", "MarshalIndent") and
|
||||
(inp.isParameter(_) and outp.isResult(0))
|
||||
or
|
||||
// signature: func NewDecoder(r io.Reader) *Decoder
|
||||
hasQualifiedName("encoding/json", "NewDecoder") and
|
||||
this.hasQualifiedName("encoding/json", "NewDecoder") and
|
||||
(inp.isParameter(0) and outp.isResult())
|
||||
or
|
||||
// signature: func NewEncoder(w io.Writer) *Encoder
|
||||
hasQualifiedName("encoding/json", "NewEncoder") and
|
||||
this.hasQualifiedName("encoding/json", "NewEncoder") and
|
||||
(inp.isResult() and outp.isParameter(0))
|
||||
or
|
||||
// signature: func Unmarshal(data []byte, v interface{}) error
|
||||
hasQualifiedName("encoding/json", "Unmarshal") and
|
||||
this.hasQualifiedName("encoding/json", "Unmarshal") and
|
||||
(inp.isParameter(0) and outp.isParameter(1))
|
||||
}
|
||||
|
||||
@@ -82,31 +82,31 @@ module EncodingJson {
|
||||
|
||||
MethodModels() {
|
||||
// signature: func (*Decoder) Buffered() io.Reader
|
||||
hasQualifiedName("encoding/json", "Decoder", "Buffered") and
|
||||
this.hasQualifiedName("encoding/json", "Decoder", "Buffered") and
|
||||
(inp.isReceiver() and outp.isResult())
|
||||
or
|
||||
// signature: func (*Decoder) Decode(v interface{}) error
|
||||
hasQualifiedName("encoding/json", "Decoder", "Decode") and
|
||||
this.hasQualifiedName("encoding/json", "Decoder", "Decode") and
|
||||
(inp.isReceiver() and outp.isParameter(0))
|
||||
or
|
||||
// signature: func (*Decoder) Token() (Token, error)
|
||||
hasQualifiedName("encoding/json", "Decoder", "Token") and
|
||||
this.hasQualifiedName("encoding/json", "Decoder", "Token") and
|
||||
(inp.isReceiver() and outp.isResult(0))
|
||||
or
|
||||
// signature: func (*Encoder) Encode(v interface{}) error
|
||||
hasQualifiedName("encoding/json", "Encoder", "Encode") and
|
||||
this.hasQualifiedName("encoding/json", "Encoder", "Encode") and
|
||||
(inp.isParameter(0) and outp.isReceiver())
|
||||
or
|
||||
// signature: func (*Encoder) SetIndent(prefix string, indent string)
|
||||
hasQualifiedName("encoding/json", "Encoder", "SetIndent") and
|
||||
this.hasQualifiedName("encoding/json", "Encoder", "SetIndent") and
|
||||
(inp.isParameter(_) and outp.isReceiver())
|
||||
or
|
||||
// signature: func (Marshaler) MarshalJSON() ([]byte, error)
|
||||
implements("encoding/json", "Marshaler", "MarshalJSON") and
|
||||
this.implements("encoding/json", "Marshaler", "MarshalJSON") and
|
||||
(inp.isReceiver() and outp.isResult(0))
|
||||
or
|
||||
// signature: func (Unmarshaler) UnmarshalJSON([]byte) error
|
||||
implements("encoding/json", "Unmarshaler", "UnmarshalJSON") and
|
||||
this.implements("encoding/json", "Unmarshaler", "UnmarshalJSON") and
|
||||
(inp.isParameter(0) and outp.isReceiver())
|
||||
}
|
||||
|
||||
|
||||
@@ -9,8 +9,8 @@ module EncodingXml {
|
||||
/** The `Marshal` or `MarshalIndent` function in the `encoding/xml` package. */
|
||||
private class MarshalFunction extends MarshalingFunction::Range {
|
||||
MarshalFunction() {
|
||||
hasQualifiedName("encoding/xml", "Marshal") or
|
||||
hasQualifiedName("encoding/xml", "MarshalIndent")
|
||||
this.hasQualifiedName("encoding/xml", "Marshal") or
|
||||
this.hasQualifiedName("encoding/xml", "MarshalIndent")
|
||||
}
|
||||
|
||||
override FunctionInput getAnInput() { result.isParameter(0) }
|
||||
@@ -21,7 +21,7 @@ module EncodingXml {
|
||||
}
|
||||
|
||||
private class UnmarshalFunction extends UnmarshalingFunction::Range {
|
||||
UnmarshalFunction() { hasQualifiedName("encoding/xml", "Unmarshal") }
|
||||
UnmarshalFunction() { this.hasQualifiedName("encoding/xml", "Unmarshal") }
|
||||
|
||||
override FunctionInput getAnInput() { result.isParameter(0) }
|
||||
|
||||
@@ -36,39 +36,39 @@ module EncodingXml {
|
||||
|
||||
FunctionModels() {
|
||||
// signature: func CopyToken(t Token) Token
|
||||
hasQualifiedName("encoding/xml", "CopyToken") and
|
||||
this.hasQualifiedName("encoding/xml", "CopyToken") and
|
||||
(inp.isParameter(0) and outp.isResult())
|
||||
or
|
||||
// signature: func Escape(w io.Writer, s []byte)
|
||||
hasQualifiedName("encoding/xml", "Escape") and
|
||||
this.hasQualifiedName("encoding/xml", "Escape") and
|
||||
(inp.isParameter(1) and outp.isParameter(0))
|
||||
or
|
||||
// signature: func EscapeText(w io.Writer, s []byte) error
|
||||
hasQualifiedName("encoding/xml", "EscapeText") and
|
||||
this.hasQualifiedName("encoding/xml", "EscapeText") and
|
||||
(inp.isParameter(1) and outp.isParameter(0))
|
||||
or
|
||||
// signature: func Marshal(v interface{}) ([]byte, error)
|
||||
hasQualifiedName("encoding/xml", "Marshal") and
|
||||
this.hasQualifiedName("encoding/xml", "Marshal") and
|
||||
(inp.isParameter(0) and outp.isResult(0))
|
||||
or
|
||||
// signature: func MarshalIndent(v interface{}, prefix string, indent string) ([]byte, error)
|
||||
hasQualifiedName("encoding/xml", "MarshalIndent") and
|
||||
this.hasQualifiedName("encoding/xml", "MarshalIndent") and
|
||||
(inp.isParameter(_) and outp.isResult(0))
|
||||
or
|
||||
// signature: func NewDecoder(r io.Reader) *Decoder
|
||||
hasQualifiedName("encoding/xml", "NewDecoder") and
|
||||
this.hasQualifiedName("encoding/xml", "NewDecoder") and
|
||||
(inp.isParameter(0) and outp.isResult())
|
||||
or
|
||||
// signature: func NewEncoder(w io.Writer) *Encoder
|
||||
hasQualifiedName("encoding/xml", "NewEncoder") and
|
||||
this.hasQualifiedName("encoding/xml", "NewEncoder") and
|
||||
(inp.isResult() and outp.isParameter(0))
|
||||
or
|
||||
// signature: func NewTokenDecoder(t TokenReader) *Decoder
|
||||
hasQualifiedName("encoding/xml", "NewTokenDecoder") and
|
||||
this.hasQualifiedName("encoding/xml", "NewTokenDecoder") and
|
||||
(inp.isParameter(0) and outp.isResult())
|
||||
or
|
||||
// signature: func Unmarshal(data []byte, v interface{}) error
|
||||
hasQualifiedName("encoding/xml", "Unmarshal") and
|
||||
this.hasQualifiedName("encoding/xml", "Unmarshal") and
|
||||
(inp.isParameter(0) and outp.isParameter(1))
|
||||
}
|
||||
|
||||
@@ -83,55 +83,55 @@ module EncodingXml {
|
||||
|
||||
MethodModels() {
|
||||
// signature: func (CharData) Copy() CharData
|
||||
hasQualifiedName("encoding/xml", "CharData", "Copy") and
|
||||
this.hasQualifiedName("encoding/xml", "CharData", "Copy") and
|
||||
(inp.isReceiver() and outp.isResult())
|
||||
or
|
||||
// signature: func (Comment) Copy() Comment
|
||||
hasQualifiedName("encoding/xml", "Comment", "Copy") and
|
||||
this.hasQualifiedName("encoding/xml", "Comment", "Copy") and
|
||||
(inp.isReceiver() and outp.isResult())
|
||||
or
|
||||
// signature: func (*Decoder) Decode(v interface{}) error
|
||||
hasQualifiedName("encoding/xml", "Decoder", "Decode") and
|
||||
this.hasQualifiedName("encoding/xml", "Decoder", "Decode") and
|
||||
(inp.isReceiver() and outp.isParameter(0))
|
||||
or
|
||||
// signature: func (*Decoder) DecodeElement(v interface{}, start *StartElement) error
|
||||
hasQualifiedName("encoding/xml", "Decoder", "DecodeElement") and
|
||||
this.hasQualifiedName("encoding/xml", "Decoder", "DecodeElement") and
|
||||
(inp.isReceiver() and outp.isParameter(0))
|
||||
or
|
||||
// signature: func (*Decoder) RawToken() (Token, error)
|
||||
hasQualifiedName("encoding/xml", "Decoder", "RawToken") and
|
||||
this.hasQualifiedName("encoding/xml", "Decoder", "RawToken") and
|
||||
(inp.isReceiver() and outp.isResult(0))
|
||||
or
|
||||
// signature: func (*Decoder) Token() (Token, error)
|
||||
hasQualifiedName("encoding/xml", "Decoder", "Token") and
|
||||
this.hasQualifiedName("encoding/xml", "Decoder", "Token") and
|
||||
(inp.isReceiver() and outp.isResult(0))
|
||||
or
|
||||
// signature: func (Directive) Copy() Directive
|
||||
hasQualifiedName("encoding/xml", "Directive", "Copy") and
|
||||
this.hasQualifiedName("encoding/xml", "Directive", "Copy") and
|
||||
(inp.isReceiver() and outp.isResult())
|
||||
or
|
||||
// signature: func (*Encoder) Encode(v interface{}) error
|
||||
hasQualifiedName("encoding/xml", "Encoder", "Encode") and
|
||||
this.hasQualifiedName("encoding/xml", "Encoder", "Encode") and
|
||||
(inp.isParameter(0) and outp.isReceiver())
|
||||
or
|
||||
// signature: func (*Encoder) EncodeElement(v interface{}, start StartElement) error
|
||||
hasQualifiedName("encoding/xml", "Encoder", "EncodeElement") and
|
||||
this.hasQualifiedName("encoding/xml", "Encoder", "EncodeElement") and
|
||||
(inp.isParameter(0) and outp.isReceiver())
|
||||
or
|
||||
// signature: func (*Encoder) EncodeToken(t Token) error
|
||||
hasQualifiedName("encoding/xml", "Encoder", "EncodeToken") and
|
||||
this.hasQualifiedName("encoding/xml", "Encoder", "EncodeToken") and
|
||||
(inp.isParameter(0) and outp.isReceiver())
|
||||
or
|
||||
// signature: func (*Encoder) Indent(prefix string, indent string)
|
||||
hasQualifiedName("encoding/xml", "Encoder", "Indent") and
|
||||
this.hasQualifiedName("encoding/xml", "Encoder", "Indent") and
|
||||
(inp.isParameter(_) and outp.isReceiver())
|
||||
or
|
||||
// signature: func (ProcInst) Copy() ProcInst
|
||||
hasQualifiedName("encoding/xml", "ProcInst", "Copy") and
|
||||
this.hasQualifiedName("encoding/xml", "ProcInst", "Copy") and
|
||||
(inp.isReceiver() and outp.isResult())
|
||||
or
|
||||
// signature: func (StartElement) Copy() StartElement
|
||||
hasQualifiedName("encoding/xml", "StartElement", "Copy") and
|
||||
this.hasQualifiedName("encoding/xml", "StartElement", "Copy") and
|
||||
(inp.isReceiver() and outp.isResult())
|
||||
or
|
||||
// signature: func (Marshaler) MarshalXML(e *Encoder, start StartElement) error
|
||||
|
||||
@@ -10,13 +10,13 @@ module Fmt {
|
||||
class Sprinter extends TaintTracking::FunctionModel {
|
||||
Sprinter() {
|
||||
// signature: func Sprint(a ...interface{}) string
|
||||
hasQualifiedName("fmt", "Sprint")
|
||||
this.hasQualifiedName("fmt", "Sprint")
|
||||
or
|
||||
// signature: func Sprintf(format string, a ...interface{}) string
|
||||
hasQualifiedName("fmt", "Sprintf")
|
||||
this.hasQualifiedName("fmt", "Sprintf")
|
||||
or
|
||||
// signature: func Sprintln(a ...interface{}) string
|
||||
hasQualifiedName("fmt", "Sprintln")
|
||||
this.hasQualifiedName("fmt", "Sprintln")
|
||||
}
|
||||
|
||||
override predicate hasTaintFlow(FunctionInput inp, FunctionOutput outp) {
|
||||
@@ -26,7 +26,7 @@ module Fmt {
|
||||
|
||||
/** The `Print` function or one of its variants. */
|
||||
class Printer extends Function {
|
||||
Printer() { hasQualifiedName("fmt", ["Print", "Printf", "Println"]) }
|
||||
Printer() { this.hasQualifiedName("fmt", ["Print", "Printf", "Println"]) }
|
||||
}
|
||||
|
||||
/** A call to `Print`, `Fprint`, or similar. */
|
||||
@@ -48,13 +48,13 @@ module Fmt {
|
||||
private class Fprinter extends TaintTracking::FunctionModel {
|
||||
Fprinter() {
|
||||
// signature: func Fprint(w io.Writer, a ...interface{}) (n int, err error)
|
||||
hasQualifiedName("fmt", "Fprint")
|
||||
this.hasQualifiedName("fmt", "Fprint")
|
||||
or
|
||||
// signature: func Fprintf(w io.Writer, format string, a ...interface{}) (n int, err error)
|
||||
hasQualifiedName("fmt", "Fprintf")
|
||||
this.hasQualifiedName("fmt", "Fprintf")
|
||||
or
|
||||
// signature: func Fprintln(w io.Writer, a ...interface{}) (n int, err error)
|
||||
hasQualifiedName("fmt", "Fprintln")
|
||||
this.hasQualifiedName("fmt", "Fprintln")
|
||||
}
|
||||
|
||||
override predicate hasTaintFlow(FunctionInput input, FunctionOutput output) {
|
||||
@@ -69,15 +69,15 @@ module Fmt {
|
||||
|
||||
Sscanner() {
|
||||
// signature: func Sscan(str string, a ...interface{}) (n int, err error)
|
||||
hasQualifiedName("fmt", "Sscan") and
|
||||
this.hasQualifiedName("fmt", "Sscan") and
|
||||
(inp.isParameter(0) and outp.isParameter(any(int i | i >= 1)))
|
||||
or
|
||||
// signature: func Sscanf(str string, format string, a ...interface{}) (n int, err error)
|
||||
hasQualifiedName("fmt", "Sscanf") and
|
||||
this.hasQualifiedName("fmt", "Sscanf") and
|
||||
(inp.isParameter([0, 1]) and outp.isParameter(any(int i | i >= 2)))
|
||||
or
|
||||
// signature: func Sscanln(str string, a ...interface{}) (n int, err error)
|
||||
hasQualifiedName("fmt", "Sscanln") and
|
||||
this.hasQualifiedName("fmt", "Sscanln") and
|
||||
(inp.isParameter(0) and outp.isParameter(any(int i | i >= 1)))
|
||||
}
|
||||
|
||||
@@ -111,19 +111,19 @@ module Fmt {
|
||||
|
||||
FunctionModels() {
|
||||
// signature: func Errorf(format string, a ...interface{}) error
|
||||
hasQualifiedName("fmt", "Errorf") and
|
||||
this.hasQualifiedName("fmt", "Errorf") and
|
||||
(inp.isParameter(_) and outp.isResult())
|
||||
or
|
||||
// signature: func Fscan(r io.Reader, a ...interface{}) (n int, err error)
|
||||
hasQualifiedName("fmt", "Fscan") and
|
||||
this.hasQualifiedName("fmt", "Fscan") and
|
||||
(inp.isParameter(0) and outp.isParameter(any(int i | i >= 1)))
|
||||
or
|
||||
// signature: func Fscanf(r io.Reader, format string, a ...interface{}) (n int, err error)
|
||||
hasQualifiedName("fmt", "Fscanf") and
|
||||
this.hasQualifiedName("fmt", "Fscanf") and
|
||||
(inp.isParameter([0, 1]) and outp.isParameter(any(int i | i >= 2)))
|
||||
or
|
||||
// signature: func Fscanln(r io.Reader, a ...interface{}) (n int, err error)
|
||||
hasQualifiedName("fmt", "Fscanln") and
|
||||
this.hasQualifiedName("fmt", "Fscanln") and
|
||||
(inp.isParameter(0) and outp.isParameter(any(int i | i >= 1)))
|
||||
}
|
||||
|
||||
@@ -138,19 +138,19 @@ module Fmt {
|
||||
|
||||
MethodModels() {
|
||||
// signature: func (GoStringer) GoString() string
|
||||
implements("fmt", "GoStringer", "GoString") and
|
||||
this.implements("fmt", "GoStringer", "GoString") and
|
||||
(inp.isReceiver() and outp.isResult())
|
||||
or
|
||||
// signature: func (ScanState) Read(buf []byte) (n int, err error)
|
||||
implements("fmt", "ScanState", "Read") and
|
||||
this.implements("fmt", "ScanState", "Read") and
|
||||
(inp.isReceiver() and outp.isParameter(0))
|
||||
or
|
||||
// signature: func (Stringer) String() string
|
||||
implements("fmt", "Stringer", "String") and
|
||||
this.implements("fmt", "Stringer", "String") and
|
||||
(inp.isReceiver() and outp.isResult())
|
||||
or
|
||||
// signature: func (ScanState) Token(skipSpace bool, f func(rune) bool) (token []byte, err error)
|
||||
implements("fmt", "ScanState", "Token") and
|
||||
this.implements("fmt", "ScanState", "Token") and
|
||||
(inp.isReceiver() and outp.isResult(0))
|
||||
or
|
||||
// signature: func (State) Write(b []byte) (n int, err error)
|
||||
|
||||
@@ -17,7 +17,7 @@ module HtmlTemplate {
|
||||
or
|
||||
fn.matches("URLQueryEscape%") and kind = "url"
|
||||
|
|
||||
hasQualifiedName("html/template", fn)
|
||||
this.hasQualifiedName("html/template", fn)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -30,31 +30,31 @@ module HtmlTemplate {
|
||||
|
||||
FunctionModels() {
|
||||
// signature: func HTMLEscape(w io.Writer, b []byte)
|
||||
hasQualifiedName("html/template", "HTMLEscape") and
|
||||
this.hasQualifiedName("html/template", "HTMLEscape") and
|
||||
(inp.isParameter(1) and outp.isParameter(0))
|
||||
or
|
||||
// signature: func HTMLEscapeString(s string) string
|
||||
hasQualifiedName("html/template", "HTMLEscapeString") and
|
||||
this.hasQualifiedName("html/template", "HTMLEscapeString") and
|
||||
(inp.isParameter(0) and outp.isResult())
|
||||
or
|
||||
// signature: func HTMLEscaper(args ...interface{}) string
|
||||
hasQualifiedName("html/template", "HTMLEscaper") and
|
||||
this.hasQualifiedName("html/template", "HTMLEscaper") and
|
||||
(inp.isParameter(_) and outp.isResult())
|
||||
or
|
||||
// signature: func JSEscape(w io.Writer, b []byte)
|
||||
hasQualifiedName("html/template", "JSEscape") and
|
||||
this.hasQualifiedName("html/template", "JSEscape") and
|
||||
(inp.isParameter(1) and outp.isParameter(0))
|
||||
or
|
||||
// signature: func JSEscapeString(s string) string
|
||||
hasQualifiedName("html/template", "JSEscapeString") and
|
||||
this.hasQualifiedName("html/template", "JSEscapeString") and
|
||||
(inp.isParameter(0) and outp.isResult())
|
||||
or
|
||||
// signature: func JSEscaper(args ...interface{}) string
|
||||
hasQualifiedName("html/template", "JSEscaper") and
|
||||
this.hasQualifiedName("html/template", "JSEscaper") and
|
||||
(inp.isParameter(_) and outp.isResult())
|
||||
or
|
||||
// signature: func URLQueryEscaper(args ...interface{}) string
|
||||
hasQualifiedName("html/template", "URLQueryEscaper") and
|
||||
this.hasQualifiedName("html/template", "URLQueryEscaper") and
|
||||
(inp.isParameter(_) and outp.isResult())
|
||||
}
|
||||
|
||||
@@ -69,11 +69,11 @@ module HtmlTemplate {
|
||||
|
||||
MethodModels() {
|
||||
// signature: func (*Template) Execute(wr io.Writer, data interface{}) error
|
||||
hasQualifiedName("html/template", "Template", "Execute") and
|
||||
this.hasQualifiedName("html/template", "Template", "Execute") and
|
||||
(inp.isParameter(1) and outp.isParameter(0))
|
||||
or
|
||||
// signature: func (*Template) ExecuteTemplate(wr io.Writer, name string, data interface{}) error
|
||||
hasQualifiedName("html/template", "Template", "ExecuteTemplate") and
|
||||
this.hasQualifiedName("html/template", "Template", "ExecuteTemplate") and
|
||||
(inp.isParameter(2) and outp.isParameter(0))
|
||||
}
|
||||
|
||||
@@ -100,7 +100,7 @@ module HtmlTemplate {
|
||||
string getBody() { result = text.regexpCapture("(?s)\\{\\{(.*)\\}\\}", 1) } // matches the inside of the curly bracket delimiters
|
||||
|
||||
/** Gets the file in which this statement appears. */
|
||||
File getFile() { hasLocationInfo(result.getAbsolutePath(), _, _, _, _) }
|
||||
File getFile() { this.hasLocationInfo(result.getAbsolutePath(), _, _, _, _) }
|
||||
|
||||
/** Gets a textual representation of this statement. */
|
||||
string toString() { result = "HTML template statement" }
|
||||
@@ -148,7 +148,7 @@ module HtmlTemplate {
|
||||
}
|
||||
|
||||
/** Gets the file in which this read appears. */
|
||||
File getFile() { hasLocationInfo(result.getAbsolutePath(), _, _, _, _) }
|
||||
File getFile() { this.hasLocationInfo(result.getAbsolutePath(), _, _, _, _) }
|
||||
|
||||
/** Gets a textual representation of this statement. */
|
||||
string toString() { result = "HTML template read of " + text }
|
||||
|
||||
@@ -26,7 +26,9 @@ module Log {
|
||||
|
||||
/** A fatal log function, which calls `os.Exit`. */
|
||||
private class FatalLogFunction extends Function {
|
||||
FatalLogFunction() { exists(string fn | fn.matches("Fatal%") | hasQualifiedName("log", fn)) }
|
||||
FatalLogFunction() {
|
||||
exists(string fn | fn.matches("Fatal%") | this.hasQualifiedName("log", fn))
|
||||
}
|
||||
|
||||
override predicate mayReturnNormally() { none() }
|
||||
}
|
||||
@@ -37,7 +39,7 @@ module Log {
|
||||
|
||||
FunctionModels() {
|
||||
// signature: func New(out io.Writer, prefix string, flag int) *Logger
|
||||
hasQualifiedName("log", "New") and
|
||||
this.hasQualifiedName("log", "New") and
|
||||
(inp.isResult() and outp.isParameter(0))
|
||||
}
|
||||
|
||||
@@ -52,51 +54,51 @@ module Log {
|
||||
|
||||
MethodModels() {
|
||||
// signature: func (*Logger) Fatal(v ...interface{})
|
||||
hasQualifiedName("log", "Logger", "Fatal") and
|
||||
this.hasQualifiedName("log", "Logger", "Fatal") and
|
||||
(inp.isParameter(_) and outp.isReceiver())
|
||||
or
|
||||
// signature: func (*Logger) Fatalf(format string, v ...interface{})
|
||||
hasQualifiedName("log", "Logger", "Fatalf") and
|
||||
this.hasQualifiedName("log", "Logger", "Fatalf") and
|
||||
(inp.isParameter(_) and outp.isReceiver())
|
||||
or
|
||||
// signature: func (*Logger) Fatalln(v ...interface{})
|
||||
hasQualifiedName("log", "Logger", "Fatalln") and
|
||||
this.hasQualifiedName("log", "Logger", "Fatalln") and
|
||||
(inp.isParameter(_) and outp.isReceiver())
|
||||
or
|
||||
// signature: func (*Logger) Panic(v ...interface{})
|
||||
hasQualifiedName("log", "Logger", "Panic") and
|
||||
this.hasQualifiedName("log", "Logger", "Panic") and
|
||||
(inp.isParameter(_) and outp.isReceiver())
|
||||
or
|
||||
// signature: func (*Logger) Panicf(format string, v ...interface{})
|
||||
hasQualifiedName("log", "Logger", "Panicf") and
|
||||
this.hasQualifiedName("log", "Logger", "Panicf") and
|
||||
(inp.isParameter(_) and outp.isReceiver())
|
||||
or
|
||||
// signature: func (*Logger) Panicln(v ...interface{})
|
||||
hasQualifiedName("log", "Logger", "Panicln") and
|
||||
this.hasQualifiedName("log", "Logger", "Panicln") and
|
||||
(inp.isParameter(_) and outp.isReceiver())
|
||||
or
|
||||
// signature: func (*Logger) Print(v ...interface{})
|
||||
hasQualifiedName("log", "Logger", "Print") and
|
||||
this.hasQualifiedName("log", "Logger", "Print") and
|
||||
(inp.isParameter(_) and outp.isReceiver())
|
||||
or
|
||||
// signature: func (*Logger) Printf(format string, v ...interface{})
|
||||
hasQualifiedName("log", "Logger", "Printf") and
|
||||
this.hasQualifiedName("log", "Logger", "Printf") and
|
||||
(inp.isParameter(_) and outp.isReceiver())
|
||||
or
|
||||
// signature: func (*Logger) Println(v ...interface{})
|
||||
hasQualifiedName("log", "Logger", "Println") and
|
||||
this.hasQualifiedName("log", "Logger", "Println") and
|
||||
(inp.isParameter(_) and outp.isReceiver())
|
||||
or
|
||||
// signature: func (*Logger) SetOutput(w io.Writer)
|
||||
hasQualifiedName("log", "Logger", "SetOutput") and
|
||||
this.hasQualifiedName("log", "Logger", "SetOutput") and
|
||||
(inp.isReceiver() and outp.isParameter(0))
|
||||
or
|
||||
// signature: func (*Logger) SetPrefix(prefix string)
|
||||
hasQualifiedName("log", "Logger", "SetPrefix") and
|
||||
this.hasQualifiedName("log", "Logger", "SetPrefix") and
|
||||
(inp.isParameter(0) and outp.isReceiver())
|
||||
or
|
||||
// signature: func (*Logger) Writer() io.Writer
|
||||
hasQualifiedName("log", "Logger", "Writer") and
|
||||
this.hasQualifiedName("log", "Logger", "Writer") and
|
||||
(inp.isReceiver() and outp.isResult())
|
||||
}
|
||||
|
||||
|
||||
@@ -284,35 +284,35 @@ module NetHttp {
|
||||
|
||||
FunctionModels() {
|
||||
// signature: func CanonicalHeaderKey(s string) string
|
||||
hasQualifiedName("net/http", "CanonicalHeaderKey") and
|
||||
this.hasQualifiedName("net/http", "CanonicalHeaderKey") and
|
||||
(inp.isParameter(0) and outp.isResult())
|
||||
or
|
||||
// signature: func Error(w ResponseWriter, error string, code int)
|
||||
hasQualifiedName("net/http", "Error") and
|
||||
this.hasQualifiedName("net/http", "Error") and
|
||||
(inp.isParameter(1) and outp.isParameter(0))
|
||||
or
|
||||
// signature: func MaxBytesReader(w ResponseWriter, r io.ReadCloser, n int64) io.ReadCloser
|
||||
hasQualifiedName("net/http", "MaxBytesReader") and
|
||||
this.hasQualifiedName("net/http", "MaxBytesReader") and
|
||||
(inp.isParameter(1) and outp.isResult())
|
||||
or
|
||||
// signature: func NewRequest(method, url string, body io.Reader) (*Request, error)
|
||||
hasQualifiedName("net/http", "NewRequest") and
|
||||
this.hasQualifiedName("net/http", "NewRequest") and
|
||||
(inp.isParameter(1) and outp.isResult(0))
|
||||
or
|
||||
// signature: func NewRequestWithContext(ctx context.Context, method, url string, body io.Reader) (*Request, error)
|
||||
hasQualifiedName("net/http", "NewRequestWithContext") and
|
||||
this.hasQualifiedName("net/http", "NewRequestWithContext") and
|
||||
(inp.isParameter(2) and outp.isResult(0))
|
||||
or
|
||||
// signature: func ReadRequest(b *bufio.Reader) (*Request, error)
|
||||
hasQualifiedName("net/http", "ReadRequest") and
|
||||
this.hasQualifiedName("net/http", "ReadRequest") and
|
||||
(inp.isParameter(0) and outp.isResult(0))
|
||||
or
|
||||
// signature: func ReadResponse(r *bufio.Reader, req *Request) (*Response, error)
|
||||
hasQualifiedName("net/http", "ReadResponse") and
|
||||
this.hasQualifiedName("net/http", "ReadResponse") and
|
||||
(inp.isParameter(0) and outp.isResult(0))
|
||||
or
|
||||
// signature: func SetCookie(w ResponseWriter, cookie *Cookie)
|
||||
hasQualifiedName("net/http", "SetCookie") and
|
||||
this.hasQualifiedName("net/http", "SetCookie") and
|
||||
(inp.isParameter(1) and outp.isParameter(0))
|
||||
}
|
||||
|
||||
@@ -327,63 +327,63 @@ module NetHttp {
|
||||
|
||||
MethodModels() {
|
||||
// signature: func (Header) Add(key string, value string)
|
||||
hasQualifiedName("net/http", "Header", "Add") and
|
||||
this.hasQualifiedName("net/http", "Header", "Add") and
|
||||
(inp.isParameter(_) and outp.isReceiver())
|
||||
or
|
||||
// signature: func (Header) Clone() Header
|
||||
hasQualifiedName("net/http", "Header", "Clone") and
|
||||
this.hasQualifiedName("net/http", "Header", "Clone") and
|
||||
(inp.isReceiver() and outp.isResult())
|
||||
or
|
||||
// signature: func (Header) Get(key string) string
|
||||
hasQualifiedName("net/http", "Header", "Get") and
|
||||
this.hasQualifiedName("net/http", "Header", "Get") and
|
||||
(inp.isReceiver() and outp.isResult())
|
||||
or
|
||||
// signature: func (Header) Set(key string, value string)
|
||||
hasQualifiedName("net/http", "Header", "Set") and
|
||||
this.hasQualifiedName("net/http", "Header", "Set") and
|
||||
(inp.isParameter(_) and outp.isReceiver())
|
||||
or
|
||||
// signature: func (Header) Values(key string) []string
|
||||
hasQualifiedName("net/http", "Header", "Values") and
|
||||
this.hasQualifiedName("net/http", "Header", "Values") and
|
||||
(inp.isReceiver() and outp.isResult())
|
||||
or
|
||||
// signature: func (Header) Write(w io.Writer) error
|
||||
hasQualifiedName("net/http", "Header", "Write") and
|
||||
this.hasQualifiedName("net/http", "Header", "Write") and
|
||||
(inp.isReceiver() and outp.isParameter(0))
|
||||
or
|
||||
// signature: func (Header) WriteSubset(w io.Writer, exclude map[string]bool) error
|
||||
hasQualifiedName("net/http", "Header", "WriteSubset") and
|
||||
this.hasQualifiedName("net/http", "Header", "WriteSubset") and
|
||||
(inp.isReceiver() and outp.isParameter(0))
|
||||
or
|
||||
// signature: func (*Request) AddCookie(c *Cookie)
|
||||
hasQualifiedName("net/http", "Request", "AddCookie") and
|
||||
this.hasQualifiedName("net/http", "Request", "AddCookie") and
|
||||
(inp.isParameter(0) and outp.isReceiver())
|
||||
or
|
||||
// signature: func (*Request) Clone(ctx context.Context) *Request
|
||||
hasQualifiedName("net/http", "Request", "Clone") and
|
||||
this.hasQualifiedName("net/http", "Request", "Clone") and
|
||||
(inp.isReceiver() and outp.isResult())
|
||||
or
|
||||
// signature: func (*Request) Write(w io.Writer) error
|
||||
hasQualifiedName("net/http", "Request", "Write") and
|
||||
this.hasQualifiedName("net/http", "Request", "Write") and
|
||||
(inp.isReceiver() and outp.isParameter(0))
|
||||
or
|
||||
// signature: func (*Request) WriteProxy(w io.Writer) error
|
||||
hasQualifiedName("net/http", "Request", "WriteProxy") and
|
||||
this.hasQualifiedName("net/http", "Request", "WriteProxy") and
|
||||
(inp.isReceiver() and outp.isParameter(0))
|
||||
or
|
||||
// signature: func (*Response) Write(w io.Writer) error
|
||||
hasQualifiedName("net/http", "Response", "Write") and
|
||||
this.hasQualifiedName("net/http", "Response", "Write") and
|
||||
(inp.isReceiver() and outp.isParameter(0))
|
||||
or
|
||||
// signature: func (*Transport) Clone() *Transport
|
||||
hasQualifiedName("net/http", "Transport", "Clone") and
|
||||
this.hasQualifiedName("net/http", "Transport", "Clone") and
|
||||
(inp.isReceiver() and outp.isResult())
|
||||
or
|
||||
// signature: func (Hijacker) Hijack() (net.Conn, *bufio.ReadWriter, error)
|
||||
implements("net/http", "Hijacker", "Hijack") and
|
||||
this.implements("net/http", "Hijacker", "Hijack") and
|
||||
(inp.isReceiver() and outp.isResult([0, 1]))
|
||||
or
|
||||
// signature: func (ResponseWriter) Write([]byte) (int, error)
|
||||
implements("net/http", "ResponseWriter", "Write") and
|
||||
this.implements("net/http", "ResponseWriter", "Write") and
|
||||
(inp.isParameter(0) and outp.isReceiver())
|
||||
}
|
||||
|
||||
|
||||
@@ -32,7 +32,9 @@ module Regexp {
|
||||
}
|
||||
|
||||
private class MatchFunction extends RegexpMatchFunction::Range, Function {
|
||||
MatchFunction() { exists(string fn | fn.matches("Match%") | hasQualifiedName("regexp", fn)) }
|
||||
MatchFunction() {
|
||||
exists(string fn | fn.matches("Match%") | this.hasQualifiedName("regexp", fn))
|
||||
}
|
||||
|
||||
override FunctionInput getRegexpArg() { result.isParameter(0) }
|
||||
|
||||
@@ -43,7 +45,7 @@ module Regexp {
|
||||
|
||||
private class MatchMethod extends RegexpMatchFunction::Range, Method {
|
||||
MatchMethod() {
|
||||
exists(string fn | fn.matches("Match%") | hasQualifiedName("regexp", "Regexp", fn))
|
||||
exists(string fn | fn.matches("Match%") | this.hasQualifiedName("regexp", "Regexp", fn))
|
||||
}
|
||||
|
||||
override FunctionInput getRegexpArg() { result.isReceiver() }
|
||||
@@ -55,7 +57,7 @@ module Regexp {
|
||||
|
||||
private class ReplaceFunction extends RegexpReplaceFunction::Range, Method {
|
||||
ReplaceFunction() {
|
||||
exists(string fn | fn.matches("ReplaceAll%") | hasQualifiedName("regexp", "Regexp", fn))
|
||||
exists(string fn | fn.matches("ReplaceAll%") | this.hasQualifiedName("regexp", "Regexp", fn))
|
||||
}
|
||||
|
||||
override FunctionInput getRegexpArg() { result.isReceiver() }
|
||||
@@ -71,7 +73,7 @@ module Regexp {
|
||||
|
||||
FunctionModels() {
|
||||
// signature: func QuoteMeta(s string) string
|
||||
hasQualifiedName("regexp", "QuoteMeta") and
|
||||
this.hasQualifiedName("regexp", "QuoteMeta") and
|
||||
(inp.isParameter(0) and outp.isResult())
|
||||
}
|
||||
|
||||
@@ -86,77 +88,77 @@ module Regexp {
|
||||
|
||||
MethodModels() {
|
||||
// signature: func (*Regexp) Expand(dst []byte, template []byte, src []byte, match []int) []byte
|
||||
hasQualifiedName("regexp", "Regexp", "Expand") and
|
||||
this.hasQualifiedName("regexp", "Regexp", "Expand") and
|
||||
(
|
||||
inp.isParameter([1, 2]) and
|
||||
(outp.isParameter(0) or outp.isResult())
|
||||
)
|
||||
or
|
||||
// signature: func (*Regexp) ExpandString(dst []byte, template string, src string, match []int) []byte
|
||||
hasQualifiedName("regexp", "Regexp", "ExpandString") and
|
||||
this.hasQualifiedName("regexp", "Regexp", "ExpandString") and
|
||||
(
|
||||
inp.isParameter([1, 2]) and
|
||||
(outp.isParameter(0) or outp.isResult())
|
||||
)
|
||||
or
|
||||
// signature: func (*Regexp) Find(b []byte) []byte
|
||||
hasQualifiedName("regexp", "Regexp", "Find") and
|
||||
this.hasQualifiedName("regexp", "Regexp", "Find") and
|
||||
(inp.isParameter(0) and outp.isResult())
|
||||
or
|
||||
// signature: func (*Regexp) FindAll(b []byte, n int) [][]byte
|
||||
hasQualifiedName("regexp", "Regexp", "FindAll") and
|
||||
this.hasQualifiedName("regexp", "Regexp", "FindAll") and
|
||||
(inp.isParameter(0) and outp.isResult())
|
||||
or
|
||||
// signature: func (*Regexp) FindAllString(s string, n int) []string
|
||||
hasQualifiedName("regexp", "Regexp", "FindAllString") and
|
||||
this.hasQualifiedName("regexp", "Regexp", "FindAllString") and
|
||||
(inp.isParameter(0) and outp.isResult())
|
||||
or
|
||||
// signature: func (*Regexp) FindAllStringSubmatch(s string, n int) [][]string
|
||||
hasQualifiedName("regexp", "Regexp", "FindAllStringSubmatch") and
|
||||
this.hasQualifiedName("regexp", "Regexp", "FindAllStringSubmatch") and
|
||||
(inp.isParameter(0) and outp.isResult())
|
||||
or
|
||||
// signature: func (*Regexp) FindAllSubmatch(b []byte, n int) [][][]byte
|
||||
hasQualifiedName("regexp", "Regexp", "FindAllSubmatch") and
|
||||
this.hasQualifiedName("regexp", "Regexp", "FindAllSubmatch") and
|
||||
(inp.isParameter(0) and outp.isResult())
|
||||
or
|
||||
// signature: func (*Regexp) FindString(s string) string
|
||||
hasQualifiedName("regexp", "Regexp", "FindString") and
|
||||
this.hasQualifiedName("regexp", "Regexp", "FindString") and
|
||||
(inp.isParameter(0) and outp.isResult())
|
||||
or
|
||||
// signature: func (*Regexp) FindStringSubmatch(s string) []string
|
||||
hasQualifiedName("regexp", "Regexp", "FindStringSubmatch") and
|
||||
this.hasQualifiedName("regexp", "Regexp", "FindStringSubmatch") and
|
||||
(inp.isParameter(0) and outp.isResult())
|
||||
or
|
||||
// signature: func (*Regexp) FindSubmatch(b []byte) [][]byte
|
||||
hasQualifiedName("regexp", "Regexp", "FindSubmatch") and
|
||||
this.hasQualifiedName("regexp", "Regexp", "FindSubmatch") and
|
||||
(inp.isParameter(0) and outp.isResult())
|
||||
or
|
||||
// signature: func (*Regexp) ReplaceAll(src []byte, repl []byte) []byte
|
||||
hasQualifiedName("regexp", "Regexp", "ReplaceAll") and
|
||||
this.hasQualifiedName("regexp", "Regexp", "ReplaceAll") and
|
||||
(inp.isParameter(_) and outp.isResult())
|
||||
or
|
||||
// signature: func (*Regexp) ReplaceAllFunc(src []byte, repl func([]byte) []byte) []byte
|
||||
hasQualifiedName("regexp", "Regexp", "ReplaceAllFunc") and
|
||||
this.hasQualifiedName("regexp", "Regexp", "ReplaceAllFunc") and
|
||||
(inp.isParameter(_) and outp.isResult())
|
||||
or
|
||||
// signature: func (*Regexp) ReplaceAllLiteral(src []byte, repl []byte) []byte
|
||||
hasQualifiedName("regexp", "Regexp", "ReplaceAllLiteral") and
|
||||
this.hasQualifiedName("regexp", "Regexp", "ReplaceAllLiteral") and
|
||||
(inp.isParameter(_) and outp.isResult())
|
||||
or
|
||||
// signature: func (*Regexp) ReplaceAllLiteralString(src string, repl string) string
|
||||
hasQualifiedName("regexp", "Regexp", "ReplaceAllLiteralString") and
|
||||
this.hasQualifiedName("regexp", "Regexp", "ReplaceAllLiteralString") and
|
||||
(inp.isParameter(_) and outp.isResult())
|
||||
or
|
||||
// signature: func (*Regexp) ReplaceAllString(src string, repl string) string
|
||||
hasQualifiedName("regexp", "Regexp", "ReplaceAllString") and
|
||||
this.hasQualifiedName("regexp", "Regexp", "ReplaceAllString") and
|
||||
(inp.isParameter(_) and outp.isResult())
|
||||
or
|
||||
// signature: func (*Regexp) ReplaceAllStringFunc(src string, repl func(string) string) string
|
||||
hasQualifiedName("regexp", "Regexp", "ReplaceAllStringFunc") and
|
||||
this.hasQualifiedName("regexp", "Regexp", "ReplaceAllStringFunc") and
|
||||
(inp.isParameter(_) and outp.isResult())
|
||||
or
|
||||
// signature: func (*Regexp) Split(s string, n int) []string
|
||||
hasQualifiedName("regexp", "Regexp", "Split") and
|
||||
this.hasQualifiedName("regexp", "Regexp", "Split") and
|
||||
(inp.isParameter(0) and outp.isResult())
|
||||
}
|
||||
|
||||
|
||||
@@ -41,39 +41,39 @@ module Strconv {
|
||||
|
||||
FunctionModels() {
|
||||
// signature: func AppendQuote(dst []byte, s string) []byte
|
||||
hasQualifiedName("strconv", "AppendQuote") and
|
||||
this.hasQualifiedName("strconv", "AppendQuote") and
|
||||
(inp.isParameter(_) and outp.isResult())
|
||||
or
|
||||
// signature: func AppendQuoteToASCII(dst []byte, s string) []byte
|
||||
hasQualifiedName("strconv", "AppendQuoteToASCII") and
|
||||
this.hasQualifiedName("strconv", "AppendQuoteToASCII") and
|
||||
(inp.isParameter(_) and outp.isResult())
|
||||
or
|
||||
// signature: func AppendQuoteToGraphic(dst []byte, s string) []byte
|
||||
hasQualifiedName("strconv", "AppendQuoteToGraphic") and
|
||||
this.hasQualifiedName("strconv", "AppendQuoteToGraphic") and
|
||||
(inp.isParameter(_) and outp.isResult())
|
||||
or
|
||||
// signature: func Quote(s string) string
|
||||
hasQualifiedName("strconv", "Quote") and
|
||||
this.hasQualifiedName("strconv", "Quote") and
|
||||
(inp.isParameter(0) and outp.isResult())
|
||||
or
|
||||
// signature: func QuotedPrefix(s string) (string, error)
|
||||
hasQualifiedName("strconv", "QuotedPrefix") and
|
||||
this.hasQualifiedName("strconv", "QuotedPrefix") and
|
||||
(inp.isParameter(0) and outp.isResult(0))
|
||||
or
|
||||
// signature: func QuoteToASCII(s string) string
|
||||
hasQualifiedName("strconv", "QuoteToASCII") and
|
||||
this.hasQualifiedName("strconv", "QuoteToASCII") and
|
||||
(inp.isParameter(0) and outp.isResult())
|
||||
or
|
||||
// signature: func QuoteToGraphic(s string) string
|
||||
hasQualifiedName("strconv", "QuoteToGraphic") and
|
||||
this.hasQualifiedName("strconv", "QuoteToGraphic") and
|
||||
(inp.isParameter(0) and outp.isResult())
|
||||
or
|
||||
// signature: func Unquote(s string) (string, error)
|
||||
hasQualifiedName("strconv", "Unquote") and
|
||||
this.hasQualifiedName("strconv", "Unquote") and
|
||||
(inp.isParameter(0) and outp.isResult(0))
|
||||
or
|
||||
// signature: func UnquoteChar(s string, quote byte) (value rune, multibyte bool, tail string, err error)
|
||||
hasQualifiedName("strconv", "UnquoteChar") and
|
||||
this.hasQualifiedName("strconv", "UnquoteChar") and
|
||||
(inp.isParameter(0) and outp.isResult(2))
|
||||
}
|
||||
|
||||
|
||||
@@ -29,7 +29,7 @@ module TextTemplate {
|
||||
int dataArg;
|
||||
|
||||
TextTemplateInstantiation() {
|
||||
exists(string m | getTarget().hasQualifiedName("text/template", "Template", m) |
|
||||
exists(string m | this.getTarget().hasQualifiedName("text/template", "Template", m) |
|
||||
m = "Execute" and
|
||||
dataArg = 1
|
||||
or
|
||||
@@ -49,31 +49,31 @@ module TextTemplate {
|
||||
|
||||
FunctionModels() {
|
||||
// signature: func HTMLEscape(w io.Writer, b []byte)
|
||||
hasQualifiedName("text/template", "HTMLEscape") and
|
||||
this.hasQualifiedName("text/template", "HTMLEscape") and
|
||||
(inp.isParameter(1) and outp.isParameter(0))
|
||||
or
|
||||
// signature: func HTMLEscapeString(s string) string
|
||||
hasQualifiedName("text/template", "HTMLEscapeString") and
|
||||
this.hasQualifiedName("text/template", "HTMLEscapeString") and
|
||||
(inp.isParameter(0) and outp.isResult())
|
||||
or
|
||||
// signature: func HTMLEscaper(args ...interface{}) string
|
||||
hasQualifiedName("text/template", "HTMLEscaper") and
|
||||
this.hasQualifiedName("text/template", "HTMLEscaper") and
|
||||
(inp.isParameter(_) and outp.isResult())
|
||||
or
|
||||
// signature: func JSEscape(w io.Writer, b []byte)
|
||||
hasQualifiedName("text/template", "JSEscape") and
|
||||
this.hasQualifiedName("text/template", "JSEscape") and
|
||||
(inp.isParameter(1) and outp.isParameter(0))
|
||||
or
|
||||
// signature: func JSEscapeString(s string) string
|
||||
hasQualifiedName("text/template", "JSEscapeString") and
|
||||
this.hasQualifiedName("text/template", "JSEscapeString") and
|
||||
(inp.isParameter(0) and outp.isResult())
|
||||
or
|
||||
// signature: func JSEscaper(args ...interface{}) string
|
||||
hasQualifiedName("text/template", "JSEscaper") and
|
||||
this.hasQualifiedName("text/template", "JSEscaper") and
|
||||
(inp.isParameter(_) and outp.isResult())
|
||||
or
|
||||
// signature: func URLQueryEscaper(args ...interface{}) string
|
||||
hasQualifiedName("text/template", "URLQueryEscaper") and
|
||||
this.hasQualifiedName("text/template", "URLQueryEscaper") and
|
||||
(inp.isParameter(_) and outp.isResult())
|
||||
}
|
||||
|
||||
@@ -88,11 +88,11 @@ module TextTemplate {
|
||||
|
||||
MethodModels() {
|
||||
// signature: func (*Template) Execute(wr io.Writer, data interface{}) error
|
||||
hasQualifiedName("text/template", "Template", "Execute") and
|
||||
this.hasQualifiedName("text/template", "Template", "Execute") and
|
||||
(inp.isParameter(1) and outp.isParameter(0))
|
||||
or
|
||||
// signature: func (*Template) ExecuteTemplate(wr io.Writer, name string, data interface{}) error
|
||||
hasQualifiedName("text/template", "Template", "ExecuteTemplate") and
|
||||
this.hasQualifiedName("text/template", "Template", "ExecuteTemplate") and
|
||||
(inp.isParameter(2) and outp.isParameter(0))
|
||||
}
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ module CleartextLogging {
|
||||
abstract class Source extends DataFlow::Node {
|
||||
Source() {
|
||||
// hard-coded strings are uninteresting
|
||||
not exists(getStringValue())
|
||||
not exists(this.getStringValue())
|
||||
}
|
||||
|
||||
/** Gets a string that describes the type of this data-flow source. */
|
||||
@@ -164,7 +164,7 @@ module CleartextLogging {
|
||||
string name;
|
||||
|
||||
CallPasswordSource() {
|
||||
name = getCalleeName() and
|
||||
name = this.getCalleeName() and
|
||||
name.regexpMatch("(?is)getPassword")
|
||||
}
|
||||
|
||||
|
||||
@@ -194,7 +194,7 @@ class ExternalAPIUsedWithUntrustedData extends TExternalAPI {
|
||||
|
||||
/** Gets the number of untrusted sources used with this external API. */
|
||||
int getNumberOfUntrustedSources() {
|
||||
result = count(getUntrustedDataNode().getAnUntrustedSource())
|
||||
result = count(this.getUntrustedDataNode().getAnUntrustedSource())
|
||||
}
|
||||
|
||||
/** Gets a textual representation of this element. */
|
||||
|
||||
@@ -1,20 +1,4 @@
|
||||
/**
|
||||
* @name Incorrect conversion between integer types
|
||||
* @description Converting the result of `strconv.Atoi`, `strconv.ParseInt`,
|
||||
* and `strconv.ParseUint` to integer types of smaller bit size
|
||||
* can produce unexpected values.
|
||||
* @kind path-problem
|
||||
* @problem.severity warning
|
||||
* @security-severity 8.1
|
||||
* @id go/incorrect-integer-conversion
|
||||
* @tags security
|
||||
* external/cwe/cwe-190
|
||||
* external/cwe/cwe-681
|
||||
* @precision very-high
|
||||
*/
|
||||
|
||||
import go
|
||||
import DataFlow::PathGraph
|
||||
|
||||
/**
|
||||
* Gets the maximum value of an integer (signed if `isSigned`
|
||||
@@ -146,7 +130,7 @@ class ConversionWithoutBoundsCheckConfig extends TaintTracking::Configuration {
|
||||
// To catch flows that only happen on 32-bit architectures we
|
||||
// consider an architecture-dependent sink bit size to be 32.
|
||||
exists(int bitSize | if sinkBitSize != 0 then bitSize = sinkBitSize else bitSize = 32 |
|
||||
guard.(UpperBoundCheckGuard).getBound() <= getMaxIntValue(bitSize, sourceIsSigned)
|
||||
guard.(UpperBoundCheckGuard).isBoundFor(bitSize, sourceIsSigned)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -159,23 +143,45 @@ class ConversionWithoutBoundsCheckConfig extends TaintTracking::Configuration {
|
||||
|
||||
/** An upper bound check that compares a variable to a constant value. */
|
||||
class UpperBoundCheckGuard extends DataFlow::BarrierGuard, DataFlow::RelationalComparisonNode {
|
||||
UpperBoundCheckGuard() { count(expr.getAnOperand().getIntValue()) = 1 }
|
||||
UpperBoundCheckGuard() {
|
||||
count(expr.getAnOperand().getExactValue()) = 1 and
|
||||
expr.getAnOperand().getType().getUnderlyingType() instanceof IntegerType
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the constant value which this upper bound check ensures the
|
||||
* other value is less than or equal to.
|
||||
*/
|
||||
float getBound() {
|
||||
exists(int strictnessOffset |
|
||||
if expr.isStrict() then strictnessOffset = 1 else strictnessOffset = 0
|
||||
predicate isBoundFor(int bitSize, boolean isSigned) {
|
||||
bitSize = [8, 16, 32] and
|
||||
exists(float bound, float strictnessOffset |
|
||||
// For `x < c` the bound is `c-1`. For `x >= c` we will be an upper bound
|
||||
// on the `branch` argument of `checks` is false, which is equivalent to
|
||||
// `x < c`.
|
||||
if expr instanceof LssExpr or expr instanceof GeqExpr
|
||||
then strictnessOffset = 1
|
||||
else strictnessOffset = 0
|
||||
|
|
||||
result = expr.getAnOperand().getExactValue().toFloat() - strictnessOffset
|
||||
(
|
||||
bound = expr.getAnOperand().getExactValue().toFloat()
|
||||
or
|
||||
exists(DeclaredConstant maxint | maxint.hasQualifiedName("math", "MaxInt") |
|
||||
expr.getAnOperand() = maxint.getAReference() and
|
||||
bound = getMaxIntValue(32, true)
|
||||
)
|
||||
or
|
||||
exists(DeclaredConstant maxuint | maxuint.hasQualifiedName("math", "MaxUint") |
|
||||
expr.getAnOperand() = maxuint.getAReference() and
|
||||
bound = getMaxIntValue(32, false)
|
||||
)
|
||||
) and
|
||||
bound - strictnessOffset <= getMaxIntValue(bitSize, isSigned)
|
||||
)
|
||||
}
|
||||
|
||||
override predicate checks(Expr e, boolean branch) {
|
||||
this.leq(branch, DataFlow::exprNode(e), _, _) and
|
||||
not exists(e.getIntValue())
|
||||
not e.isConst()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -192,13 +198,3 @@ string describeBitSize(int bitSize, int intTypeBitSize) {
|
||||
"a number with architecture-dependent bit-width, which is constrained to be " +
|
||||
intTypeBitSize + "-bit by build constraints,"
|
||||
}
|
||||
|
||||
from
|
||||
DataFlow::PathNode source, DataFlow::PathNode sink, ConversionWithoutBoundsCheckConfig cfg,
|
||||
DataFlow::CallNode call
|
||||
where cfg.hasFlowPath(source, sink) and call.getResult(0) = source.getNode()
|
||||
select sink.getNode(), source, sink,
|
||||
"Incorrect conversion of " +
|
||||
describeBitSize(cfg.getSourceBitSize(), getIntTypeBitSize(source.getNode().getFile())) +
|
||||
" from $@ to a lower bit size type " + sink.getNode().getType().getUnderlyingType().getName() +
|
||||
" without an upper bound check.", source, call.getTarget().getQualifiedName()
|
||||
@@ -116,7 +116,7 @@ class SensitiveCall extends SensitiveExpr, CallExpr {
|
||||
)
|
||||
}
|
||||
|
||||
override string describe() { result = "a call to " + getCalleeName() }
|
||||
override string describe() { result = "a call to " + this.getCalleeName() }
|
||||
|
||||
override SensitiveExpr::Classification getClassification() { result = classification }
|
||||
}
|
||||
|
||||
@@ -67,7 +67,7 @@ module TaintedPath {
|
||||
}
|
||||
|
||||
override predicate checks(Expr e, boolean branch) {
|
||||
e = getArgument(0).asExpr() and
|
||||
e = this.getArgument(0).asExpr() and
|
||||
branch = false
|
||||
}
|
||||
}
|
||||
@@ -125,7 +125,7 @@ module TaintedPath {
|
||||
}
|
||||
|
||||
override predicate checks(Expr e, boolean branch) {
|
||||
e = getArgument(0).asExpr() and branch = true
|
||||
e = this.getArgument(0).asExpr() and branch = true
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -27,6 +27,28 @@ class RsaKeyTrackingConfiguration extends DataFlow::Configuration {
|
||||
c.getTarget().hasQualifiedName("crypto/rsa", "GenerateKey")
|
||||
)
|
||||
}
|
||||
|
||||
override predicate isBarrierGuard(DataFlow::BarrierGuard guard) {
|
||||
guard instanceof ComparisonBarrierGuard
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A comparison which guarantees that an expression is at least 2048,
|
||||
* considered as a barrier guard for key sizes.
|
||||
*/
|
||||
class ComparisonBarrierGuard extends DataFlow::BarrierGuard instanceof DataFlow::RelationalComparisonNode {
|
||||
override predicate checks(Expr e, boolean branch) {
|
||||
exists(DataFlow::Node lesser, DataFlow::Node greater, int bias |
|
||||
super.leq(branch, lesser, greater, bias)
|
||||
|
|
||||
// Force join order: find comparisons checking x >= 2048, then take the global value
|
||||
// number of x. Otherwise this can be realised by starting from all pairs of matching value
|
||||
// numbers, which can be huge.
|
||||
pragma[only_bind_into](globalValueNumber(DataFlow::exprNode(e))) = globalValueNumber(greater) and
|
||||
lesser.getIntValue() - bias >= 2048
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
from RsaKeyTrackingConfiguration cfg, DataFlow::PathNode source, DataFlow::PathNode sink
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* @name Incorrect conversion between integer types
|
||||
* @description Converting the result of `strconv.Atoi`, `strconv.ParseInt`,
|
||||
* and `strconv.ParseUint` to integer types of smaller bit size
|
||||
* can produce unexpected values.
|
||||
* @kind path-problem
|
||||
* @problem.severity warning
|
||||
* @security-severity 8.1
|
||||
* @id go/incorrect-integer-conversion
|
||||
* @tags security
|
||||
* external/cwe/cwe-190
|
||||
* external/cwe/cwe-681
|
||||
* @precision very-high
|
||||
*/
|
||||
|
||||
import go
|
||||
import DataFlow::PathGraph
|
||||
import semmle.go.security.IncorrectIntegerConversionLib
|
||||
|
||||
from
|
||||
DataFlow::PathNode source, DataFlow::PathNode sink, ConversionWithoutBoundsCheckConfig cfg,
|
||||
DataFlow::CallNode call
|
||||
where cfg.hasFlowPath(source, sink) and call.getResult(0) = source.getNode()
|
||||
select sink.getNode(), source, sink,
|
||||
"Incorrect conversion of " +
|
||||
describeBitSize(cfg.getSourceBitSize(), getIntTypeBitSize(source.getNode().getFile())) +
|
||||
" from $@ to a lower bit size type " + sink.getNode().getType().getUnderlyingType().getName() +
|
||||
" without an upper bound check.", source, call.getTarget().getQualifiedName()
|
||||
@@ -0,0 +1,19 @@
|
||||
/**
|
||||
* @name LDAP query built from user-controlled sources
|
||||
* @description Building an LDAP query from user-controlled sources is vulnerable to insertion of
|
||||
* malicious LDAP code by the user.
|
||||
* @kind path-problem
|
||||
* @problem.severity error
|
||||
* @id go/ldap-injection
|
||||
* @tags security
|
||||
* external/cwe/cwe-90
|
||||
*/
|
||||
|
||||
import go
|
||||
import LDAPInjection
|
||||
import DataFlow::PathGraph
|
||||
|
||||
from LdapInjectionConfiguration config, DataFlow::PathNode source, DataFlow::PathNode sink
|
||||
where config.hasFlowPath(source, sink)
|
||||
select sink.getNode(), source, sink, "LDAP query parameter is derived from $@.", source.getNode(),
|
||||
"a user-provided value"
|
||||
@@ -0,0 +1,111 @@
|
||||
import go
|
||||
import DataFlow::PathGraph
|
||||
|
||||
/**
|
||||
* A sanitizer function that prevents LDAP injection attacks.
|
||||
*/
|
||||
abstract class LdapSanitizer extends DataFlow::Node { }
|
||||
|
||||
/**
|
||||
* A common sanitizer function. These are name-based heuristics only.
|
||||
*/
|
||||
private class CommonLdapEscape extends LdapSanitizer {
|
||||
CommonLdapEscape() {
|
||||
exists(DataFlow::MethodCallNode m |
|
||||
m.getTarget().getName() in [
|
||||
"sanitizedUserQuery", "sanitizedUserDN", "sanitizedGroupFilter", "sanitizedGroupDN"
|
||||
]
|
||||
|
|
||||
this = m.getResult(0)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An `EscapeFilter` function from the `go-ldap` or `ldap` packages.
|
||||
*/
|
||||
private class EscapeFilterCall extends LdapSanitizer {
|
||||
EscapeFilterCall() {
|
||||
exists(Function f |
|
||||
f.hasQualifiedName([
|
||||
"github.com/go-ldap/ldap", "github.com/go-ldap/ldap/v3", "gopkg.in/ldap.v2",
|
||||
"gopkg.in/ldap.v3"
|
||||
], "EscapeFilter")
|
||||
|
|
||||
this = f.getACall()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A sink that is vulnerable to LDAP injection vulnerabilities.
|
||||
*/
|
||||
abstract class LdapSink extends DataFlow::Node { }
|
||||
|
||||
/**
|
||||
* A vulnerable argument to `go-ldap` or `ldap`'s `NewSearchRequest` function.
|
||||
*/
|
||||
private class GoLdapSink extends LdapSink {
|
||||
GoLdapSink() {
|
||||
exists(Function f |
|
||||
f.hasQualifiedName([
|
||||
"github.com/go-ldap/ldap", "github.com/go-ldap/ldap/v3", "gopkg.in/ldap.v2",
|
||||
"gopkg.in/ldap.v3"
|
||||
], "NewSearchRequest")
|
||||
|
|
||||
this = f.getACall().getArgument([0, 6, 7])
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A value written to the `ldap` package's `SearchRequest.BaseDN` field.
|
||||
*/
|
||||
private class LdapV2DNSink extends LdapSink {
|
||||
LdapV2DNSink() {
|
||||
exists(Field f, Write w |
|
||||
f.hasQualifiedName(["gopkg.in/ldap.v2", "gopkg.in/ldap.v3"], "SearchRequest", "BaseDN") and
|
||||
w.writesField(_, f, this)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An argument to `go-ldap-client`'s `LDAPClient.Authenticate` or `.GetGroupsOfUser` function.
|
||||
*/
|
||||
private class LdapClientSink extends LdapSink {
|
||||
LdapClientSink() {
|
||||
exists(Method m |
|
||||
m.hasQualifiedName("github.com/jtblin/go-ldap-client", "LDAPClient",
|
||||
["Authenticate", "GetGroupsOfUser"])
|
||||
|
|
||||
this = m.getACall().getArgument(0)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A value written to `go-ldap-client`'s `LDAPClient.Base` field.
|
||||
*/
|
||||
private class LdapClientDNSink extends LdapSink {
|
||||
LdapClientDNSink() {
|
||||
exists(Field f, Write w |
|
||||
f.hasQualifiedName("github.com/jtblin/go-ldap-client", "LDAPClient", "Base") and
|
||||
w.writesField(_, f, this)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A taint-tracking configuration for reasoning about when an `UntrustedFlowSource`
|
||||
* flows into an argument or field that is vulnerable to LDAP injection.
|
||||
*/
|
||||
class LdapInjectionConfiguration extends TaintTracking::Configuration {
|
||||
LdapInjectionConfiguration() { this = "Ldap injection" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) { source instanceof UntrustedFlowSource }
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) { sink instanceof LdapSink }
|
||||
|
||||
override predicate isSanitizer(DataFlow::Node sanitizer) { sanitizer instanceof LdapSanitizer }
|
||||
}
|
||||
@@ -113,7 +113,7 @@ private newtype TCryptographicAlgorithm =
|
||||
*/
|
||||
abstract class CryptographicAlgorithm extends TCryptographicAlgorithm {
|
||||
/** Gets a textual representation of this element. */
|
||||
string toString() { result = getName() }
|
||||
string toString() { result = this.getName() }
|
||||
|
||||
/**
|
||||
* Gets the name of this algorithm.
|
||||
@@ -126,7 +126,7 @@ abstract class CryptographicAlgorithm extends TCryptographicAlgorithm {
|
||||
*/
|
||||
bindingset[name]
|
||||
predicate matchesName(string name) {
|
||||
exists(name.regexpReplaceAll("[-_]", "").regexpFind("(?i)\\Q" + getName() + "\\E", _, _))
|
||||
exists(name.regexpReplaceAll("[-_]", "").regexpFind("(?i)\\Q" + this.getName() + "\\E", _, _))
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
22
repo-tests/codeql-go/ql/src/experimental/CWE-918/SSRF.ql
Normal file
22
repo-tests/codeql-go/ql/src/experimental/CWE-918/SSRF.ql
Normal file
@@ -0,0 +1,22 @@
|
||||
/**
|
||||
* @name Uncontrolled data used in network request
|
||||
* @description Sending network requests with user-controlled data allows for request forgery attacks.
|
||||
* @id go/ssrf
|
||||
* @kind path-problem
|
||||
* @problem.severity error
|
||||
* @precision high
|
||||
* @tags security
|
||||
* external/cwe/cwe-918
|
||||
*/
|
||||
|
||||
import go
|
||||
import SSRF
|
||||
import DataFlow::PathGraph
|
||||
|
||||
from
|
||||
ServerSideRequestForgery::Configuration cfg, DataFlow::PathNode source, DataFlow::PathNode sink,
|
||||
DataFlow::Node request
|
||||
where
|
||||
cfg.hasFlowPath(source, sink) and
|
||||
request = sink.getNode().(ServerSideRequestForgery::Sink).getARequest()
|
||||
select request, source, sink, "The URL of this request depends on a user-provided value"
|
||||
164
repo-tests/codeql-go/ql/src/experimental/CWE-918/SSRF.qll
Normal file
164
repo-tests/codeql-go/ql/src/experimental/CWE-918/SSRF.qll
Normal file
@@ -0,0 +1,164 @@
|
||||
/**
|
||||
* Provides a taint-tracking configuration for reasoning about request forgery
|
||||
* (SSRF) vulnerabilities.
|
||||
*/
|
||||
|
||||
import go
|
||||
|
||||
/**
|
||||
* Provides a taint-tracking configuration for reasoning about request forgery
|
||||
* (SSRF) vulnerabilities.
|
||||
*/
|
||||
module ServerSideRequestForgery {
|
||||
private import semmle.go.frameworks.Gin
|
||||
private import validator
|
||||
private import semmle.go.security.UrlConcatenation
|
||||
private import semmle.go.dataflow.barrierguardutil.RegexpCheck
|
||||
private import semmle.go.dataflow.Properties
|
||||
|
||||
/**
|
||||
* A taint-tracking configuration for reasoning about request forgery.
|
||||
*/
|
||||
class Configuration extends TaintTracking::Configuration {
|
||||
Configuration() { this = "SSRF" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) { source instanceof Source }
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) { sink instanceof Sink }
|
||||
|
||||
override predicate isAdditionalTaintStep(DataFlow::Node pred, DataFlow::Node succ) {
|
||||
// propagate to a URL when its host is assigned to
|
||||
exists(Write w, Field f, SsaWithFields v | f.hasQualifiedName("net/url", "URL", "Host") |
|
||||
w.writesField(v.getAUse(), f, pred) and succ = v.getAUse()
|
||||
)
|
||||
}
|
||||
|
||||
override predicate isSanitizer(DataFlow::Node node) {
|
||||
super.isSanitizer(node) or
|
||||
node instanceof Sanitizer
|
||||
}
|
||||
|
||||
override predicate isSanitizerOut(DataFlow::Node node) {
|
||||
super.isSanitizerOut(node) or
|
||||
node instanceof SanitizerEdge
|
||||
}
|
||||
|
||||
override predicate isSanitizerGuard(DataFlow::BarrierGuard guard) {
|
||||
super.isSanitizerGuard(guard) or guard instanceof SanitizerGuard
|
||||
}
|
||||
}
|
||||
|
||||
/** A data flow source for request forgery vulnerabilities. */
|
||||
abstract class Source extends DataFlow::Node { }
|
||||
|
||||
/** A data flow sink for request forgery vulnerabilities. */
|
||||
abstract class Sink extends DataFlow::Node {
|
||||
/** Gets a request that uses this sink. */
|
||||
abstract DataFlow::Node getARequest();
|
||||
|
||||
/**
|
||||
* Gets the name of a part of the request that may be tainted by this sink,
|
||||
* such as the URL or the host.
|
||||
*/
|
||||
abstract string getKind();
|
||||
}
|
||||
|
||||
/** A sanitizer for request forgery vulnerabilities. */
|
||||
abstract class Sanitizer extends DataFlow::Node { }
|
||||
|
||||
/** An outgoing sanitizer edge for request forgery vulnerabilities. */
|
||||
abstract class SanitizerEdge extends DataFlow::Node { }
|
||||
|
||||
/**
|
||||
* A sanitizer guard for request forgery vulnerabilities.
|
||||
*/
|
||||
abstract class SanitizerGuard extends DataFlow::BarrierGuard { }
|
||||
|
||||
/**
|
||||
* An user controlled input, considered as a flow source for request forgery.
|
||||
*/
|
||||
class UntrustedFlowAsSource extends Source instanceof UntrustedFlowSource { }
|
||||
|
||||
/**
|
||||
* The URL of an HTTP request, viewed as a sink for request forgery.
|
||||
*/
|
||||
private class ClientRequestUrlAsSink extends Sink {
|
||||
HTTP::ClientRequest request;
|
||||
|
||||
ClientRequestUrlAsSink() { this = request.getUrl() }
|
||||
|
||||
override DataFlow::Node getARequest() { result = request }
|
||||
|
||||
override string getKind() { result = "URL" }
|
||||
}
|
||||
|
||||
/**
|
||||
* The URL of a WebSocket request, viewed as a sink for request forgery.
|
||||
*/
|
||||
class WebSocketCallAsSink extends Sink {
|
||||
WebSocketRequestCall request;
|
||||
|
||||
WebSocketCallAsSink() { this = request.getRequestUrl() }
|
||||
|
||||
override DataFlow::Node getARequest() { result = request }
|
||||
|
||||
override string getKind() { result = "WebSocket URL" }
|
||||
}
|
||||
|
||||
/**
|
||||
* Result value of prepending a string that prevents any value from controlling the
|
||||
* host of a URL.
|
||||
*/
|
||||
private class PathSanitizer extends SanitizerEdge {
|
||||
PathSanitizer() { sanitizingPrefixEdge(this, _) }
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to a regexp match function, considered as a barrier guard for sanitizing untrusted URLs.
|
||||
*
|
||||
* This is overapproximate: we do not attempt to reason about the correctness of the regexp.
|
||||
*/
|
||||
class RegexpCheckAsBarrierGuard extends RegexpCheck, SanitizerGuard { }
|
||||
|
||||
/**
|
||||
* An equality check comparing a data-flow node against a constant string, considered as
|
||||
* a barrier guard for sanitizing untrusted URLs.
|
||||
*/
|
||||
class EqualityAsSanitizerGuard extends SanitizerGuard, DataFlow::EqualityTestNode {
|
||||
DataFlow::Node url;
|
||||
|
||||
EqualityAsSanitizerGuard() {
|
||||
exists(this.getAnOperand().getStringValue()) and
|
||||
url = this.getAnOperand()
|
||||
}
|
||||
|
||||
override predicate checks(Expr e, boolean outcome) {
|
||||
e = url.asExpr() and outcome = this.getPolarity()
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If the tainted variable is a boolean or has numeric type is not possible to exploit a SSRF
|
||||
*/
|
||||
class NumSanitizer extends Sanitizer {
|
||||
NumSanitizer() {
|
||||
this.getType() instanceof NumericType or
|
||||
this.getType() instanceof BoolType
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* When we receive a body from a request, we can use certain tags on our struct's fields to hint
|
||||
* the binding function to run some validations for that field. If these binding functions returns
|
||||
* no error, then we consider these fields safe for SSRF.
|
||||
*/
|
||||
class BodySanitizer extends Sanitizer instanceof CheckedAlphanumericStructFieldRead { }
|
||||
|
||||
/**
|
||||
* The method Var of package validator is a sanitizer guard only if the check
|
||||
* of the error binding exists, and the tag to check is one of "alpha", "alphanum", "alphaunicode", "alphanumunicode", "number", "numeric".
|
||||
*/
|
||||
class ValidatorAsSanitizer extends SanitizerGuard instanceof ValidatorVarCheck {
|
||||
override predicate checks(Expr e, boolean branch) { this.checks(e, branch) }
|
||||
}
|
||||
}
|
||||
159
repo-tests/codeql-go/ql/src/experimental/CWE-918/validator.qll
Normal file
159
repo-tests/codeql-go/ql/src/experimental/CWE-918/validator.qll
Normal file
@@ -0,0 +1,159 @@
|
||||
import go
|
||||
private import semmle.go.dataflow.Properties
|
||||
|
||||
/**
|
||||
* Holds if `validationKind` is a validation kind that restricts to alphanumeric characters,
|
||||
* which we consider safe for use in a URL.
|
||||
*/
|
||||
private predicate isAlphanumericValidationKind(string validationKind) {
|
||||
validationKind in [
|
||||
"alpha", "alphanum", "alphaunicode", "alphanumunicode", "number", "numeric", "uuid"
|
||||
]
|
||||
}
|
||||
|
||||
private string getKeyAndValuesRegex() { result = "([a-zA-Z0-9]+):\"([a-zA-Z0-9,]+)\"" }
|
||||
|
||||
/**
|
||||
* A struct field with json tags like `key:"value1,value2"`.
|
||||
*/
|
||||
class FieldWithTags extends FieldDecl {
|
||||
FieldWithTags() { this.getTag().toString().regexpMatch("`([a-zA-Z0-9]+:\"[a-zA-Z0-9,]+\" *)+`") }
|
||||
|
||||
/**
|
||||
* Holds if this field's tag maps `key` to `value`.
|
||||
* For example: the tag `json:"word" binding:"required,alpha"` yields `key: "json", value: "word"`
|
||||
* and `key: "binding" values: "required","alpha"`.
|
||||
*/
|
||||
predicate getTagByKeyValue(string key, string value) {
|
||||
exists(string tag, string key_value, string values |
|
||||
this.getTag().toString() = tag and
|
||||
// Each key_value is like key:"value1,value2"
|
||||
tag.regexpFind(getKeyAndValuesRegex(), _, _) = key_value and
|
||||
// key is the "key" from key:"value1,value2"
|
||||
key_value.regexpCapture(getKeyAndValuesRegex(), 1) = key and
|
||||
// values are the value1,value2 (without the quotation marks) from key:"value1,value2"
|
||||
key_value.regexpCapture(getKeyAndValuesRegex(), 2) = values and
|
||||
// value is value1 or value2 from key:"value1,value2"
|
||||
values.regexpFind("[a-zA-Z0-9]+", _, _) = value
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A node that reads from a field with a tag indicating it
|
||||
* must be alphanumeric (for example, having the tag `binding:"alpha"`).
|
||||
*/
|
||||
class AlphanumericStructFieldRead extends DataFlow::Node {
|
||||
string key;
|
||||
|
||||
AlphanumericStructFieldRead() {
|
||||
exists(FieldWithTags decl, Field field, string tag |
|
||||
this = field.getARead() and
|
||||
field.getDeclaration() = decl.getNameExpr(0) and
|
||||
decl.getTagByKeyValue(key, tag) and
|
||||
isAlphanumericValidationKind(tag)
|
||||
)
|
||||
}
|
||||
|
||||
string getKey() { result = key }
|
||||
}
|
||||
|
||||
/**
|
||||
* A node that is considered safe because it (a) reads a field with a tag indicating it should be
|
||||
* alphanumeric, and (b) is guarded by a call to a validation function checking that it really
|
||||
* is alphanumeric.
|
||||
*
|
||||
* See `AlphanumericStructFieldRead` and `isAlphanumericValidationKind` for supported tags.
|
||||
* See `StructValidationFunction` for supported binding functions.
|
||||
*/
|
||||
class CheckedAlphanumericStructFieldRead extends AlphanumericStructFieldRead {
|
||||
CheckedAlphanumericStructFieldRead() {
|
||||
exists(StructValidationFunction guard, SelectorExpr selector |
|
||||
guard.getAGuardedNode().asExpr() = selector.getBase() and
|
||||
selector = this.asExpr() and
|
||||
this.getKey() = guard.getValidationKindKey()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A function that validates a struct, checking that fields conform to restrictions given as a tag.
|
||||
*
|
||||
* The Gin `Context.Bind` family of functions apply checks according to a `binding:` tag, and the
|
||||
* Go-Playground Validator checks fields that have a `validate:` tag.
|
||||
*/
|
||||
private class StructValidationFunction extends DataFlow::BarrierGuard, DataFlow::EqualityTestNode {
|
||||
Expr checked;
|
||||
boolean safeOutcome;
|
||||
string validationKindKey;
|
||||
|
||||
StructValidationFunction() {
|
||||
exists(Function bindFunction, DataFlow::CallNode bindCall, DataFlow::Node resultErr |
|
||||
(
|
||||
// Gin call
|
||||
bindFunction
|
||||
.(Method)
|
||||
.hasQualifiedName("github.com/gin-gonic/gin", "Context",
|
||||
[
|
||||
"BindJSON", "MustBindWith", "BindWith", "Bind", "ShouldBind", "ShouldBindBodyWith",
|
||||
"ShouldBindJSON", "ShouldBindWith"
|
||||
]) and
|
||||
validationKindKey = "binding"
|
||||
or
|
||||
// Validator Struct
|
||||
bindFunction
|
||||
.(Method)
|
||||
.hasQualifiedName("github.com/go-playground/validator", "Validate", "Struct") and
|
||||
validationKindKey = "validate"
|
||||
) and
|
||||
bindCall = bindFunction.getACall() and
|
||||
checked = dereference(bindCall.getAnArgument()) and
|
||||
resultErr = bindCall.getResult().getASuccessor*() and
|
||||
nilProperty().checkOn(this, safeOutcome, resultErr)
|
||||
)
|
||||
}
|
||||
|
||||
override predicate checks(Expr e, boolean branch) { e = checked and branch = safeOutcome }
|
||||
|
||||
/**
|
||||
* Returns the struct tag key from which this validation function draws its validation kind.
|
||||
*
|
||||
* For example, if this returns `xyz` then this function looks for a struct tag like
|
||||
* `` mustBeNumeric string `xyz:"numeric"` ``
|
||||
*/
|
||||
string getValidationKindKey() { result = validationKindKey }
|
||||
}
|
||||
|
||||
/**
|
||||
* If `nd` is an address-of expression `&a`, returns expressions `&a` and `a`. Otherwise, returns `nd` as-is.
|
||||
*/
|
||||
private Expr dereference(DataFlow::Node nd) {
|
||||
nd.asExpr().(AddressExpr).getOperand() = result
|
||||
or
|
||||
nd.asExpr() = result
|
||||
}
|
||||
|
||||
/**
|
||||
* A validation performed by package `validator`'s method `Var` to check that an expression is
|
||||
* alphanumeric (see `isAlphanumericValidationKind` for more information) sanitizes guarded uses
|
||||
* of the same variable.
|
||||
*/
|
||||
class ValidatorVarCheck extends DataFlow::BarrierGuard, DataFlow::EqualityTestNode {
|
||||
DataFlow::CallNode callToValidator;
|
||||
boolean outcome;
|
||||
|
||||
ValidatorVarCheck() {
|
||||
exists(Method validatorMethod, DataFlow::Node resultErr |
|
||||
validatorMethod.hasQualifiedName("github.com/go-playground/validator", "Validate", "Var") and
|
||||
callToValidator = validatorMethod.getACall() and
|
||||
isAlphanumericValidationKind(callToValidator.getArgument(1).getStringValue()) and
|
||||
resultErr = callToValidator.getResult().getASuccessor*() and
|
||||
nilProperty().checkOn(this, outcome, resultErr)
|
||||
)
|
||||
}
|
||||
|
||||
override predicate checks(Expr e, boolean branch) {
|
||||
callToValidator.getArgument(0).asExpr() = e and
|
||||
branch = outcome
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user