mirror of
https://github.com/github/codeql.git
synced 2026-06-23 21:57:01 +02:00
Compare commits
6 Commits
copilot/sw
...
yoff/pytho
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
408ba6218f | ||
|
|
b7f79f2d34 | ||
|
|
9cdeb8e7ee | ||
|
|
ea0b2e9219 | ||
|
|
9c41238eee | ||
|
|
d7c0ef7e4d |
@@ -1,3 +0,0 @@
|
|||||||
import go
|
|
||||||
private import semmle.go.controlflow.ControlFlowGraphShared
|
|
||||||
import GoCfg::ControlFlow::Consistency
|
|
||||||
@@ -1,4 +0,0 @@
|
|||||||
---
|
|
||||||
category: fix
|
|
||||||
---
|
|
||||||
* The Go control flow graph implementation has been migrated to use the shared CFG library. This is an internal change with no user-visible API changes.
|
|
||||||
@@ -1,53 +0,0 @@
|
|||||||
/**
|
|
||||||
* @name Print CFG
|
|
||||||
* @description Produces a representation of a file's Control Flow Graph.
|
|
||||||
* This query is used by the VS Code extension.
|
|
||||||
* @id go/print-cfg
|
|
||||||
* @kind graph
|
|
||||||
* @tags ide-contextual-queries/print-cfg
|
|
||||||
*/
|
|
||||||
|
|
||||||
import go
|
|
||||||
import semmle.go.controlflow.ControlFlowGraph
|
|
||||||
private import semmle.go.controlflow.ControlFlowGraphShared
|
|
||||||
|
|
||||||
external string selectedSourceFile();
|
|
||||||
|
|
||||||
private predicate selectedSourceFileAlias = selectedSourceFile/0;
|
|
||||||
|
|
||||||
external int selectedSourceLine();
|
|
||||||
|
|
||||||
private predicate selectedSourceLineAlias = selectedSourceLine/0;
|
|
||||||
|
|
||||||
external int selectedSourceColumn();
|
|
||||||
|
|
||||||
private predicate selectedSourceColumnAlias = selectedSourceColumn/0;
|
|
||||||
|
|
||||||
module ViewCfgQueryInput implements GoCfg::ControlFlow::ViewCfgQueryInputSig<File> {
|
|
||||||
predicate selectedSourceFile = selectedSourceFileAlias/0;
|
|
||||||
|
|
||||||
predicate selectedSourceLine = selectedSourceLineAlias/0;
|
|
||||||
|
|
||||||
predicate selectedSourceColumn = selectedSourceColumnAlias/0;
|
|
||||||
|
|
||||||
predicate cfgScopeSpan(
|
|
||||||
CfgScope scope, File file, int startLine, int startColumn, int endLine, int endColumn
|
|
||||||
) {
|
|
||||||
file = scope.getFile() and
|
|
||||||
scope.getLocation().getStartLine() = startLine and
|
|
||||||
scope.getLocation().getStartColumn() = startColumn and
|
|
||||||
exists(Location loc |
|
|
||||||
loc.getEndLine() = endLine and
|
|
||||||
loc.getEndColumn() = endColumn and
|
|
||||||
loc = scope.(FuncDef).getBody().getLocation()
|
|
||||||
)
|
|
||||||
or
|
|
||||||
file = scope.(File) and
|
|
||||||
startLine = 1 and
|
|
||||||
startColumn = 1 and
|
|
||||||
endLine = file.getNumberOfLines() and
|
|
||||||
endColumn = 999999
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
import GoCfg::ControlFlow::ViewCfgQuery<File, ViewCfgQueryInput>
|
|
||||||
@@ -431,7 +431,7 @@ private class HeuristicLoggerFunction extends Method {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override predicate mustNotReturnNormally() { logFunctionPrefix = "Fatal" }
|
override predicate mayReturnNormally() { logFunctionPrefix != "Fatal" }
|
||||||
|
|
||||||
override predicate mustPanic() { logFunctionPrefix = "Panic" }
|
override predicate mustPanic() { logFunctionPrefix = "Panic" }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/**
|
/**
|
||||||
* Provides queries to pretty-print a Go AST as a graph.
|
* Provides queries to pretty-print a Go AST as a graph.
|
||||||
*/
|
*/
|
||||||
overlay[local?]
|
overlay[local]
|
||||||
module;
|
module;
|
||||||
|
|
||||||
import go
|
import go
|
||||||
|
|||||||
@@ -437,12 +437,11 @@ class Function extends ValueEntity, @functionobject {
|
|||||||
* This predicate is an over-approximation: it may hold for functions that can never
|
* This predicate is an over-approximation: it may hold for functions that can never
|
||||||
* return normally, but it never fails to hold for functions that can.
|
* return normally, but it never fails to hold for functions that can.
|
||||||
*
|
*
|
||||||
* Library models should not override this predicate; override `mustNotReturnNormally`
|
* Note this is declared here and not in `DeclaredFunction` so that library models can override this
|
||||||
* instead, so that the control-flow graph construction can take the model into account.
|
* by extending `Function` rather than having to remember to extend `DeclaredFunction`.
|
||||||
*/
|
*/
|
||||||
predicate mayReturnNormally() {
|
predicate mayReturnNormally() {
|
||||||
not this.mustPanic() and
|
not this.mustPanic() and
|
||||||
not this.mustNotReturnNormally() and
|
|
||||||
(ControlFlow::mayReturnNormally(this.getFuncDecl()) or not exists(this.getBody()))
|
(ControlFlow::mayReturnNormally(this.getFuncDecl()) or not exists(this.getBody()))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -462,16 +461,6 @@ class Function extends ValueEntity, @functionobject {
|
|||||||
*/
|
*/
|
||||||
predicate mustPanic() { none() }
|
predicate mustPanic() { none() }
|
||||||
|
|
||||||
/**
|
|
||||||
* Holds if calling this function never returns normally (for example because it
|
|
||||||
* always panics, exits the process, or loops forever).
|
|
||||||
*
|
|
||||||
* Unlike `mayReturnNormally`, this predicate must be defined without reference to
|
|
||||||
* the control-flow graph, so that it can be used during CFG construction to
|
|
||||||
* suppress normal-flow successors of calls to this function.
|
|
||||||
*/
|
|
||||||
predicate mustNotReturnNormally() { none() }
|
|
||||||
|
|
||||||
/** Gets the number of parameters of this function. */
|
/** Gets the number of parameters of this function. */
|
||||||
int getNumParameter() { result = this.getType().(SignatureType).getNumParameter() }
|
int getNumParameter() { result = this.getType().(SignatureType).getNumParameter() }
|
||||||
|
|
||||||
|
|||||||
@@ -761,7 +761,7 @@ class CaseClause extends @caseclause, Stmt, ScopeNode {
|
|||||||
*
|
*
|
||||||
* Note that the default clause does not have any expressions.
|
* Note that the default clause does not have any expressions.
|
||||||
*/
|
*/
|
||||||
Expr getAnExpr() { result = this.getExpr(_) }
|
Expr getAnExpr() { result = this.getAChildExpr() }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the number of expressions of this `case` clause.
|
* Gets the number of expressions of this `case` clause.
|
||||||
|
|||||||
@@ -5,27 +5,66 @@ overlay[local]
|
|||||||
module;
|
module;
|
||||||
|
|
||||||
import go
|
import go
|
||||||
private import ControlFlowGraphShared
|
private import ControlFlowGraphImpl
|
||||||
|
private import codeql.controlflow.BasicBlock as BB
|
||||||
|
private import codeql.controlflow.SuccessorType
|
||||||
|
|
||||||
/** A basic block in the control-flow graph. */
|
private module Input implements BB::InputSig<Location> {
|
||||||
class BasicBlock = GoCfg::Cfg::BasicBlock;
|
/** A delineated part of the AST with its own CFG. */
|
||||||
|
class CfgScope = ControlFlow::Root;
|
||||||
|
|
||||||
/** An entry basic block. */
|
/** The class of control flow nodes. */
|
||||||
class EntryBasicBlock = GoCfg::Cfg::EntryBasicBlock;
|
class Node = ControlFlowNode;
|
||||||
|
|
||||||
|
/** Gets the CFG scope in which this node occurs. */
|
||||||
|
CfgScope nodeGetCfgScope(Node node) { node.getRoot() = result }
|
||||||
|
|
||||||
|
/** Gets an immediate successor of this node. */
|
||||||
|
Node nodeGetASuccessor(Node node, SuccessorType t) {
|
||||||
|
result = node.getASuccessor() and
|
||||||
|
(
|
||||||
|
not result instanceof ControlFlow::ConditionGuardNode and t instanceof DirectSuccessor
|
||||||
|
or
|
||||||
|
t.(BooleanSuccessor).getValue() = result.(ControlFlow::ConditionGuardNode).getOutcome()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds if `node` represents an entry node to be used when calculating
|
||||||
|
* dominance.
|
||||||
|
*/
|
||||||
|
predicate nodeIsDominanceEntry(Node node) { node instanceof EntryNode }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds if `node` represents an exit node to be used when calculating
|
||||||
|
* post dominance.
|
||||||
|
*/
|
||||||
|
predicate nodeIsPostDominanceExit(Node node) { node instanceof ExitNode }
|
||||||
|
}
|
||||||
|
|
||||||
|
module Cfg = BB::Make<Location, Input>;
|
||||||
|
|
||||||
|
class BasicBlock = Cfg::BasicBlock;
|
||||||
|
|
||||||
|
class EntryBasicBlock = Cfg::EntryBasicBlock;
|
||||||
|
|
||||||
|
cached
|
||||||
|
private predicate reachableBB(BasicBlock bb) {
|
||||||
|
bb instanceof EntryBasicBlock
|
||||||
|
or
|
||||||
|
exists(BasicBlock predBB | predBB.getASuccessor(_) = bb | reachableBB(predBB))
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A basic block that is reachable from an entry basic block.
|
* A basic block that is reachable from an entry basic block.
|
||||||
*
|
|
||||||
* Since the shared CFG library only creates nodes for reachable code,
|
|
||||||
* all basic blocks are reachable by construction.
|
|
||||||
*/
|
*/
|
||||||
class ReachableBasicBlock extends BasicBlock {
|
class ReachableBasicBlock extends BasicBlock {
|
||||||
ReachableBasicBlock() { any() }
|
ReachableBasicBlock() { reachableBB(this) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A reachable basic block with more than one predecessor.
|
* A reachable basic block with more than one predecessor.
|
||||||
*/
|
*/
|
||||||
class ReachableJoinBlock extends ReachableBasicBlock {
|
class ReachableJoinBlock extends ReachableBasicBlock {
|
||||||
ReachableJoinBlock() { this.getFirstNode().(ControlFlow::Node).isJoin() }
|
ReachableJoinBlock() { this.getFirstNode().isJoin() }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,17 +5,13 @@ overlay[local]
|
|||||||
module;
|
module;
|
||||||
|
|
||||||
import go
|
import go
|
||||||
private import ControlFlowGraphShared
|
private import ControlFlowGraphImpl
|
||||||
|
|
||||||
/** Provides helper predicates for mapping between CFG nodes and the AST. */
|
/** Provides helper predicates for mapping btween CFG nodes and the AST. */
|
||||||
module ControlFlow {
|
module ControlFlow {
|
||||||
/** A file or function with which a CFG is associated. */
|
/** A file or function with which a CFG is associated. */
|
||||||
class Root extends AstNode {
|
class Root extends AstNode {
|
||||||
Root() {
|
Root() { exists(this.(File).getADecl()) or exists(this.(FuncDef).getBody()) }
|
||||||
exists(this.(FuncDef).getBody())
|
|
||||||
or
|
|
||||||
exists(this.(File).getADecl())
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Holds if `nd` belongs to this file or function. */
|
/** Holds if `nd` belongs to this file or function. */
|
||||||
predicate isRootOf(AstNode nd) {
|
predicate isRootOf(AstNode nd) {
|
||||||
@@ -33,16 +29,22 @@ module ControlFlow {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A node in the intra-procedural control-flow graph of a Go function.
|
* A node in the intra-procedural control-flow graph of a Go function or file.
|
||||||
*
|
*
|
||||||
* Nodes correspond to expressions and statements that compute a value or perform
|
* Nodes correspond to expressions and statements that compute a value or perform
|
||||||
* an operation (as opposed to providing syntactic structure or type information).
|
* an operation (as opposed to providing syntactic structure or type information).
|
||||||
*
|
*
|
||||||
* There are also synthetic entry and exit nodes for each Go function
|
* There are also synthetic entry and exit nodes for each Go function and file
|
||||||
* that mark the beginning and the end, respectively, of the execution of the
|
* that mark the beginning and the end, respectively, of the execution of the
|
||||||
* function.
|
* function and the loading of the file.
|
||||||
*/
|
*/
|
||||||
class Node extends GoCfg::ControlFlowNode {
|
class Node extends TControlFlowNode {
|
||||||
|
/** Gets a node that directly follows this one in the control-flow graph. */
|
||||||
|
Node getASuccessor() { result = CFG::succ(this) }
|
||||||
|
|
||||||
|
/** Gets a node that directly precedes this one in the control-flow graph. */
|
||||||
|
Node getAPredecessor() { this = result.getASuccessor() }
|
||||||
|
|
||||||
/** Holds if this is a node with more than one successor. */
|
/** Holds if this is a node with more than one successor. */
|
||||||
predicate isBranch() { strictcount(this.getASuccessor()) > 1 }
|
predicate isBranch() { strictcount(this.getASuccessor()) > 1 }
|
||||||
|
|
||||||
@@ -50,23 +52,22 @@ module ControlFlow {
|
|||||||
predicate isJoin() { strictcount(this.getAPredecessor()) > 1 }
|
predicate isJoin() { strictcount(this.getAPredecessor()) > 1 }
|
||||||
|
|
||||||
/** Holds if this is the first control-flow node in `subtree`. */
|
/** Holds if this is the first control-flow node in `subtree`. */
|
||||||
predicate isFirstNodeOf(AstNode subtree) {
|
predicate isFirstNodeOf(AstNode subtree) { CFG::firstNode(subtree, this) }
|
||||||
this.isBefore(subtree)
|
|
||||||
or
|
|
||||||
this.injects(subtree)
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Holds if this node is the (unique) entry node of a function. */
|
/** Holds if this node is the (unique) entry node of a function or file. */
|
||||||
predicate isEntryNode() { this instanceof GoCfg::ControlFlow::EntryNode }
|
predicate isEntryNode() { this instanceof MkEntryNode }
|
||||||
|
|
||||||
/** Holds if this node is the (unique) exit node of a function. */
|
/** Holds if this node is the (unique) exit node of a function or file. */
|
||||||
predicate isExitNode() { this instanceof GoCfg::ControlFlow::ExitNode }
|
predicate isExitNode() { this instanceof MkExitNode }
|
||||||
|
|
||||||
|
/** Gets the basic block to which this node belongs. */
|
||||||
|
BasicBlock getBasicBlock() { result.getANode() = this }
|
||||||
|
|
||||||
/** Holds if this node dominates `dominee` in the control-flow graph. */
|
/** Holds if this node dominates `dominee` in the control-flow graph. */
|
||||||
overlay[caller?]
|
overlay[caller?]
|
||||||
pragma[inline]
|
pragma[inline]
|
||||||
predicate dominatesNode(ControlFlow::Node dominee) {
|
predicate dominatesNode(ControlFlow::Node dominee) {
|
||||||
exists(GoCfg::Cfg::BasicBlock thisbb, GoCfg::Cfg::BasicBlock dbb, int i, int j |
|
exists(ReachableBasicBlock thisbb, ReachableBasicBlock dbb, int i, int j |
|
||||||
this = thisbb.getNode(i) and dominee = dbb.getNode(j)
|
this = thisbb.getNode(i) and dominee = dbb.getNode(j)
|
||||||
|
|
|
|
||||||
thisbb.strictlyDominates(dbb)
|
thisbb.strictlyDominates(dbb)
|
||||||
@@ -75,12 +76,20 @@ module ControlFlow {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Gets the innermost function to which this node belongs. */
|
/** Gets the innermost function or file to which this node belongs. */
|
||||||
Root getRoot() { result = this.getEnclosingCallable() }
|
Root getRoot() { none() }
|
||||||
|
|
||||||
/** Gets the file to which this node belongs. */
|
/** Gets the file to which this node belongs. */
|
||||||
File getFile() { result = this.getLocation().getFile() }
|
File getFile() { result = this.getLocation().getFile() }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a textual representation of this control flow node.
|
||||||
|
*/
|
||||||
|
string toString() { result = "control-flow node" }
|
||||||
|
|
||||||
|
/** Gets the source location for this element. */
|
||||||
|
Location getLocation() { none() }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* DEPRECATED: Use `getLocation()` instead.
|
* DEPRECATED: Use `getLocation()` instead.
|
||||||
*
|
*
|
||||||
@@ -104,22 +113,6 @@ module ControlFlow {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** A synthetic entry node for a function. */
|
|
||||||
class EntryNode extends Node instanceof GoCfg::ControlFlow::EntryNode { }
|
|
||||||
|
|
||||||
/** A synthetic exit node for a function. */
|
|
||||||
class ExitNode extends Node instanceof GoCfg::ControlFlow::ExitNode { }
|
|
||||||
|
|
||||||
private predicate isBranchConditionRoot(Expr expr) {
|
|
||||||
expr = any(LogicalBinaryExpr lbe).getLeftOperand()
|
|
||||||
or
|
|
||||||
expr = any(ForStmt fs).getCond()
|
|
||||||
or
|
|
||||||
expr = any(IfStmt is).getCond()
|
|
||||||
or
|
|
||||||
expr = any(ExpressionSwitchStmt ess | not exists(ess.getExpr())).getACase().getAnExpr()
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A control-flow node that initializes or updates the value of a constant, a variable,
|
* A control-flow node that initializes or updates the value of a constant, a variable,
|
||||||
* a field, or an (array, slice, or map) element.
|
* a field, or an (array, slice, or map) element.
|
||||||
@@ -179,7 +172,7 @@ module ControlFlow {
|
|||||||
exists(IR::FieldTarget trg | trg = super.getLhs() |
|
exists(IR::FieldTarget trg | trg = super.getLhs() |
|
||||||
(
|
(
|
||||||
trg.getBase() = base or
|
trg.getBase() = base or
|
||||||
trg.getBase() = IR::implicitDerefInstruction(base.(IR::EvalInstruction).getExpr())
|
trg.getBase() = MkImplicitDeref(base.(IR::EvalInstruction).getExpr())
|
||||||
) and
|
) and
|
||||||
trg.getField() = f and
|
trg.getField() = f and
|
||||||
super.getRhs() = rhs
|
super.getRhs() = rhs
|
||||||
@@ -227,7 +220,7 @@ module ControlFlow {
|
|||||||
exists(IR::ElementTarget trg | trg = super.getLhs() |
|
exists(IR::ElementTarget trg | trg = super.getLhs() |
|
||||||
(
|
(
|
||||||
trg.getBase() = base or
|
trg.getBase() = base or
|
||||||
trg.getBase() = IR::implicitDerefInstruction(base.(IR::EvalInstruction).getExpr())
|
trg.getBase() = MkImplicitDeref(base.(IR::EvalInstruction).getExpr())
|
||||||
) and
|
) and
|
||||||
trg.getIndex() = index and
|
trg.getIndex() = index and
|
||||||
super.getRhs() = rhs
|
super.getRhs() = rhs
|
||||||
@@ -257,19 +250,11 @@ module ControlFlow {
|
|||||||
* A control-flow node recording the fact that a certain expression has a known
|
* A control-flow node recording the fact that a certain expression has a known
|
||||||
* Boolean value at this point in the program.
|
* Boolean value at this point in the program.
|
||||||
*/
|
*/
|
||||||
class ConditionGuardNode extends IR::Instruction {
|
class ConditionGuardNode extends IR::Instruction, MkConditionGuardNode {
|
||||||
Expr cond;
|
Expr cond;
|
||||||
boolean outcome;
|
boolean outcome;
|
||||||
|
|
||||||
ConditionGuardNode() {
|
ConditionGuardNode() { this = MkConditionGuardNode(cond, outcome) }
|
||||||
isBranchConditionRoot(cond) and
|
|
||||||
this.isAfterTrue(cond) and
|
|
||||||
outcome = true
|
|
||||||
or
|
|
||||||
isBranchConditionRoot(cond) and
|
|
||||||
this.isAfterFalse(cond) and
|
|
||||||
outcome = false
|
|
||||||
}
|
|
||||||
|
|
||||||
private predicate ensuresAux(Expr expr, boolean b) {
|
private predicate ensuresAux(Expr expr, boolean b) {
|
||||||
expr = cond and b = outcome
|
expr = cond and b = outcome
|
||||||
@@ -335,17 +320,21 @@ module ControlFlow {
|
|||||||
boolean getOutcome() { result = outcome }
|
boolean getOutcome() { result = outcome }
|
||||||
|
|
||||||
override Root getRoot() { result.isRootOf(cond) }
|
override Root getRoot() { result.isRootOf(cond) }
|
||||||
|
|
||||||
|
override string toString() { result = cond + " is " + outcome }
|
||||||
|
|
||||||
|
override Location getLocation() { result = cond.getLocation() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the entry node of function `root`.
|
* Gets the entry node of function or file `root`.
|
||||||
*/
|
*/
|
||||||
EntryNode entryNode(Root root) { result.getEnclosingCallable() = root }
|
Node entryNode(Root root) { result = MkEntryNode(root) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the exit node of function `root`.
|
* Gets the exit node of function or file `root`.
|
||||||
*/
|
*/
|
||||||
ExitNode exitNode(Root root) { result.getEnclosingCallable() = root }
|
Node exitNode(Root root) { result = MkExitNode(root) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds if the function `f` may return without panicking, exiting the process, or looping forever.
|
* Holds if the function `f` may return without panicking, exiting the process, or looping forever.
|
||||||
@@ -353,12 +342,7 @@ module ControlFlow {
|
|||||||
* This is defined conservatively, and so may also hold of a function that in fact
|
* This is defined conservatively, and so may also hold of a function that in fact
|
||||||
* cannot return normally, but never fails to hold of a function that can return normally.
|
* cannot return normally, but never fails to hold of a function that can return normally.
|
||||||
*/
|
*/
|
||||||
predicate mayReturnNormally(FuncDecl f) {
|
predicate mayReturnNormally(FuncDecl f) { CFG::mayReturnNormally(f.getBody()) }
|
||||||
exists(GoCfg::ControlFlow::NormalExitNode exit |
|
|
||||||
exit.getEnclosingCallable() = f and
|
|
||||||
exists(exit.getAPredecessor())
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds if `pred` is the node for the case `testExpr` in an expression
|
* Holds if `pred` is the node for the case `testExpr` in an expression
|
||||||
@@ -368,18 +352,10 @@ module ControlFlow {
|
|||||||
predicate isSwitchCaseTestPassingEdge(
|
predicate isSwitchCaseTestPassingEdge(
|
||||||
ControlFlow::Node pred, ControlFlow::Node succ, Expr switchExpr, Expr testExpr
|
ControlFlow::Node pred, ControlFlow::Node succ, Expr switchExpr, Expr testExpr
|
||||||
) {
|
) {
|
||||||
exists(ExpressionSwitchStmt ess, CaseClause cc, int i |
|
CFG::isSwitchCaseTestPassingEdge(pred, succ, switchExpr, testExpr)
|
||||||
ess.getExpr() = switchExpr and
|
|
||||||
cc = ess.getACase() and
|
|
||||||
testExpr = cc.getExpr(i) and
|
|
||||||
pred.isAfter(testExpr) and
|
|
||||||
succ.isFirstNodeOf(cc.getStmt(0))
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ControlFlowNode = ControlFlow::Node;
|
class ControlFlowNode = ControlFlow::Node;
|
||||||
|
|
||||||
class CfgScope = GoCfg::CfgScope;
|
|
||||||
|
|
||||||
class Write = ControlFlow::WriteNode;
|
class Write = ControlFlow::WriteNode;
|
||||||
|
|||||||
2133
go/ql/lib/semmle/go/controlflow/ControlFlowGraphImpl.qll
Normal file
2133
go/ql/lib/semmle/go/controlflow/ControlFlowGraphImpl.qll
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -200,7 +200,7 @@ private ControlFlow::Node mostRecentSideEffect(ControlFlow::Node entry, ControlF
|
|||||||
|
|
||||||
cached
|
cached
|
||||||
private ControlFlow::Node mostRecentSideEffectUnique(ControlFlow::Node node) {
|
private ControlFlow::Node mostRecentSideEffectUnique(ControlFlow::Node node) {
|
||||||
result = unique( | | mostRecentSideEffect(getControlFlowEntry(node), node))
|
result = unique( | | mostRecentSideEffect(_, node))
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Used to represent the "global value number" of an expression. */
|
/** Used to represent the "global value number" of an expression. */
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ module;
|
|||||||
import go
|
import go
|
||||||
private import codeql.ssa.Ssa as SsaImplCommon
|
private import codeql.ssa.Ssa as SsaImplCommon
|
||||||
private import semmle.go.controlflow.BasicBlocks as BasicBlocks
|
private import semmle.go.controlflow.BasicBlocks as BasicBlocks
|
||||||
private import semmle.go.controlflow.ControlFlowGraphShared
|
|
||||||
|
|
||||||
private class BasicBlock = BasicBlocks::BasicBlock;
|
private class BasicBlock = BasicBlocks::BasicBlock;
|
||||||
|
|
||||||
@@ -39,7 +38,7 @@ private module Internal {
|
|||||||
/** Holds if the `i`th node of `bb` in function `f` is an entry node. */
|
/** Holds if the `i`th node of `bb` in function `f` is an entry node. */
|
||||||
private predicate entryNode(FuncDef f, BasicBlock bb, int i) {
|
private predicate entryNode(FuncDef f, BasicBlock bb, int i) {
|
||||||
f = bb.getScope() and
|
f = bb.getScope() and
|
||||||
bb.getNode(i).(ControlFlow::Node).isEntryNode()
|
bb.getNode(i).isEntryNode()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -111,7 +110,7 @@ private module Internal {
|
|||||||
v.isCaptured() and
|
v.isCaptured() and
|
||||||
exists(FuncDef f |
|
exists(FuncDef f |
|
||||||
f = bb.getScope() and
|
f = bb.getScope() and
|
||||||
bb.getLastNode().(ControlFlow::Node).isExitNode() and
|
bb.getLastNode().isExitNode() and
|
||||||
i = bb.length() - 1 and
|
i = bb.length() - 1 and
|
||||||
certain = false
|
certain = false
|
||||||
|
|
|
|
||||||
@@ -127,7 +126,7 @@ private module Internal {
|
|||||||
}
|
}
|
||||||
|
|
||||||
import Internal
|
import Internal
|
||||||
import SsaImplCommon::Make<Location, GoCfg::Cfg, SsaInput> as Impl
|
import SsaImplCommon::Make<Location, BasicBlocks::Cfg, SsaInput> as Impl
|
||||||
|
|
||||||
final class Definition = Impl::Definition;
|
final class Definition = Impl::Definition;
|
||||||
|
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ module Glog {
|
|||||||
/** Holds if this function takes a format string. */
|
/** Holds if this function takes a format string. */
|
||||||
predicate formatter() { format = "f" }
|
predicate formatter() { format = "f" }
|
||||||
|
|
||||||
override predicate mustNotReturnNormally() { level = "Fatal" or level = "Exit" }
|
override predicate mayReturnNormally() { level != "Fatal" and level != "Exit" }
|
||||||
}
|
}
|
||||||
|
|
||||||
private class StringFormatter extends StringOps::Formatting::Range instanceof GlogFunction {
|
private class StringFormatter extends StringOps::Formatting::Range instanceof GlogFunction {
|
||||||
|
|||||||
@@ -29,8 +29,8 @@ module Logrus {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override predicate mustNotReturnNormally() {
|
override predicate mayReturnNormally() {
|
||||||
exists(string level, string suffix | level = ["Fatal", "Panic"] |
|
not exists(string level, string suffix | level = ["Fatal", "Panic"] |
|
||||||
this.getName() = level + suffix
|
this.getName() = level + suffix
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -154,7 +154,7 @@ module Revel {
|
|||||||
|
|
||||||
private IR::EvalInstruction skipImplicitFieldReads(IR::Instruction insn) {
|
private IR::EvalInstruction skipImplicitFieldReads(IR::Instruction insn) {
|
||||||
result = insn or
|
result = insn or
|
||||||
result = skipImplicitFieldReads(insn.(IR::ImplicitFieldReadInstruction).getBaseInstruction())
|
result = skipImplicitFieldReads(insn.(IR::ImplicitFieldReadInstruction).getBase())
|
||||||
}
|
}
|
||||||
|
|
||||||
/** A call to `Controller.Render`. */
|
/** A call to `Controller.Render`. */
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ module Zap {
|
|||||||
this.hasQualifiedName(packagePath(), "SugaredLogger", "Fatal" + getSuffix())
|
this.hasQualifiedName(packagePath(), "SugaredLogger", "Fatal" + getSuffix())
|
||||||
}
|
}
|
||||||
|
|
||||||
override predicate mustNotReturnNormally() { any() }
|
override predicate mayReturnNormally() { none() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/** A Zap logging function which always panics. */
|
/** A Zap logging function which always panics. */
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ module Log {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override predicate mustNotReturnNormally() { any() }
|
override predicate mayReturnNormally() { none() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/** A log function which must panic. */
|
/** A log function which must panic. */
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ module Os {
|
|||||||
private class Exit extends Function {
|
private class Exit extends Function {
|
||||||
Exit() { this.hasQualifiedName("os", "Exit") }
|
Exit() { this.hasQualifiedName("os", "Exit") }
|
||||||
|
|
||||||
override predicate mustNotReturnNormally() { any() }
|
override predicate mayReturnNormally() { none() }
|
||||||
}
|
}
|
||||||
|
|
||||||
// These models are not implemented using Models-as-Data because they represent reverse flow.
|
// These models are not implemented using Models-as-Data because they represent reverse flow.
|
||||||
|
|||||||
@@ -14,36 +14,11 @@
|
|||||||
|
|
||||||
import go
|
import go
|
||||||
|
|
||||||
/**
|
ControlFlow::Node nonGuardPredecessor(ControlFlow::Node nd) {
|
||||||
* Holds if `s` is reachable, that is, the control-flow graph contains a node for it.
|
exists(ControlFlow::Node pred | pred = nd.getAPredecessor() |
|
||||||
*
|
if pred instanceof ControlFlow::ConditionGuardNode
|
||||||
* The shared control-flow library does not create control-flow nodes for dead code, so an
|
then result = nonGuardPredecessor(pred)
|
||||||
* unreachable statement has no first control-flow node.
|
else result = pred
|
||||||
*/
|
|
||||||
predicate isReachable(Stmt s) { exists(s.getFirstControlFlowNode()) }
|
|
||||||
|
|
||||||
/** Gets the statement immediately preceding `s` in a statement list, if any. */
|
|
||||||
Stmt getPreviousStmt(Stmt s) {
|
|
||||||
exists(BlockStmt b, int i | s = b.getStmt(i) and result = b.getStmt(i - 1))
|
|
||||||
or
|
|
||||||
exists(CaseClause c, int i | s = c.getStmt(i) and result = c.getStmt(i - 1))
|
|
||||||
or
|
|
||||||
exists(CommClause c, int i | s = c.getStmt(i) and result = c.getStmt(i - 1))
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Holds if `s` is unreachable but the code that would precede it in the control-flow graph is
|
|
||||||
* reachable, so that `s` is the first unreachable statement in a run of dead code.
|
|
||||||
*/
|
|
||||||
predicate firstUnreachableStmt(Stmt s) {
|
|
||||||
not isReachable(s) and
|
|
||||||
not s instanceof EmptyStmt and
|
|
||||||
(
|
|
||||||
// a statement whose preceding statement in the same list is reachable
|
|
||||||
isReachable(getPreviousStmt(s))
|
|
||||||
or
|
|
||||||
// the post statement of a `for` loop whose body is entered
|
|
||||||
exists(ForStmt f | s = f.getPost() and isReachable(f.getBody().getAStmt()))
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -88,13 +63,18 @@ predicate allowlist(Stmt s) {
|
|||||||
forall(Expr retval | retval = ret.getAnExpr() | isAllowedReturnValue(retval))
|
forall(Expr retval | retval = ret.getAnExpr() | isAllowedReturnValue(retval))
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
// statements deliberately made unreachable by a constant condition, such as the code
|
// statements in an `if false { ... }` and similar
|
||||||
// following `if true { return }`
|
exists(IfStmt is, ControlFlow::ConditionGuardNode iffalse, Expr cond, boolean b |
|
||||||
exists(getPreviousStmt(s).(IfStmt).getCond().getBoolValue())
|
iffalse.getCondition() = is.getCond() and
|
||||||
|
iffalse = s.getFirstControlFlowNode().getAPredecessor() and
|
||||||
|
cond.getBoolValue() = b and
|
||||||
|
iffalse.ensures(DataFlow::exprNode(cond), b.booleanNot())
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
from Stmt s
|
from Stmt s, ControlFlow::Node fst
|
||||||
where
|
where
|
||||||
firstUnreachableStmt(s) and
|
fst = s.getFirstControlFlowNode() and
|
||||||
|
not exists(nonGuardPredecessor(fst)) and
|
||||||
not allowlist(s)
|
not allowlist(s)
|
||||||
select s, "This statement is unreachable."
|
select s, "This statement is unreachable."
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
| main.go:23:3:23:21 | assign:0 ... = ... | main.go:23:17:23:21 | "200" |
|
| main.go:23:3:23:13 | assignment to field Status | main.go:23:17:23:21 | "200" |
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
| file://:0:0:0:0 | [summary param] -1 in Clone |
|
| file://:0:0:0:0 | [summary param] -1 in Clone |
|
||||||
| file://:0:0:0:0 | [summary param] -1 in Write |
|
| file://:0:0:0:0 | [summary param] -1 in Write |
|
||||||
| file://:0:0:0:0 | [summary param] -1 in WriteProxy |
|
| file://:0:0:0:0 | [summary param] -1 in WriteProxy |
|
||||||
| main.go:18:103:26:1 | SSA def(req) |
|
| main.go:18:12:18:14 | SSA def(req) |
|
||||||
| main.go:18:103:26:1 | arg:0 block statement |
|
| main.go:18:12:18:14 | argument corresponding to req |
|
||||||
| main.go:20:5:20:7 | req |
|
| main.go:20:5:20:7 | req |
|
||||||
| main.go:20:5:20:7 | req [postupdate] |
|
| main.go:20:5:20:7 | req [postupdate] |
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
| main.go:29:2:29:31 | assign:0 ... := ... | main.go:29:9:29:31 | call to test1 |
|
| main.go:29:2:29:4 | assignment to err | main.go:29:9:29:31 | call to test1 |
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
| main.go:10:2:12:3 | extract:0 ... := ... | This Pam transaction may not be secure. |
|
| main.go:10:2:12:3 | ... := ...[0] | This Pam transaction may not be secure. |
|
||||||
@@ -8,23 +8,23 @@
|
|||||||
edges
|
edges
|
||||||
| DivideByZero.go:10:12:10:16 | selection of URL | DivideByZero.go:10:12:10:24 | call to Query | provenance | Src:MaD:1 MaD:2 |
|
| DivideByZero.go:10:12:10:16 | selection of URL | DivideByZero.go:10:12:10:24 | call to Query | provenance | Src:MaD:1 MaD:2 |
|
||||||
| DivideByZero.go:10:12:10:24 | call to Query | DivideByZero.go:11:27:11:32 | param1 | provenance | |
|
| DivideByZero.go:10:12:10:24 | call to Query | DivideByZero.go:11:27:11:32 | param1 | provenance | |
|
||||||
| DivideByZero.go:11:2:11:33 | extract:0 ... := ... | DivideByZero.go:12:16:12:20 | value | provenance | |
|
| DivideByZero.go:11:2:11:33 | ... := ...[0] | DivideByZero.go:12:16:12:20 | value | provenance | |
|
||||||
| DivideByZero.go:11:27:11:32 | param1 | DivideByZero.go:11:2:11:33 | extract:0 ... := ... | provenance | Config |
|
| DivideByZero.go:11:27:11:32 | param1 | DivideByZero.go:11:2:11:33 | ... := ...[0] | provenance | Config |
|
||||||
| DivideByZero.go:17:12:17:16 | selection of URL | DivideByZero.go:17:12:17:24 | call to Query | provenance | Src:MaD:1 MaD:2 |
|
| DivideByZero.go:17:12:17:16 | selection of URL | DivideByZero.go:17:12:17:24 | call to Query | provenance | Src:MaD:1 MaD:2 |
|
||||||
| DivideByZero.go:17:12:17:24 | call to Query | DivideByZero.go:18:11:18:24 | type conversion | provenance | |
|
| DivideByZero.go:17:12:17:24 | call to Query | DivideByZero.go:18:11:18:24 | type conversion | provenance | |
|
||||||
| DivideByZero.go:18:11:18:24 | type conversion | DivideByZero.go:19:16:19:20 | value | provenance | |
|
| DivideByZero.go:18:11:18:24 | type conversion | DivideByZero.go:19:16:19:20 | value | provenance | |
|
||||||
| DivideByZero.go:24:12:24:16 | selection of URL | DivideByZero.go:24:12:24:24 | call to Query | provenance | Src:MaD:1 MaD:2 |
|
| DivideByZero.go:24:12:24:16 | selection of URL | DivideByZero.go:24:12:24:24 | call to Query | provenance | Src:MaD:1 MaD:2 |
|
||||||
| DivideByZero.go:24:12:24:24 | call to Query | DivideByZero.go:25:31:25:36 | param1 | provenance | |
|
| DivideByZero.go:24:12:24:24 | call to Query | DivideByZero.go:25:31:25:36 | param1 | provenance | |
|
||||||
| DivideByZero.go:25:2:25:45 | extract:0 ... := ... | DivideByZero.go:26:16:26:20 | value | provenance | |
|
| DivideByZero.go:25:2:25:45 | ... := ...[0] | DivideByZero.go:26:16:26:20 | value | provenance | |
|
||||||
| DivideByZero.go:25:31:25:36 | param1 | DivideByZero.go:25:2:25:45 | extract:0 ... := ... | provenance | Config |
|
| DivideByZero.go:25:31:25:36 | param1 | DivideByZero.go:25:2:25:45 | ... := ...[0] | provenance | Config |
|
||||||
| DivideByZero.go:31:12:31:16 | selection of URL | DivideByZero.go:31:12:31:24 | call to Query | provenance | Src:MaD:1 MaD:2 |
|
| DivideByZero.go:31:12:31:16 | selection of URL | DivideByZero.go:31:12:31:24 | call to Query | provenance | Src:MaD:1 MaD:2 |
|
||||||
| DivideByZero.go:31:12:31:24 | call to Query | DivideByZero.go:32:33:32:38 | param1 | provenance | |
|
| DivideByZero.go:31:12:31:24 | call to Query | DivideByZero.go:32:33:32:38 | param1 | provenance | |
|
||||||
| DivideByZero.go:32:2:32:43 | extract:0 ... := ... | DivideByZero.go:33:16:33:20 | value | provenance | |
|
| DivideByZero.go:32:2:32:43 | ... := ...[0] | DivideByZero.go:33:16:33:20 | value | provenance | |
|
||||||
| DivideByZero.go:32:33:32:38 | param1 | DivideByZero.go:32:2:32:43 | extract:0 ... := ... | provenance | Config |
|
| DivideByZero.go:32:33:32:38 | param1 | DivideByZero.go:32:2:32:43 | ... := ...[0] | provenance | Config |
|
||||||
| DivideByZero.go:38:12:38:16 | selection of URL | DivideByZero.go:38:12:38:24 | call to Query | provenance | Src:MaD:1 MaD:2 |
|
| DivideByZero.go:38:12:38:16 | selection of URL | DivideByZero.go:38:12:38:24 | call to Query | provenance | Src:MaD:1 MaD:2 |
|
||||||
| DivideByZero.go:38:12:38:24 | call to Query | DivideByZero.go:39:32:39:37 | param1 | provenance | |
|
| DivideByZero.go:38:12:38:24 | call to Query | DivideByZero.go:39:32:39:37 | param1 | provenance | |
|
||||||
| DivideByZero.go:39:2:39:46 | extract:0 ... := ... | DivideByZero.go:40:16:40:20 | value | provenance | |
|
| DivideByZero.go:39:2:39:46 | ... := ...[0] | DivideByZero.go:40:16:40:20 | value | provenance | |
|
||||||
| DivideByZero.go:39:32:39:37 | param1 | DivideByZero.go:39:2:39:46 | extract:0 ... := ... | provenance | Config |
|
| DivideByZero.go:39:32:39:37 | param1 | DivideByZero.go:39:2:39:46 | ... := ...[0] | provenance | Config |
|
||||||
| DivideByZero.go:54:12:54:16 | selection of URL | DivideByZero.go:54:12:54:24 | call to Query | provenance | Src:MaD:1 MaD:2 |
|
| DivideByZero.go:54:12:54:16 | selection of URL | DivideByZero.go:54:12:54:24 | call to Query | provenance | Src:MaD:1 MaD:2 |
|
||||||
| DivideByZero.go:54:12:54:24 | call to Query | DivideByZero.go:55:11:55:24 | type conversion | provenance | |
|
| DivideByZero.go:54:12:54:24 | call to Query | DivideByZero.go:55:11:55:24 | type conversion | provenance | |
|
||||||
| DivideByZero.go:55:11:55:24 | type conversion | DivideByZero.go:57:17:57:21 | value | provenance | |
|
| DivideByZero.go:55:11:55:24 | type conversion | DivideByZero.go:57:17:57:21 | value | provenance | |
|
||||||
@@ -34,7 +34,7 @@ models
|
|||||||
nodes
|
nodes
|
||||||
| DivideByZero.go:10:12:10:16 | selection of URL | semmle.label | selection of URL |
|
| DivideByZero.go:10:12:10:16 | selection of URL | semmle.label | selection of URL |
|
||||||
| DivideByZero.go:10:12:10:24 | call to Query | semmle.label | call to Query |
|
| DivideByZero.go:10:12:10:24 | call to Query | semmle.label | call to Query |
|
||||||
| DivideByZero.go:11:2:11:33 | extract:0 ... := ... | semmle.label | extract:0 ... := ... |
|
| DivideByZero.go:11:2:11:33 | ... := ...[0] | semmle.label | ... := ...[0] |
|
||||||
| DivideByZero.go:11:27:11:32 | param1 | semmle.label | param1 |
|
| DivideByZero.go:11:27:11:32 | param1 | semmle.label | param1 |
|
||||||
| DivideByZero.go:12:16:12:20 | value | semmle.label | value |
|
| DivideByZero.go:12:16:12:20 | value | semmle.label | value |
|
||||||
| DivideByZero.go:17:12:17:16 | selection of URL | semmle.label | selection of URL |
|
| DivideByZero.go:17:12:17:16 | selection of URL | semmle.label | selection of URL |
|
||||||
@@ -43,17 +43,17 @@ nodes
|
|||||||
| DivideByZero.go:19:16:19:20 | value | semmle.label | value |
|
| DivideByZero.go:19:16:19:20 | value | semmle.label | value |
|
||||||
| DivideByZero.go:24:12:24:16 | selection of URL | semmle.label | selection of URL |
|
| DivideByZero.go:24:12:24:16 | selection of URL | semmle.label | selection of URL |
|
||||||
| DivideByZero.go:24:12:24:24 | call to Query | semmle.label | call to Query |
|
| DivideByZero.go:24:12:24:24 | call to Query | semmle.label | call to Query |
|
||||||
| DivideByZero.go:25:2:25:45 | extract:0 ... := ... | semmle.label | extract:0 ... := ... |
|
| DivideByZero.go:25:2:25:45 | ... := ...[0] | semmle.label | ... := ...[0] |
|
||||||
| DivideByZero.go:25:31:25:36 | param1 | semmle.label | param1 |
|
| DivideByZero.go:25:31:25:36 | param1 | semmle.label | param1 |
|
||||||
| DivideByZero.go:26:16:26:20 | value | semmle.label | value |
|
| DivideByZero.go:26:16:26:20 | value | semmle.label | value |
|
||||||
| DivideByZero.go:31:12:31:16 | selection of URL | semmle.label | selection of URL |
|
| DivideByZero.go:31:12:31:16 | selection of URL | semmle.label | selection of URL |
|
||||||
| DivideByZero.go:31:12:31:24 | call to Query | semmle.label | call to Query |
|
| DivideByZero.go:31:12:31:24 | call to Query | semmle.label | call to Query |
|
||||||
| DivideByZero.go:32:2:32:43 | extract:0 ... := ... | semmle.label | extract:0 ... := ... |
|
| DivideByZero.go:32:2:32:43 | ... := ...[0] | semmle.label | ... := ...[0] |
|
||||||
| DivideByZero.go:32:33:32:38 | param1 | semmle.label | param1 |
|
| DivideByZero.go:32:33:32:38 | param1 | semmle.label | param1 |
|
||||||
| DivideByZero.go:33:16:33:20 | value | semmle.label | value |
|
| DivideByZero.go:33:16:33:20 | value | semmle.label | value |
|
||||||
| DivideByZero.go:38:12:38:16 | selection of URL | semmle.label | selection of URL |
|
| DivideByZero.go:38:12:38:16 | selection of URL | semmle.label | selection of URL |
|
||||||
| DivideByZero.go:38:12:38:24 | call to Query | semmle.label | call to Query |
|
| DivideByZero.go:38:12:38:24 | call to Query | semmle.label | call to Query |
|
||||||
| DivideByZero.go:39:2:39:46 | extract:0 ... := ... | semmle.label | extract:0 ... := ... |
|
| DivideByZero.go:39:2:39:46 | ... := ...[0] | semmle.label | ... := ...[0] |
|
||||||
| DivideByZero.go:39:32:39:37 | param1 | semmle.label | param1 |
|
| DivideByZero.go:39:32:39:37 | param1 | semmle.label | param1 |
|
||||||
| DivideByZero.go:40:16:40:20 | value | semmle.label | value |
|
| DivideByZero.go:40:16:40:20 | value | semmle.label | value |
|
||||||
| DivideByZero.go:54:12:54:16 | selection of URL | semmle.label | selection of URL |
|
| DivideByZero.go:54:12:54:16 | selection of URL | semmle.label | selection of URL |
|
||||||
|
|||||||
@@ -8,14 +8,14 @@ edges
|
|||||||
| Dsn.go:28:102:28:109 | index expression | Dsn.go:28:11:28:110 | []type{args} [array] | provenance | |
|
| Dsn.go:28:102:28:109 | index expression | Dsn.go:28:11:28:110 | []type{args} [array] | provenance | |
|
||||||
| Dsn.go:28:102:28:109 | index expression | Dsn.go:28:11:28:110 | call to Sprintf | provenance | FunctionModel |
|
| Dsn.go:28:102:28:109 | index expression | Dsn.go:28:11:28:110 | call to Sprintf | provenance | FunctionModel |
|
||||||
| Dsn.go:63:9:63:11 | cfg [postupdate] [pointer] | Dsn.go:67:102:67:104 | cfg [pointer] | provenance | |
|
| Dsn.go:63:9:63:11 | cfg [postupdate] [pointer] | Dsn.go:67:102:67:104 | cfg [pointer] | provenance | |
|
||||||
| Dsn.go:63:9:63:11 | implicit-deref cfg [postupdate] | Dsn.go:63:9:63:11 | cfg [postupdate] [pointer] | provenance | |
|
| Dsn.go:63:9:63:11 | implicit dereference [postupdate] | Dsn.go:63:9:63:11 | cfg [postupdate] [pointer] | provenance | |
|
||||||
| Dsn.go:63:9:63:11 | implicit-deref cfg [postupdate] | Dsn.go:67:102:67:108 | selection of dsn | provenance | |
|
| Dsn.go:63:9:63:11 | implicit dereference [postupdate] | Dsn.go:67:102:67:108 | selection of dsn | provenance | |
|
||||||
| Dsn.go:63:19:63:25 | selection of Args | Dsn.go:63:19:63:29 | slice expression | provenance | Src:MaD:1 |
|
| Dsn.go:63:19:63:25 | selection of Args | Dsn.go:63:19:63:29 | slice expression | provenance | Src:MaD:1 |
|
||||||
| Dsn.go:63:19:63:29 | slice expression | Dsn.go:63:9:63:11 | implicit-deref cfg [postupdate] | provenance | FunctionModel |
|
| Dsn.go:63:19:63:29 | slice expression | Dsn.go:63:9:63:11 | implicit dereference [postupdate] | provenance | FunctionModel |
|
||||||
| Dsn.go:67:11:67:109 | []type{args} [array] | Dsn.go:67:11:67:109 | call to Sprintf | provenance | MaD:2 |
|
| Dsn.go:67:11:67:109 | []type{args} [array] | Dsn.go:67:11:67:109 | call to Sprintf | provenance | MaD:2 |
|
||||||
| Dsn.go:67:11:67:109 | call to Sprintf | Dsn.go:68:29:68:33 | dbDSN | provenance | |
|
| Dsn.go:67:11:67:109 | call to Sprintf | Dsn.go:68:29:68:33 | dbDSN | provenance | |
|
||||||
| Dsn.go:67:102:67:104 | cfg [pointer] | Dsn.go:67:102:67:104 | implicit-deref cfg | provenance | |
|
| Dsn.go:67:102:67:104 | cfg [pointer] | Dsn.go:67:102:67:104 | implicit dereference | provenance | |
|
||||||
| Dsn.go:67:102:67:104 | implicit-deref cfg | Dsn.go:67:102:67:108 | selection of dsn | provenance | |
|
| Dsn.go:67:102:67:104 | implicit dereference | Dsn.go:67:102:67:108 | selection of dsn | provenance | |
|
||||||
| Dsn.go:67:102:67:108 | selection of dsn | Dsn.go:67:11:67:109 | []type{args} [array] | provenance | |
|
| Dsn.go:67:102:67:108 | selection of dsn | Dsn.go:67:11:67:109 | []type{args} [array] | provenance | |
|
||||||
| Dsn.go:67:102:67:108 | selection of dsn | Dsn.go:67:11:67:109 | call to Sprintf | provenance | FunctionModel |
|
| Dsn.go:67:102:67:108 | selection of dsn | Dsn.go:67:11:67:109 | call to Sprintf | provenance | FunctionModel |
|
||||||
models
|
models
|
||||||
@@ -28,13 +28,13 @@ nodes
|
|||||||
| Dsn.go:28:102:28:109 | index expression | semmle.label | index expression |
|
| Dsn.go:28:102:28:109 | index expression | semmle.label | index expression |
|
||||||
| Dsn.go:29:29:29:33 | dbDSN | semmle.label | dbDSN |
|
| Dsn.go:29:29:29:33 | dbDSN | semmle.label | dbDSN |
|
||||||
| Dsn.go:63:9:63:11 | cfg [postupdate] [pointer] | semmle.label | cfg [postupdate] [pointer] |
|
| Dsn.go:63:9:63:11 | cfg [postupdate] [pointer] | semmle.label | cfg [postupdate] [pointer] |
|
||||||
| Dsn.go:63:9:63:11 | implicit-deref cfg [postupdate] | semmle.label | implicit-deref cfg [postupdate] |
|
| Dsn.go:63:9:63:11 | implicit dereference [postupdate] | semmle.label | implicit dereference [postupdate] |
|
||||||
| Dsn.go:63:19:63:25 | selection of Args | semmle.label | selection of Args |
|
| Dsn.go:63:19:63:25 | selection of Args | semmle.label | selection of Args |
|
||||||
| Dsn.go:63:19:63:29 | slice expression | semmle.label | slice expression |
|
| Dsn.go:63:19:63:29 | slice expression | semmle.label | slice expression |
|
||||||
| Dsn.go:67:11:67:109 | []type{args} [array] | semmle.label | []type{args} [array] |
|
| Dsn.go:67:11:67:109 | []type{args} [array] | semmle.label | []type{args} [array] |
|
||||||
| Dsn.go:67:11:67:109 | call to Sprintf | semmle.label | call to Sprintf |
|
| Dsn.go:67:11:67:109 | call to Sprintf | semmle.label | call to Sprintf |
|
||||||
| Dsn.go:67:102:67:104 | cfg [pointer] | semmle.label | cfg [pointer] |
|
| Dsn.go:67:102:67:104 | cfg [pointer] | semmle.label | cfg [pointer] |
|
||||||
| Dsn.go:67:102:67:104 | implicit-deref cfg | semmle.label | implicit-deref cfg |
|
| Dsn.go:67:102:67:104 | implicit dereference | semmle.label | implicit dereference |
|
||||||
| Dsn.go:67:102:67:108 | selection of dsn | semmle.label | selection of dsn |
|
| Dsn.go:67:102:67:108 | selection of dsn | semmle.label | selection of dsn |
|
||||||
| Dsn.go:68:29:68:33 | dbDSN | semmle.label | dbDSN |
|
| Dsn.go:68:29:68:33 | dbDSN | semmle.label | dbDSN |
|
||||||
subpaths
|
subpaths
|
||||||
|
|||||||
@@ -24,9 +24,9 @@ edges
|
|||||||
| builtin.go:112:21:112:31 | call to Referer | builtin.go:115:15:115:28 | untrustedInput | provenance | Src:MaD:8 |
|
| builtin.go:112:21:112:31 | call to Referer | builtin.go:115:15:115:28 | untrustedInput | provenance | Src:MaD:8 |
|
||||||
| builtin.go:130:21:130:31 | call to Referer | builtin.go:133:38:133:51 | untrustedInput | provenance | Src:MaD:8 |
|
| builtin.go:130:21:130:31 | call to Referer | builtin.go:133:38:133:51 | untrustedInput | provenance | Src:MaD:8 |
|
||||||
| builtin.go:151:16:151:36 | call to FormValue | builtin.go:154:13:154:22 | unsafehost | provenance | Src:MaD:7 |
|
| builtin.go:151:16:151:36 | call to FormValue | builtin.go:154:13:154:22 | unsafehost | provenance | Src:MaD:7 |
|
||||||
| builtin.go:154:2:154:4 | implicit-deref url [postupdate] | builtin.go:154:2:154:4 | url [postupdate] | provenance | |
|
| builtin.go:154:2:154:4 | implicit dereference [postupdate] | builtin.go:154:2:154:4 | url [postupdate] | provenance | |
|
||||||
| builtin.go:154:2:154:4 | url [postupdate] | builtin.go:156:21:156:23 | url | provenance | |
|
| builtin.go:154:2:154:4 | url [postupdate] | builtin.go:156:21:156:23 | url | provenance | |
|
||||||
| builtin.go:154:13:154:22 | unsafehost | builtin.go:154:2:154:4 | implicit-deref url [postupdate] | provenance | Config |
|
| builtin.go:154:13:154:22 | unsafehost | builtin.go:154:2:154:4 | implicit dereference [postupdate] | provenance | Config |
|
||||||
| builtin.go:154:13:154:22 | unsafehost | builtin.go:154:2:154:4 | url [postupdate] | provenance | Config |
|
| builtin.go:154:13:154:22 | unsafehost | builtin.go:154:2:154:4 | url [postupdate] | provenance | Config |
|
||||||
| builtin.go:156:21:156:23 | url | builtin.go:156:21:156:32 | call to String | provenance | MaD:12 |
|
| builtin.go:156:21:156:23 | url | builtin.go:156:21:156:32 | call to String | provenance | MaD:12 |
|
||||||
| new-tests.go:26:26:26:30 | &... [postupdate] | new-tests.go:31:48:31:56 | selection of word | provenance | Src:MaD:3 |
|
| new-tests.go:26:26:26:30 | &... [postupdate] | new-tests.go:31:48:31:56 | selection of word | provenance | Src:MaD:3 |
|
||||||
@@ -43,8 +43,8 @@ edges
|
|||||||
| new-tests.go:35:49:35:57 | selection of word | new-tests.go:35:12:35:58 | call to Sprintf | provenance | FunctionModel |
|
| new-tests.go:35:49:35:57 | selection of word | new-tests.go:35:12:35:58 | call to Sprintf | provenance | FunctionModel |
|
||||||
| new-tests.go:39:18:39:30 | call to Param | new-tests.go:47:11:47:46 | ...+... | provenance | Src:MaD:1 |
|
| new-tests.go:39:18:39:30 | call to Param | new-tests.go:47:11:47:46 | ...+... | provenance | Src:MaD:1 |
|
||||||
| new-tests.go:49:18:49:30 | call to Query | new-tests.go:50:11:50:46 | ...+... | provenance | Src:MaD:2 |
|
| new-tests.go:49:18:49:30 | call to Query | new-tests.go:50:11:50:46 | ...+... | provenance | Src:MaD:2 |
|
||||||
| new-tests.go:62:2:62:39 | extract:0 ... := ... | new-tests.go:63:17:63:23 | reqBody | provenance | |
|
| new-tests.go:62:2:62:39 | ... := ...[0] | new-tests.go:63:17:63:23 | reqBody | provenance | |
|
||||||
| new-tests.go:62:31:62:38 | selection of Body | new-tests.go:62:2:62:39 | extract:0 ... := ... | provenance | Src:MaD:6 MaD:13 |
|
| new-tests.go:62:31:62:38 | selection of Body | new-tests.go:62:2:62:39 | ... := ...[0] | provenance | Src:MaD:6 MaD:13 |
|
||||||
| new-tests.go:63:17:63:23 | reqBody | new-tests.go:63:26:63:30 | &... [postupdate] | provenance | MaD:10 |
|
| new-tests.go:63:17:63:23 | reqBody | new-tests.go:63:26:63:30 | &... [postupdate] | provenance | MaD:10 |
|
||||||
| new-tests.go:63:26:63:30 | &... [postupdate] | new-tests.go:68:48:68:56 | selection of word | provenance | |
|
| new-tests.go:63:26:63:30 | &... [postupdate] | new-tests.go:68:48:68:56 | selection of word | provenance | |
|
||||||
| new-tests.go:63:26:63:30 | &... [postupdate] | new-tests.go:69:48:69:56 | selection of safe | provenance | |
|
| new-tests.go:63:26:63:30 | &... [postupdate] | new-tests.go:69:48:69:56 | selection of safe | provenance | |
|
||||||
@@ -95,7 +95,7 @@ nodes
|
|||||||
| builtin.go:130:21:130:31 | call to Referer | semmle.label | call to Referer |
|
| builtin.go:130:21:130:31 | call to Referer | semmle.label | call to Referer |
|
||||||
| builtin.go:133:38:133:51 | untrustedInput | semmle.label | untrustedInput |
|
| builtin.go:133:38:133:51 | untrustedInput | semmle.label | untrustedInput |
|
||||||
| builtin.go:151:16:151:36 | call to FormValue | semmle.label | call to FormValue |
|
| builtin.go:151:16:151:36 | call to FormValue | semmle.label | call to FormValue |
|
||||||
| builtin.go:154:2:154:4 | implicit-deref url [postupdate] | semmle.label | implicit-deref url [postupdate] |
|
| builtin.go:154:2:154:4 | implicit dereference [postupdate] | semmle.label | implicit dereference [postupdate] |
|
||||||
| builtin.go:154:2:154:4 | url [postupdate] | semmle.label | url [postupdate] |
|
| builtin.go:154:2:154:4 | url [postupdate] | semmle.label | url [postupdate] |
|
||||||
| builtin.go:154:13:154:22 | unsafehost | semmle.label | unsafehost |
|
| builtin.go:154:13:154:22 | unsafehost | semmle.label | unsafehost |
|
||||||
| builtin.go:156:21:156:23 | url | semmle.label | url |
|
| builtin.go:156:21:156:23 | url | semmle.label | url |
|
||||||
@@ -114,7 +114,7 @@ nodes
|
|||||||
| new-tests.go:47:11:47:46 | ...+... | semmle.label | ...+... |
|
| new-tests.go:47:11:47:46 | ...+... | semmle.label | ...+... |
|
||||||
| new-tests.go:49:18:49:30 | call to Query | semmle.label | call to Query |
|
| new-tests.go:49:18:49:30 | call to Query | semmle.label | call to Query |
|
||||||
| new-tests.go:50:11:50:46 | ...+... | semmle.label | ...+... |
|
| new-tests.go:50:11:50:46 | ...+... | semmle.label | ...+... |
|
||||||
| new-tests.go:62:2:62:39 | extract:0 ... := ... | semmle.label | extract:0 ... := ... |
|
| new-tests.go:62:2:62:39 | ... := ...[0] | semmle.label | ... := ...[0] |
|
||||||
| new-tests.go:62:31:62:38 | selection of Body | semmle.label | selection of Body |
|
| new-tests.go:62:31:62:38 | selection of Body | semmle.label | selection of Body |
|
||||||
| new-tests.go:63:17:63:23 | reqBody | semmle.label | reqBody |
|
| new-tests.go:63:17:63:23 | reqBody | semmle.label | reqBody |
|
||||||
| new-tests.go:63:26:63:30 | &... [postupdate] | semmle.label | &... [postupdate] |
|
| new-tests.go:63:26:63:30 | &... [postupdate] | semmle.label | &... [postupdate] |
|
||||||
|
|||||||
@@ -22,8 +22,8 @@ edges
|
|||||||
| WrongUsageOfUnsafe.go:166:33:166:57 | type conversion | WrongUsageOfUnsafe.go:166:16:166:58 | type conversion | provenance | |
|
| WrongUsageOfUnsafe.go:166:33:166:57 | type conversion | WrongUsageOfUnsafe.go:166:16:166:58 | type conversion | provenance | |
|
||||||
| WrongUsageOfUnsafe.go:189:31:189:55 | type conversion | WrongUsageOfUnsafe.go:189:16:189:56 | type conversion | provenance | |
|
| WrongUsageOfUnsafe.go:189:31:189:55 | type conversion | WrongUsageOfUnsafe.go:189:16:189:56 | type conversion | provenance | |
|
||||||
| WrongUsageOfUnsafe.go:211:31:211:60 | type conversion | WrongUsageOfUnsafe.go:211:16:211:61 | type conversion | provenance | |
|
| WrongUsageOfUnsafe.go:211:31:211:60 | type conversion | WrongUsageOfUnsafe.go:211:16:211:61 | type conversion | provenance | |
|
||||||
| WrongUsageOfUnsafe.go:227:31:227:55 | type conversion | WrongUsageOfUnsafe.go:236:53:245:1 | SSA def(req) | provenance | |
|
| WrongUsageOfUnsafe.go:227:31:227:55 | type conversion | WrongUsageOfUnsafe.go:236:21:236:23 | SSA def(req) | provenance | |
|
||||||
| WrongUsageOfUnsafe.go:236:53:245:1 | SSA def(req) | WrongUsageOfUnsafe.go:243:9:243:27 | type conversion | provenance | |
|
| WrongUsageOfUnsafe.go:236:21:236:23 | SSA def(req) | WrongUsageOfUnsafe.go:243:9:243:27 | type conversion | provenance | |
|
||||||
| WrongUsageOfUnsafe.go:256:28:256:52 | type conversion | WrongUsageOfUnsafe.go:256:16:256:53 | type conversion | provenance | |
|
| WrongUsageOfUnsafe.go:256:28:256:52 | type conversion | WrongUsageOfUnsafe.go:256:16:256:53 | type conversion | provenance | |
|
||||||
| WrongUsageOfUnsafe.go:274:25:274:49 | type conversion | WrongUsageOfUnsafe.go:274:16:274:50 | type conversion | provenance | |
|
| WrongUsageOfUnsafe.go:274:25:274:49 | type conversion | WrongUsageOfUnsafe.go:274:16:274:50 | type conversion | provenance | |
|
||||||
| WrongUsageOfUnsafe.go:292:23:292:47 | type conversion | WrongUsageOfUnsafe.go:292:16:292:48 | type conversion | provenance | |
|
| WrongUsageOfUnsafe.go:292:23:292:47 | type conversion | WrongUsageOfUnsafe.go:292:16:292:48 | type conversion | provenance | |
|
||||||
@@ -51,7 +51,7 @@ nodes
|
|||||||
| WrongUsageOfUnsafe.go:211:16:211:61 | type conversion | semmle.label | type conversion |
|
| WrongUsageOfUnsafe.go:211:16:211:61 | type conversion | semmle.label | type conversion |
|
||||||
| WrongUsageOfUnsafe.go:211:31:211:60 | type conversion | semmle.label | type conversion |
|
| WrongUsageOfUnsafe.go:211:31:211:60 | type conversion | semmle.label | type conversion |
|
||||||
| WrongUsageOfUnsafe.go:227:31:227:55 | type conversion | semmle.label | type conversion |
|
| WrongUsageOfUnsafe.go:227:31:227:55 | type conversion | semmle.label | type conversion |
|
||||||
| WrongUsageOfUnsafe.go:236:53:245:1 | SSA def(req) | semmle.label | SSA def(req) |
|
| WrongUsageOfUnsafe.go:236:21:236:23 | SSA def(req) | semmle.label | SSA def(req) |
|
||||||
| WrongUsageOfUnsafe.go:243:9:243:27 | type conversion | semmle.label | type conversion |
|
| WrongUsageOfUnsafe.go:243:9:243:27 | type conversion | semmle.label | type conversion |
|
||||||
| WrongUsageOfUnsafe.go:256:16:256:53 | type conversion | semmle.label | type conversion |
|
| WrongUsageOfUnsafe.go:256:16:256:53 | type conversion | semmle.label | type conversion |
|
||||||
| WrongUsageOfUnsafe.go:256:28:256:52 | type conversion | semmle.label | type conversion |
|
| WrongUsageOfUnsafe.go:256:28:256:52 | type conversion | semmle.label | type conversion |
|
||||||
|
|||||||
@@ -1,156 +1,64 @@
|
|||||||
nodes
|
nodes
|
||||||
edges
|
edges
|
||||||
| conversions.go:0:0:0:0 | After conversions.go | conversions.go:0:0:0:0 | Normal Exit |
|
| conversions.go:0:0:0:0 | entry | conversions.go:3:1:3:15 | skip |
|
||||||
| conversions.go:0:0:0:0 | Entry | conversions.go:0:0:0:0 | conversions.go |
|
| conversions.go:3:1:3:15 | skip | conversions.go:5:6:5:8 | skip |
|
||||||
| conversions.go:0:0:0:0 | Normal Exit | conversions.go:0:0:0:0 | Exit |
|
| conversions.go:5:1:5:29 | entry | conversions.go:5:10:5:10 | argument corresponding to _ |
|
||||||
| conversions.go:0:0:0:0 | conversions.go | conversions.go:3:1:3:15 | import declaration |
|
| conversions.go:5:1:5:29 | function declaration | conversions.go:7:6:7:9 | skip |
|
||||||
| conversions.go:3:1:3:15 | After import declaration | conversions.go:5:1:5:29 | Before function declaration |
|
| conversions.go:5:6:5:8 | skip | conversions.go:5:1:5:29 | function declaration |
|
||||||
| conversions.go:3:1:3:15 | import declaration | conversions.go:3:8:3:15 | import specifier |
|
| conversions.go:5:10:5:10 | argument corresponding to _ | conversions.go:5:10:5:10 | initialization of _ |
|
||||||
| conversions.go:3:8:3:15 | import specifier | conversions.go:3:1:3:15 | After import declaration |
|
| conversions.go:5:10:5:10 | initialization of _ | conversions.go:5:28:5:29 | skip |
|
||||||
| conversions.go:5:1:5:29 | After function declaration | conversions.go:7:1:26:1 | Before function declaration |
|
| conversions.go:5:28:5:29 | skip | conversions.go:5:1:5:29 | exit |
|
||||||
| conversions.go:5:1:5:29 | Before function declaration | conversions.go:5:1:5:29 | function declaration |
|
| conversions.go:7:1:26:1 | entry | conversions.go:8:6:8:6 | skip |
|
||||||
| conversions.go:5:1:5:29 | Entry | conversions.go:5:28:5:29 | block statement |
|
| conversions.go:7:1:26:1 | function declaration | conversions.go:0:0:0:0 | exit |
|
||||||
| conversions.go:5:1:5:29 | Normal Exit | conversions.go:5:1:5:29 | Exit |
|
| conversions.go:7:6:7:9 | skip | conversions.go:7:1:26:1 | function declaration |
|
||||||
| conversions.go:5:1:5:29 | function declaration | conversions.go:5:1:5:29 | After function declaration |
|
| conversions.go:8:6:8:6 | assignment to a | conversions.go:10:2:10:2 | skip |
|
||||||
| conversions.go:5:28:5:29 | After block statement | conversions.go:5:1:5:29 | Normal Exit |
|
| conversions.go:8:6:8:6 | skip | conversions.go:8:6:8:6 | zero value for a |
|
||||||
| conversions.go:5:28:5:29 | arg:0 block statement | conversions.go:5:28:5:29 | param-init:0 block statement |
|
| conversions.go:8:6:8:6 | zero value for a | conversions.go:8:6:8:6 | assignment to a |
|
||||||
| conversions.go:5:28:5:29 | block statement | conversions.go:5:28:5:29 | arg:0 block statement |
|
| conversions.go:10:2:10:2 | assignment to b | conversions.go:11:2:11:4 | use |
|
||||||
| conversions.go:5:28:5:29 | param-init:0 block statement | conversions.go:5:28:5:29 | After block statement |
|
| conversions.go:10:2:10:2 | skip | conversions.go:10:7:10:16 | selection of Add |
|
||||||
| conversions.go:7:1:26:1 | After function declaration | conversions.go:0:0:0:0 | After conversions.go |
|
| conversions.go:10:7:10:16 | selection of Add | conversions.go:10:18:10:18 | a |
|
||||||
| conversions.go:7:1:26:1 | Before function declaration | conversions.go:7:1:26:1 | function declaration |
|
| conversions.go:10:7:10:23 | call to Add | conversions.go:10:2:10:2 | assignment to b |
|
||||||
| conversions.go:7:1:26:1 | Entry | conversions.go:7:13:26:1 | block statement |
|
| conversions.go:10:18:10:18 | a | conversions.go:10:21:10:22 | 10 |
|
||||||
| conversions.go:7:1:26:1 | Exceptional Exit | conversions.go:7:1:26:1 | Exit |
|
| conversions.go:10:21:10:22 | 10 | conversions.go:10:7:10:23 | call to Add |
|
||||||
| conversions.go:7:1:26:1 | Normal Exit | conversions.go:7:1:26:1 | Exit |
|
| conversions.go:11:2:11:4 | use | conversions.go:11:6:11:6 | b |
|
||||||
| conversions.go:7:1:26:1 | function declaration | conversions.go:7:1:26:1 | After function declaration |
|
| conversions.go:11:2:11:7 | call to use | conversions.go:7:1:26:1 | exit |
|
||||||
| conversions.go:7:13:26:1 | After block statement | conversions.go:7:1:26:1 | Normal Exit |
|
| conversions.go:11:2:11:7 | call to use | conversions.go:13:6:13:8 | skip |
|
||||||
| conversions.go:7:13:26:1 | block statement | conversions.go:8:2:8:21 | declaration statement |
|
| conversions.go:11:6:11:6 | b | conversions.go:11:2:11:7 | call to use |
|
||||||
| conversions.go:8:2:8:21 | After declaration statement | conversions.go:10:2:10:23 | ... := ... |
|
| conversions.go:13:6:13:8 | assignment to arr | conversions.go:14:2:14:6 | skip |
|
||||||
| conversions.go:8:2:8:21 | After variable declaration | conversions.go:8:2:8:21 | After declaration statement |
|
| conversions.go:13:6:13:8 | skip | conversions.go:13:6:13:8 | zero value for arr |
|
||||||
| conversions.go:8:2:8:21 | declaration statement | conversions.go:8:2:8:21 | variable declaration |
|
| conversions.go:13:6:13:8 | zero value for arr | conversions.go:13:6:13:8 | assignment to arr |
|
||||||
| conversions.go:8:2:8:21 | variable declaration | conversions.go:8:6:8:21 | value declaration specifier |
|
| conversions.go:14:2:14:6 | assignment to slice | conversions.go:17:2:17:4 | skip |
|
||||||
| conversions.go:8:6:8:21 | After value declaration specifier | conversions.go:8:2:8:21 | After variable declaration |
|
| conversions.go:14:2:14:6 | skip | conversions.go:14:11:14:22 | selection of Slice |
|
||||||
| conversions.go:8:6:8:21 | assign:0 value declaration specifier | conversions.go:8:6:8:21 | After value declaration specifier |
|
| conversions.go:14:11:14:22 | selection of Slice | conversions.go:14:24:14:26 | arr |
|
||||||
| conversions.go:8:6:8:21 | value declaration specifier | conversions.go:8:6:8:21 | zero-init:0 value declaration specifier |
|
| conversions.go:14:11:14:31 | call to Slice | conversions.go:14:2:14:6 | assignment to slice |
|
||||||
| conversions.go:8:6:8:21 | zero-init:0 value declaration specifier | conversions.go:8:6:8:21 | assign:0 value declaration specifier |
|
| conversions.go:14:24:14:26 | arr | conversions.go:14:29:14:30 | 20 |
|
||||||
| conversions.go:10:2:10:23 | ... := ... | conversions.go:10:7:10:23 | Before call to Add |
|
| conversions.go:14:29:14:30 | 20 | conversions.go:14:11:14:31 | call to Slice |
|
||||||
| conversions.go:10:2:10:23 | After ... := ... | conversions.go:11:2:11:7 | expression statement |
|
| conversions.go:17:2:17:4 | assignment to ptr | conversions.go:18:2:18:4 | use |
|
||||||
| conversions.go:10:2:10:23 | assign:0 ... := ... | conversions.go:10:2:10:23 | After ... := ... |
|
| conversions.go:17:2:17:4 | skip | conversions.go:17:20:17:24 | slice |
|
||||||
| conversions.go:10:7:10:16 | After selection of Add | conversions.go:10:18:10:18 | Before a |
|
| conversions.go:17:9:17:25 | type conversion | conversions.go:7:1:26:1 | exit |
|
||||||
| conversions.go:10:7:10:16 | Before selection of Add | conversions.go:10:7:10:16 | selection of Add |
|
| conversions.go:17:9:17:25 | type conversion | conversions.go:17:2:17:4 | assignment to ptr |
|
||||||
| conversions.go:10:7:10:16 | selection of Add | conversions.go:10:7:10:16 | After selection of Add |
|
| conversions.go:17:20:17:24 | slice | conversions.go:17:9:17:25 | type conversion |
|
||||||
| conversions.go:10:7:10:23 | After call to Add | conversions.go:10:2:10:23 | assign:0 ... := ... |
|
| conversions.go:18:2:18:4 | use | conversions.go:18:6:18:8 | ptr |
|
||||||
| conversions.go:10:7:10:23 | Before call to Add | conversions.go:10:7:10:16 | Before selection of Add |
|
| conversions.go:18:2:18:9 | call to use | conversions.go:7:1:26:1 | exit |
|
||||||
| conversions.go:10:7:10:23 | call to Add | conversions.go:10:7:10:23 | After call to Add |
|
| conversions.go:18:2:18:9 | call to use | conversions.go:21:2:21:4 | skip |
|
||||||
| conversions.go:10:18:10:18 | After a | conversions.go:10:21:10:22 | Before 10 |
|
| conversions.go:18:6:18:8 | ptr | conversions.go:18:2:18:9 | call to use |
|
||||||
| conversions.go:10:18:10:18 | Before a | conversions.go:10:18:10:18 | a |
|
| conversions.go:21:2:21:4 | assignment to str | conversions.go:22:2:22:6 | skip |
|
||||||
| conversions.go:10:18:10:18 | a | conversions.go:10:18:10:18 | After a |
|
| conversions.go:21:2:21:4 | skip | conversions.go:21:9:21:18 | "a string" |
|
||||||
| conversions.go:10:21:10:22 | 10 | conversions.go:10:21:10:22 | After 10 |
|
| conversions.go:21:9:21:18 | "a string" | conversions.go:21:2:21:4 | assignment to str |
|
||||||
| conversions.go:10:21:10:22 | After 10 | conversions.go:10:7:10:23 | call to Add |
|
| conversions.go:22:2:22:6 | assignment to bytes | conversions.go:23:2:23:4 | use |
|
||||||
| conversions.go:10:21:10:22 | Before 10 | conversions.go:10:21:10:22 | 10 |
|
| conversions.go:22:2:22:6 | skip | conversions.go:22:18:22:20 | str |
|
||||||
| conversions.go:11:2:11:4 | After use | conversions.go:11:6:11:6 | Before b |
|
| conversions.go:22:11:22:21 | type conversion | conversions.go:22:2:22:6 | assignment to bytes |
|
||||||
| conversions.go:11:2:11:4 | Before use | conversions.go:11:2:11:4 | use |
|
| conversions.go:22:18:22:20 | str | conversions.go:22:11:22:21 | type conversion |
|
||||||
| conversions.go:11:2:11:4 | use | conversions.go:11:2:11:4 | After use |
|
| conversions.go:23:2:23:4 | use | conversions.go:23:6:23:10 | bytes |
|
||||||
| conversions.go:11:2:11:7 | After call to use | conversions.go:11:2:11:7 | After expression statement |
|
| conversions.go:23:2:23:11 | call to use | conversions.go:7:1:26:1 | exit |
|
||||||
| conversions.go:11:2:11:7 | After expression statement | conversions.go:13:2:13:13 | declaration statement |
|
| conversions.go:23:2:23:11 | call to use | conversions.go:24:2:24:6 | skip |
|
||||||
| conversions.go:11:2:11:7 | Before call to use | conversions.go:11:2:11:4 | Before use |
|
| conversions.go:23:6:23:10 | bytes | conversions.go:23:2:23:11 | call to use |
|
||||||
| conversions.go:11:2:11:7 | call to use | conversions.go:7:1:26:1 | Exceptional Exit |
|
| conversions.go:24:2:24:6 | assignment to runes | conversions.go:25:2:25:4 | use |
|
||||||
| conversions.go:11:2:11:7 | call to use | conversions.go:11:2:11:7 | After call to use |
|
| conversions.go:24:2:24:6 | skip | conversions.go:24:18:24:20 | str |
|
||||||
| conversions.go:11:2:11:7 | expression statement | conversions.go:11:2:11:7 | Before call to use |
|
| conversions.go:24:11:24:21 | type conversion | conversions.go:24:2:24:6 | assignment to runes |
|
||||||
| conversions.go:11:6:11:6 | After b | conversions.go:11:2:11:7 | call to use |
|
| conversions.go:24:18:24:20 | str | conversions.go:24:11:24:21 | type conversion |
|
||||||
| conversions.go:11:6:11:6 | Before b | conversions.go:11:6:11:6 | b |
|
| conversions.go:25:2:25:4 | use | conversions.go:25:6:25:10 | runes |
|
||||||
| conversions.go:11:6:11:6 | b | conversions.go:11:6:11:6 | After b |
|
| conversions.go:25:2:25:11 | call to use | conversions.go:7:1:26:1 | exit |
|
||||||
| conversions.go:13:2:13:13 | After declaration statement | conversions.go:14:2:14:31 | ... := ... |
|
| conversions.go:25:6:25:10 | runes | conversions.go:25:2:25:11 | call to use |
|
||||||
| conversions.go:13:2:13:13 | After variable declaration | conversions.go:13:2:13:13 | After declaration statement |
|
|
||||||
| conversions.go:13:2:13:13 | declaration statement | conversions.go:13:2:13:13 | variable declaration |
|
|
||||||
| conversions.go:13:2:13:13 | variable declaration | conversions.go:13:6:13:13 | value declaration specifier |
|
|
||||||
| conversions.go:13:6:13:13 | After value declaration specifier | conversions.go:13:2:13:13 | After variable declaration |
|
|
||||||
| conversions.go:13:6:13:13 | assign:0 value declaration specifier | conversions.go:13:6:13:13 | After value declaration specifier |
|
|
||||||
| conversions.go:13:6:13:13 | value declaration specifier | conversions.go:13:6:13:13 | zero-init:0 value declaration specifier |
|
|
||||||
| conversions.go:13:6:13:13 | zero-init:0 value declaration specifier | conversions.go:13:6:13:13 | assign:0 value declaration specifier |
|
|
||||||
| conversions.go:14:2:14:31 | ... := ... | conversions.go:14:11:14:31 | Before call to Slice |
|
|
||||||
| conversions.go:14:2:14:31 | After ... := ... | conversions.go:17:2:17:25 | ... := ... |
|
|
||||||
| conversions.go:14:2:14:31 | assign:0 ... := ... | conversions.go:14:2:14:31 | After ... := ... |
|
|
||||||
| conversions.go:14:11:14:22 | After selection of Slice | conversions.go:14:24:14:26 | Before arr |
|
|
||||||
| conversions.go:14:11:14:22 | Before selection of Slice | conversions.go:14:11:14:22 | selection of Slice |
|
|
||||||
| conversions.go:14:11:14:22 | selection of Slice | conversions.go:14:11:14:22 | After selection of Slice |
|
|
||||||
| conversions.go:14:11:14:31 | After call to Slice | conversions.go:14:2:14:31 | assign:0 ... := ... |
|
|
||||||
| conversions.go:14:11:14:31 | Before call to Slice | conversions.go:14:11:14:22 | Before selection of Slice |
|
|
||||||
| conversions.go:14:11:14:31 | call to Slice | conversions.go:14:11:14:31 | After call to Slice |
|
|
||||||
| conversions.go:14:24:14:26 | After arr | conversions.go:14:29:14:30 | Before 20 |
|
|
||||||
| conversions.go:14:24:14:26 | Before arr | conversions.go:14:24:14:26 | arr |
|
|
||||||
| conversions.go:14:24:14:26 | arr | conversions.go:14:24:14:26 | After arr |
|
|
||||||
| conversions.go:14:29:14:30 | 20 | conversions.go:14:29:14:30 | After 20 |
|
|
||||||
| conversions.go:14:29:14:30 | After 20 | conversions.go:14:11:14:31 | call to Slice |
|
|
||||||
| conversions.go:14:29:14:30 | Before 20 | conversions.go:14:29:14:30 | 20 |
|
|
||||||
| conversions.go:17:2:17:25 | ... := ... | conversions.go:17:9:17:25 | Before type conversion |
|
|
||||||
| conversions.go:17:2:17:25 | After ... := ... | conversions.go:18:2:18:9 | expression statement |
|
|
||||||
| conversions.go:17:2:17:25 | assign:0 ... := ... | conversions.go:17:2:17:25 | After ... := ... |
|
|
||||||
| conversions.go:17:9:17:25 | After type conversion | conversions.go:17:2:17:25 | assign:0 ... := ... |
|
|
||||||
| conversions.go:17:9:17:25 | Before type conversion | conversions.go:17:20:17:24 | Before slice |
|
|
||||||
| conversions.go:17:9:17:25 | type conversion | conversions.go:7:1:26:1 | Exceptional Exit |
|
|
||||||
| conversions.go:17:9:17:25 | type conversion | conversions.go:17:9:17:25 | After type conversion |
|
|
||||||
| conversions.go:17:20:17:24 | After slice | conversions.go:17:9:17:25 | type conversion |
|
|
||||||
| conversions.go:17:20:17:24 | Before slice | conversions.go:17:20:17:24 | slice |
|
|
||||||
| conversions.go:17:20:17:24 | slice | conversions.go:17:20:17:24 | After slice |
|
|
||||||
| conversions.go:18:2:18:4 | After use | conversions.go:18:6:18:8 | Before ptr |
|
|
||||||
| conversions.go:18:2:18:4 | Before use | conversions.go:18:2:18:4 | use |
|
|
||||||
| conversions.go:18:2:18:4 | use | conversions.go:18:2:18:4 | After use |
|
|
||||||
| conversions.go:18:2:18:9 | After call to use | conversions.go:18:2:18:9 | After expression statement |
|
|
||||||
| conversions.go:18:2:18:9 | After expression statement | conversions.go:21:2:21:18 | ... := ... |
|
|
||||||
| conversions.go:18:2:18:9 | Before call to use | conversions.go:18:2:18:4 | Before use |
|
|
||||||
| conversions.go:18:2:18:9 | call to use | conversions.go:7:1:26:1 | Exceptional Exit |
|
|
||||||
| conversions.go:18:2:18:9 | call to use | conversions.go:18:2:18:9 | After call to use |
|
|
||||||
| conversions.go:18:2:18:9 | expression statement | conversions.go:18:2:18:9 | Before call to use |
|
|
||||||
| conversions.go:18:6:18:8 | After ptr | conversions.go:18:2:18:9 | call to use |
|
|
||||||
| conversions.go:18:6:18:8 | Before ptr | conversions.go:18:6:18:8 | ptr |
|
|
||||||
| conversions.go:18:6:18:8 | ptr | conversions.go:18:6:18:8 | After ptr |
|
|
||||||
| conversions.go:21:2:21:18 | ... := ... | conversions.go:21:9:21:18 | Before "a string" |
|
|
||||||
| conversions.go:21:2:21:18 | After ... := ... | conversions.go:22:2:22:21 | ... := ... |
|
|
||||||
| conversions.go:21:2:21:18 | assign:0 ... := ... | conversions.go:21:2:21:18 | After ... := ... |
|
|
||||||
| conversions.go:21:9:21:18 | "a string" | conversions.go:21:9:21:18 | After "a string" |
|
|
||||||
| conversions.go:21:9:21:18 | After "a string" | conversions.go:21:2:21:18 | assign:0 ... := ... |
|
|
||||||
| conversions.go:21:9:21:18 | Before "a string" | conversions.go:21:9:21:18 | "a string" |
|
|
||||||
| conversions.go:22:2:22:21 | ... := ... | conversions.go:22:11:22:21 | Before type conversion |
|
|
||||||
| conversions.go:22:2:22:21 | After ... := ... | conversions.go:23:2:23:11 | expression statement |
|
|
||||||
| conversions.go:22:2:22:21 | assign:0 ... := ... | conversions.go:22:2:22:21 | After ... := ... |
|
|
||||||
| conversions.go:22:11:22:21 | After type conversion | conversions.go:22:2:22:21 | assign:0 ... := ... |
|
|
||||||
| conversions.go:22:11:22:21 | Before type conversion | conversions.go:22:18:22:20 | Before str |
|
|
||||||
| conversions.go:22:11:22:21 | type conversion | conversions.go:22:11:22:21 | After type conversion |
|
|
||||||
| conversions.go:22:18:22:20 | After str | conversions.go:22:11:22:21 | type conversion |
|
|
||||||
| conversions.go:22:18:22:20 | Before str | conversions.go:22:18:22:20 | str |
|
|
||||||
| conversions.go:22:18:22:20 | str | conversions.go:22:18:22:20 | After str |
|
|
||||||
| conversions.go:23:2:23:4 | After use | conversions.go:23:6:23:10 | Before bytes |
|
|
||||||
| conversions.go:23:2:23:4 | Before use | conversions.go:23:2:23:4 | use |
|
|
||||||
| conversions.go:23:2:23:4 | use | conversions.go:23:2:23:4 | After use |
|
|
||||||
| conversions.go:23:2:23:11 | After call to use | conversions.go:23:2:23:11 | After expression statement |
|
|
||||||
| conversions.go:23:2:23:11 | After expression statement | conversions.go:24:2:24:21 | ... := ... |
|
|
||||||
| conversions.go:23:2:23:11 | Before call to use | conversions.go:23:2:23:4 | Before use |
|
|
||||||
| conversions.go:23:2:23:11 | call to use | conversions.go:7:1:26:1 | Exceptional Exit |
|
|
||||||
| conversions.go:23:2:23:11 | call to use | conversions.go:23:2:23:11 | After call to use |
|
|
||||||
| conversions.go:23:2:23:11 | expression statement | conversions.go:23:2:23:11 | Before call to use |
|
|
||||||
| conversions.go:23:6:23:10 | After bytes | conversions.go:23:2:23:11 | call to use |
|
|
||||||
| conversions.go:23:6:23:10 | Before bytes | conversions.go:23:6:23:10 | bytes |
|
|
||||||
| conversions.go:23:6:23:10 | bytes | conversions.go:23:6:23:10 | After bytes |
|
|
||||||
| conversions.go:24:2:24:21 | ... := ... | conversions.go:24:11:24:21 | Before type conversion |
|
|
||||||
| conversions.go:24:2:24:21 | After ... := ... | conversions.go:25:2:25:11 | expression statement |
|
|
||||||
| conversions.go:24:2:24:21 | assign:0 ... := ... | conversions.go:24:2:24:21 | After ... := ... |
|
|
||||||
| conversions.go:24:11:24:21 | After type conversion | conversions.go:24:2:24:21 | assign:0 ... := ... |
|
|
||||||
| conversions.go:24:11:24:21 | Before type conversion | conversions.go:24:18:24:20 | Before str |
|
|
||||||
| conversions.go:24:11:24:21 | type conversion | conversions.go:24:11:24:21 | After type conversion |
|
|
||||||
| conversions.go:24:18:24:20 | After str | conversions.go:24:11:24:21 | type conversion |
|
|
||||||
| conversions.go:24:18:24:20 | Before str | conversions.go:24:18:24:20 | str |
|
|
||||||
| conversions.go:24:18:24:20 | str | conversions.go:24:18:24:20 | After str |
|
|
||||||
| conversions.go:25:2:25:4 | After use | conversions.go:25:6:25:10 | Before runes |
|
|
||||||
| conversions.go:25:2:25:4 | Before use | conversions.go:25:2:25:4 | use |
|
|
||||||
| conversions.go:25:2:25:4 | use | conversions.go:25:2:25:4 | After use |
|
|
||||||
| conversions.go:25:2:25:11 | After call to use | conversions.go:25:2:25:11 | After expression statement |
|
|
||||||
| conversions.go:25:2:25:11 | After expression statement | conversions.go:7:13:26:1 | After block statement |
|
|
||||||
| conversions.go:25:2:25:11 | Before call to use | conversions.go:25:2:25:4 | Before use |
|
|
||||||
| conversions.go:25:2:25:11 | call to use | conversions.go:7:1:26:1 | Exceptional Exit |
|
|
||||||
| conversions.go:25:2:25:11 | call to use | conversions.go:25:2:25:11 | After call to use |
|
|
||||||
| conversions.go:25:2:25:11 | expression statement | conversions.go:25:2:25:11 | Before call to use |
|
|
||||||
| conversions.go:25:6:25:10 | After runes | conversions.go:25:2:25:11 | call to use |
|
|
||||||
| conversions.go:25:6:25:10 | Before runes | conversions.go:25:6:25:10 | runes |
|
|
||||||
| conversions.go:25:6:25:10 | runes | conversions.go:25:6:25:10 | After runes |
|
|
||||||
#select
|
#select
|
||||||
| |
|
| |
|
||||||
|
|||||||
@@ -1,6 +1,10 @@
|
|||||||
| test.go:9:2:9:16 | extract:0 ... := ... | test.go:9:13:9:16 | <-... | 0 | file://:0:0:0:0 | bool |
|
| test.go:9:2:9:16 | ... := ...[0] | test.go:9:13:9:16 | <-... | 0 | file://:0:0:0:0 | bool |
|
||||||
| test.go:9:2:9:16 | extract:1 ... := ... | test.go:9:13:9:16 | <-... | 1 | file://:0:0:0:0 | bool |
|
| test.go:9:2:9:16 | ... := ...[1] | test.go:9:13:9:16 | <-... | 1 | file://:0:0:0:0 | bool |
|
||||||
| test.go:15:2:15:20 | extract:0 ... := ... | test.go:15:13:15:20 | index expression | 0 | file://:0:0:0:0 | string |
|
| test.go:15:2:15:20 | ... := ...[0] | test.go:15:13:15:20 | index expression | 0 | file://:0:0:0:0 | string |
|
||||||
| test.go:15:2:15:20 | extract:1 ... := ... | test.go:15:13:15:20 | index expression | 1 | file://:0:0:0:0 | bool |
|
| test.go:15:2:15:20 | ... := ...[1] | test.go:15:13:15:20 | index expression | 1 | file://:0:0:0:0 | bool |
|
||||||
| test.go:21:2:21:22 | extract:0 ... := ... | test.go:21:13:21:22 | type assertion | 0 | file://:0:0:0:0 | string |
|
| test.go:21:2:21:22 | ... := ...[0] | test.go:21:13:21:22 | type assertion | 0 | file://:0:0:0:0 | string |
|
||||||
| test.go:21:2:21:22 | extract:1 ... := ... | test.go:21:13:21:22 | type assertion | 1 | file://:0:0:0:0 | bool |
|
| test.go:21:2:21:22 | ... := ...[1] | test.go:21:13:21:22 | type assertion | 1 | file://:0:0:0:0 | bool |
|
||||||
|
| test.go:29:2:29:7 | call to f[0] | test.go:29:4:29:6 | call to g | 0 | file://:0:0:0:0 | int |
|
||||||
|
| test.go:29:2:29:7 | call to f[1] | test.go:29:4:29:6 | call to g | 1 | file://:0:0:0:0 | int |
|
||||||
|
| test.go:33:2:33:7 | call to f[0] | test.go:33:4:33:6 | call to v | 0 | file://:0:0:0:0 | int |
|
||||||
|
| test.go:33:2:33:7 | call to f[1] | test.go:33:4:33:6 | call to v | 1 | file://:0:0:0:0 | int |
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
| main.go:6:2:6:2 | x | main.go:24:2:24:9 | increment statement |
|
| main.go:6:2:6:2 | x | main.go:24:2:24:9 | increment statement |
|
||||||
| main.go:13:7:13:10 | recv | main.go:13:27:15:1 | param-init:-1 block statement |
|
| main.go:13:7:13:10 | recv | main.go:13:7:13:10 | initialization of recv |
|
||||||
| main.go:17:10:17:10 | x | main.go:17:32:21:1 | param-init:0 block statement |
|
| main.go:17:10:17:10 | x | main.go:17:10:17:10 | initialization of x |
|
||||||
| main.go:17:26:17:26 | y | main.go:17:32:21:1 | param-init:1 block statement |
|
| main.go:17:26:17:26 | y | main.go:17:26:17:26 | initialization of y |
|
||||||
| main.go:23:7:23:10 | recv | main.go:23:23:25:1 | param-init:-1 block statement |
|
| main.go:23:7:23:10 | recv | main.go:23:7:23:10 | initialization of recv |
|
||||||
| types.go:33:22:33:22 | a | types.go:33:34:35:1 | param-init:0 block statement |
|
| types.go:33:22:33:22 | a | types.go:33:22:33:22 | initialization of a |
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ func logSomething(entry *logrus.Entry) {
|
|||||||
entry.Traceln(text) // $ logger=text
|
entry.Traceln(text) // $ logger=text
|
||||||
}
|
}
|
||||||
|
|
||||||
func logrusCalls(selector int) {
|
func logrusCalls() {
|
||||||
err := errors.New("Error")
|
err := errors.New("Error")
|
||||||
var fields logrus.Fields = nil
|
var fields logrus.Fields = nil
|
||||||
var fn logrus.LogFunction = nil
|
var fn logrus.LogFunction = nil
|
||||||
@@ -27,15 +27,11 @@ func logrusCalls(selector int) {
|
|||||||
tmp = logrus.WithFields(fields) // $ logger=fields
|
tmp = logrus.WithFields(fields) // $ logger=fields
|
||||||
logSomething(tmp)
|
logSomething(tmp)
|
||||||
|
|
||||||
logrus.Error(text) // $ logger=text
|
logrus.Error(text) // $ logger=text
|
||||||
logrus.Infof(fmt, text) // $ logger=fmt logger=text
|
logrus.Fatalf(fmt, text) // $ logger=fmt logger=text
|
||||||
if selector == 0 {
|
logrus.Panicln(text) // $ logger=text
|
||||||
logrus.Fatalf(fmt, text) // $ logger=fmt logger=text
|
logrus.Infof(fmt, text) // $ logger=fmt logger=text
|
||||||
} else if selector == 1 {
|
logrus.FatalFn(fn) // $ logger=fn
|
||||||
logrus.Panicln(text) // $ logger=text
|
|
||||||
} else if selector == 2 {
|
|
||||||
logrus.FatalFn(fn) // $ logger=fn
|
|
||||||
}
|
|
||||||
|
|
||||||
// components corresponding to the format specifier "%T" are not considered vulnerable
|
// components corresponding to the format specifier "%T" are not considered vulnerable
|
||||||
logrus.Infof("%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
|
logrus.Infof("%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
|
||||||
|
|||||||
@@ -8,6 +8,6 @@ var v []byte
|
|||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
glogTest(len(v))
|
glogTest(len(v))
|
||||||
stdlib(len(v))
|
stdlib()
|
||||||
slogTest()
|
slogTest()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,69 +4,37 @@ import (
|
|||||||
"log"
|
"log"
|
||||||
)
|
)
|
||||||
|
|
||||||
func stdlib(selector int) {
|
func stdlib() {
|
||||||
var logger log.Logger
|
var logger log.Logger
|
||||||
logger.SetPrefix("prefix: ")
|
logger.SetPrefix("prefix: ")
|
||||||
switch selector {
|
logger.Fatal(text) // $ logger=text
|
||||||
case 0:
|
logger.Fatalf(fmt, text) // $ logger=fmt logger=text
|
||||||
logger.Fatal(text) // $ logger=text
|
logger.Fatalln(text) // $ logger=text
|
||||||
case 1:
|
logger.Panic(text) // $ logger=text
|
||||||
logger.Fatalf(fmt, text) // $ logger=fmt logger=text
|
logger.Panicf(fmt, text) // $ logger=fmt logger=text
|
||||||
case 2:
|
logger.Panicln(text) // $ logger=text
|
||||||
logger.Fatalln(text) // $ logger=text
|
logger.Print(text) // $ logger=text
|
||||||
case 3:
|
logger.Printf(fmt, text) // $ logger=fmt logger=text
|
||||||
logger.Panic(text) // $ logger=text
|
logger.Println(text) // $ logger=text
|
||||||
case 4:
|
|
||||||
logger.Panicf(fmt, text) // $ logger=fmt logger=text
|
|
||||||
case 5:
|
|
||||||
logger.Panicln(text) // $ logger=text
|
|
||||||
case 6:
|
|
||||||
logger.Print(text) // $ logger=text
|
|
||||||
case 7:
|
|
||||||
logger.Printf(fmt, text) // $ logger=fmt logger=text
|
|
||||||
case 8:
|
|
||||||
logger.Println(text) // $ logger=text
|
|
||||||
}
|
|
||||||
|
|
||||||
// components corresponding to the format specifier "%T" are not considered vulnerable
|
// components corresponding to the format specifier "%T" are not considered vulnerable
|
||||||
switch selector {
|
logger.Fatalf("%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
|
||||||
case 9:
|
logger.Panicf("%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
|
||||||
logger.Fatalf("%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
|
logger.Printf("%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
|
||||||
case 10:
|
|
||||||
logger.Panicf("%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
|
|
||||||
case 11:
|
|
||||||
logger.Printf("%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
|
|
||||||
}
|
|
||||||
|
|
||||||
log.SetPrefix("prefix: ")
|
log.SetPrefix("prefix: ")
|
||||||
switch selector {
|
log.Fatal(text) // $ logger=text
|
||||||
case 12:
|
log.Fatalf(fmt, text) // $ logger=fmt logger=text
|
||||||
log.Fatal(text) // $ logger=text
|
log.Fatalln(text) // $ logger=text
|
||||||
case 13:
|
log.Panic(text) // $ logger=text
|
||||||
log.Fatalf(fmt, text) // $ logger=fmt logger=text
|
log.Panicf(fmt, text) // $ logger=fmt logger=text
|
||||||
case 14:
|
log.Panicln(text) // $ logger=text
|
||||||
log.Fatalln(text) // $ logger=text
|
log.Print(text) // $ logger=text
|
||||||
case 15:
|
log.Printf(fmt, text) // $ logger=fmt logger=text
|
||||||
log.Panic(text) // $ logger=text
|
log.Println(text) // $ logger=text
|
||||||
case 16:
|
|
||||||
log.Panicf(fmt, text) // $ logger=fmt logger=text
|
|
||||||
case 17:
|
|
||||||
log.Panicln(text) // $ logger=text
|
|
||||||
case 18:
|
|
||||||
log.Print(text) // $ logger=text
|
|
||||||
case 19:
|
|
||||||
log.Printf(fmt, text) // $ logger=fmt logger=text
|
|
||||||
case 20:
|
|
||||||
log.Println(text) // $ logger=text
|
|
||||||
}
|
|
||||||
|
|
||||||
// components corresponding to the format specifier "%T" are not considered vulnerable
|
// components corresponding to the format specifier "%T" are not considered vulnerable
|
||||||
switch selector {
|
log.Fatalf("%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
|
||||||
case 21:
|
log.Panicf("%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
|
||||||
log.Fatalf("%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
|
log.Printf("%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
|
||||||
case 22:
|
|
||||||
log.Panicf("%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
|
|
||||||
case 23:
|
|
||||||
log.Printf("%s: found type %T", text, v) // $ logger="%s: found type %T" logger=text type-logger=v
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -1,4 +1,3 @@
|
|||||||
| epilogues.go:115:6:115:22 | epiRecoverUnnamed | github.com/github/codeql-go/ql/test/library-tests/semmle/go/controlflow/ControlFlowGraph.epiRecoverUnnamed |
|
|
||||||
| file://:0:0:0:0 | Exit | os.Exit |
|
| file://:0:0:0:0 | Exit | os.Exit |
|
||||||
| file://:0:0:0:0 | Fatal | log.Fatal |
|
| file://:0:0:0:0 | Fatal | log.Fatal |
|
||||||
| file://:0:0:0:0 | Fatal | log.Logger.Fatal |
|
| file://:0:0:0:0 | Fatal | log.Logger.Fatal |
|
||||||
@@ -19,3 +18,4 @@
|
|||||||
| stmts7.go:10:6:10:15 | canRecover | github.com/github/codeql-go/ql/test/library-tests/semmle/go/controlflow/ControlFlowGraph.canRecover |
|
| stmts7.go:10:6:10:15 | canRecover | github.com/github/codeql-go/ql/test/library-tests/semmle/go/controlflow/ControlFlowGraph.canRecover |
|
||||||
| stmts.go:10:6:10:10 | test5 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/controlflow/ControlFlowGraph.test5 |
|
| stmts.go:10:6:10:10 | test5 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/controlflow/ControlFlowGraph.test5 |
|
||||||
| stmts.go:46:6:46:10 | test6 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/controlflow/ControlFlowGraph.test6 |
|
| stmts.go:46:6:46:10 | test6 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/controlflow/ControlFlowGraph.test6 |
|
||||||
|
| stmts.go:112:6:112:10 | test9 | github.com/github/codeql-go/ql/test/library-tests/semmle/go/controlflow/ControlFlowGraph.test9 |
|
||||||
|
|||||||
@@ -1,118 +0,0 @@
|
|||||||
package main
|
|
||||||
|
|
||||||
import "fmt"
|
|
||||||
|
|
||||||
// epiLogger has methods with both pointer and value receivers, used to check
|
|
||||||
// that the receiver and arguments of a deferred call are evaluated at the
|
|
||||||
// `defer` statement rather than in the function epilogue.
|
|
||||||
type epiLogger struct {
|
|
||||||
prefix string
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l *epiLogger) log(msg string, code int) {
|
|
||||||
fmt.Println(l.prefix, msg, code)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (l epiLogger) logValue(msg string) {
|
|
||||||
fmt.Println(l.prefix, msg)
|
|
||||||
}
|
|
||||||
|
|
||||||
// epiRecover recovers from a panic. It is used as a deferred function so we can
|
|
||||||
// check that control flow returns to the result-read nodes and the normal exit
|
|
||||||
// node after recovering.
|
|
||||||
func epiRecover() {
|
|
||||||
if r := recover(); r != nil {
|
|
||||||
fmt.Println("recovered:", r)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// epiPlain has no named result variable and a single `return` with a child
|
|
||||||
// expression.
|
|
||||||
func epiPlain(x int) int {
|
|
||||||
return x * 2
|
|
||||||
}
|
|
||||||
|
|
||||||
// epiVoid has no named result variable and no `return` statement at all.
|
|
||||||
func epiVoid() {
|
|
||||||
fmt.Println("void")
|
|
||||||
}
|
|
||||||
|
|
||||||
// epiNamedMixed has named result variables and a mix of a bare `return` (no
|
|
||||||
// child expressions) and a `return` with child expressions.
|
|
||||||
func epiNamedMixed(x int) (result int, err error) {
|
|
||||||
if x < 0 {
|
|
||||||
result = -x
|
|
||||||
return
|
|
||||||
}
|
|
||||||
return x, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// epiNamedBareOnly has a named result variable and only a bare `return`.
|
|
||||||
func epiNamedBareOnly(x int) (n int) {
|
|
||||||
n = x + 1
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// epiDeferReceiverArgs has a deferred call with a (pointer) receiver and
|
|
||||||
// arguments that are expressions, so we can check the receiver `l` and the
|
|
||||||
// arguments `"count"` and `len(items)` are evaluated at the `defer` statement.
|
|
||||||
func epiDeferReceiverArgs(l *epiLogger, items []int) {
|
|
||||||
defer l.log("count", len(items))
|
|
||||||
fmt.Println("processing", len(items))
|
|
||||||
}
|
|
||||||
|
|
||||||
// epiDeferValueReceiver has deferred calls with a value receiver and an
|
|
||||||
// address-of receiver, both with arguments evaluated at the `defer` statement.
|
|
||||||
func epiDeferValueReceiver(prefix string) {
|
|
||||||
l := epiLogger{prefix: prefix}
|
|
||||||
defer l.logValue("bye")
|
|
||||||
defer (&l).log("ptr", 7)
|
|
||||||
fmt.Println("body")
|
|
||||||
}
|
|
||||||
|
|
||||||
// epiDeferFuncLit has a deferred function literal with parameters, so we can
|
|
||||||
// check that the arguments `"done"` and `x+1` are evaluated at the `defer`
|
|
||||||
// statement and that control flow enters the function literal body when it is
|
|
||||||
// invoked at the function epilogue.
|
|
||||||
func epiDeferFuncLit(x int) {
|
|
||||||
defer func(label string, n int) {
|
|
||||||
fmt.Println(label, n)
|
|
||||||
}("done", x+1)
|
|
||||||
fmt.Println("body", x)
|
|
||||||
}
|
|
||||||
|
|
||||||
// epiRecoverNamed has a named result variable and a deferred closure containing
|
|
||||||
// `recover()`. After recovering on the panic path, control flow should return
|
|
||||||
// to the result-read nodes and the normal exit node.
|
|
||||||
func epiRecoverNamed(x int) (result int) {
|
|
||||||
defer func() {
|
|
||||||
if r := recover(); r != nil {
|
|
||||||
result = -1
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
if x < 0 {
|
|
||||||
panic("neg")
|
|
||||||
}
|
|
||||||
result = x * x
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
// epiRecoverNamedBare has named result variables, a deferred function
|
|
||||||
// containing `recover()`, and only bare `return` statements.
|
|
||||||
func epiRecoverNamedBare(x int) (ok bool, n int) {
|
|
||||||
defer epiRecover()
|
|
||||||
if x == 0 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
n = x
|
|
||||||
ok = true
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// epiRecoverUnnamed has no named result variables and a deferred function
|
|
||||||
// containing `recover()`; after recovering, control flow should reach the
|
|
||||||
// normal exit node directly (there are no result-read nodes).
|
|
||||||
func epiRecoverUnnamed() {
|
|
||||||
defer epiRecover()
|
|
||||||
panic("boom")
|
|
||||||
}
|
|
||||||
@@ -4,9 +4,9 @@ invalidModelRow
|
|||||||
| test.go:40:8:40:15 | call to Src2 | qltest |
|
| test.go:40:8:40:15 | call to Src2 | qltest |
|
||||||
| test.go:40:8:40:15 | call to Src2 | qltest-w-subtypes |
|
| test.go:40:8:40:15 | call to Src2 | qltest-w-subtypes |
|
||||||
| test.go:41:8:41:16 | call to Src2 | qltest-w-subtypes |
|
| test.go:41:8:41:16 | call to Src2 | qltest-w-subtypes |
|
||||||
| test.go:42:2:42:21 | extract:0 ... = ... | qltest |
|
| test.go:42:2:42:21 | ... = ...[0] | qltest |
|
||||||
| test.go:42:2:42:21 | extract:1 ... = ... | qltest-w-subtypes |
|
| test.go:42:2:42:21 | ... = ...[1] | qltest-w-subtypes |
|
||||||
| test.go:43:2:43:22 | extract:1 ... = ... | qltest-w-subtypes |
|
| test.go:43:2:43:22 | ... = ...[1] | qltest-w-subtypes |
|
||||||
| test.go:44:11:44:13 | arg [postupdate] | qltest-arg |
|
| test.go:44:11:44:13 | arg [postupdate] | qltest-arg |
|
||||||
| test.go:59:9:59:16 | call to Src1 | qltest |
|
| test.go:59:9:59:16 | call to Src1 | qltest |
|
||||||
| test.go:102:46:102:53 | call to Src1 | qltest |
|
| test.go:102:46:102:53 | call to Src1 | qltest |
|
||||||
@@ -22,4 +22,4 @@ invalidModelRow
|
|||||||
| test.go:187:24:187:31 | call to Src1 | qltest |
|
| test.go:187:24:187:31 | call to Src1 | qltest |
|
||||||
| test.go:191:24:191:31 | call to Src1 | qltest |
|
| test.go:191:24:191:31 | call to Src1 | qltest |
|
||||||
| test.go:209:10:209:28 | selection of SourceVariable | qltest |
|
| test.go:209:10:209:28 | selection of SourceVariable | qltest |
|
||||||
| test.go:216:37:218:1 | SSA def(src) | qltest |
|
| test.go:216:15:216:17 | SSA def(src) | qltest |
|
||||||
|
|||||||
@@ -1,14 +1,14 @@
|
|||||||
invalidModelRow
|
invalidModelRow
|
||||||
#select
|
#select
|
||||||
| test.go:17:23:17:25 | arg | test.go:17:10:17:26 | call to StepArgRes |
|
| test.go:17:23:17:25 | arg | test.go:17:10:17:26 | call to StepArgRes |
|
||||||
| test.go:18:27:18:29 | arg | test.go:18:2:18:30 | extract:1 ... = ... |
|
| test.go:18:27:18:29 | arg | test.go:18:2:18:30 | ... = ...[1] |
|
||||||
| test.go:19:15:19:17 | arg | test.go:19:20:19:23 | arg1 [postupdate] |
|
| test.go:19:15:19:17 | arg | test.go:19:20:19:23 | arg1 [postupdate] |
|
||||||
| test.go:21:16:21:18 | arg | test.go:21:2:21:2 | t [postupdate] |
|
| test.go:21:16:21:18 | arg | test.go:21:2:21:2 | t [postupdate] |
|
||||||
| test.go:22:10:22:10 | t | test.go:22:10:22:24 | call to StepQualRes |
|
| test.go:22:10:22:10 | t | test.go:22:10:22:24 | call to StepQualRes |
|
||||||
| test.go:23:2:23:2 | t | test.go:23:16:23:18 | arg [postupdate] |
|
| test.go:23:2:23:2 | t | test.go:23:16:23:18 | arg [postupdate] |
|
||||||
| test.go:24:32:24:34 | arg | test.go:24:10:24:35 | call to StepArgResNoQual |
|
| test.go:24:32:24:34 | arg | test.go:24:10:24:35 | call to StepArgResNoQual |
|
||||||
| test.go:61:25:61:27 | src | test.go:61:12:61:28 | call to StepArgRes |
|
| test.go:61:25:61:27 | src | test.go:61:12:61:28 | call to StepArgRes |
|
||||||
| test.go:64:29:64:31 | src | test.go:64:2:64:32 | extract:1 ... := ... |
|
| test.go:64:29:64:31 | src | test.go:64:2:64:32 | ... := ...[1] |
|
||||||
| test.go:68:15:68:17 | src | test.go:68:20:68:25 | taint3 [postupdate] |
|
| test.go:68:15:68:17 | src | test.go:68:20:68:25 | taint3 [postupdate] |
|
||||||
| test.go:76:21:76:23 | src | test.go:76:2:76:7 | taint4 [postupdate] |
|
| test.go:76:21:76:23 | src | test.go:76:2:76:7 | taint4 [postupdate] |
|
||||||
| test.go:79:13:79:25 | type assertion | test.go:79:12:79:40 | call to StepQualRes |
|
| test.go:79:13:79:25 | type assertion | test.go:79:12:79:40 | call to StepQualRes |
|
||||||
|
|||||||
@@ -1,40 +1,42 @@
|
|||||||
| main.go:6:2:6:5 | implicit-one increment statement | main.go:14:7:14:7 | 1 |
|
| main.go:6:2:6:5 | 1 | main.go:14:7:14:7 | 1 |
|
||||||
| main.go:10:2:10:7 | SSA def(x) | main.go:10:7:10:7 | 0 |
|
| main.go:10:2:10:2 | SSA def(x) | main.go:10:7:10:7 | 0 |
|
||||||
| main.go:10:7:10:7 | 0 | main.go:10:7:10:7 | 0 |
|
| main.go:10:7:10:7 | 0 | main.go:10:7:10:7 | 0 |
|
||||||
| main.go:11:6:11:10 | SSA def(y) | main.go:10:7:10:7 | 0 |
|
| main.go:11:6:11:6 | SSA def(y) | main.go:10:7:10:7 | 0 |
|
||||||
| main.go:11:6:11:10 | zero-init:0 value declaration specifier | main.go:10:7:10:7 | 0 |
|
| main.go:11:6:11:6 | zero value for y | main.go:10:7:10:7 | 0 |
|
||||||
| main.go:12:2:12:18 | call to Println | main.go:12:2:12:18 | call to Println |
|
| main.go:12:2:12:18 | call to Println | main.go:12:2:12:18 | call to Println |
|
||||||
| main.go:12:14:12:14 | x | main.go:10:7:10:7 | 0 |
|
| main.go:12:14:12:14 | x | main.go:10:7:10:7 | 0 |
|
||||||
| main.go:12:17:12:17 | y | main.go:10:7:10:7 | 0 |
|
| main.go:12:17:12:17 | y | main.go:10:7:10:7 | 0 |
|
||||||
| main.go:14:2:14:7 | SSA def(z) | main.go:14:7:14:7 | 1 |
|
| main.go:14:2:14:2 | SSA def(z) | main.go:14:7:14:7 | 1 |
|
||||||
| main.go:14:7:14:7 | 1 | main.go:14:7:14:7 | 1 |
|
| main.go:14:7:14:7 | 1 | main.go:14:7:14:7 | 1 |
|
||||||
| main.go:15:2:15:9 | call to bump | main.go:15:2:15:9 | call to bump |
|
| main.go:15:2:15:9 | call to bump | main.go:15:2:15:9 | call to bump |
|
||||||
| main.go:16:2:16:21 | call to Println | main.go:16:2:16:21 | call to Println |
|
| main.go:16:2:16:21 | call to Println | main.go:16:2:16:21 | call to Println |
|
||||||
| main.go:16:14:16:14 | x | main.go:10:7:10:7 | 0 |
|
| main.go:16:14:16:14 | x | main.go:10:7:10:7 | 0 |
|
||||||
| main.go:16:17:16:17 | y | main.go:10:7:10:7 | 0 |
|
| main.go:16:17:16:17 | y | main.go:10:7:10:7 | 0 |
|
||||||
| main.go:18:2:18:24 | SSA def(ss) | main.go:18:8:18:24 | call to make |
|
| main.go:18:2:18:3 | SSA def(ss) | main.go:18:8:18:24 | call to make |
|
||||||
| main.go:18:8:18:24 | call to make | main.go:18:8:18:24 | call to make |
|
| main.go:18:8:18:24 | call to make | main.go:18:8:18:24 | call to make |
|
||||||
| main.go:18:23:18:23 | 3 | main.go:18:23:18:23 | 3 |
|
| main.go:18:23:18:23 | 3 | main.go:18:23:18:23 | 3 |
|
||||||
| main.go:19:5:19:5 | 2 | main.go:19:5:19:5 | 2 |
|
| main.go:19:5:19:5 | 2 | main.go:19:5:19:5 | 2 |
|
||||||
| main.go:19:10:19:24 | "Hello, world!" | main.go:19:10:19:24 | "Hello, world!" |
|
| main.go:19:10:19:24 | "Hello, world!" | main.go:19:10:19:24 | "Hello, world!" |
|
||||||
| main.go:20:2:20:16 | call to Println | main.go:20:2:20:16 | call to Println |
|
| main.go:20:2:20:16 | call to Println | main.go:20:2:20:16 | call to Println |
|
||||||
| main.go:23:23:26:1 | result-read:0 block statement | main.go:24:8:24:8 | 4 |
|
| main.go:23:14:23:16 | implicit read of res | main.go:24:8:24:8 | 4 |
|
||||||
| main.go:24:2:24:8 | SSA def(res) | main.go:24:8:24:8 | 4 |
|
| main.go:23:14:23:16 | zero value for res | main.go:10:7:10:7 | 0 |
|
||||||
|
| main.go:24:2:24:4 | SSA def(res) | main.go:24:8:24:8 | 4 |
|
||||||
| main.go:24:8:24:8 | 4 | main.go:24:8:24:8 | 4 |
|
| main.go:24:8:24:8 | 4 | main.go:24:8:24:8 | 4 |
|
||||||
| main.go:28:24:31:1 | result-read:0 block statement | main.go:29:8:29:8 | 5 |
|
| main.go:28:15:28:17 | implicit read of res | main.go:30:9:30:9 | 6 |
|
||||||
| main.go:29:2:29:8 | SSA def(res) | main.go:29:8:29:8 | 5 |
|
| main.go:28:15:28:17 | zero value for res | main.go:10:7:10:7 | 0 |
|
||||||
| main.go:29:8:29:8 | 5 | main.go:29:8:29:8 | 5 |
|
| main.go:29:8:29:8 | 5 | main.go:29:8:29:8 | 5 |
|
||||||
| main.go:30:9:30:9 | 6 | main.go:30:9:30:9 | 6 |
|
| main.go:30:9:30:9 | 6 | main.go:30:9:30:9 | 6 |
|
||||||
| main.go:34:2:34:8 | SSA def(res) | main.go:34:8:34:8 | 7 |
|
| main.go:30:9:30:9 | SSA def(res) | main.go:30:9:30:9 | 6 |
|
||||||
|
| main.go:33:15:33:17 | zero value for res | main.go:10:7:10:7 | 0 |
|
||||||
| main.go:34:8:34:8 | 7 | main.go:34:8:34:8 | 7 |
|
| main.go:34:8:34:8 | 7 | main.go:34:8:34:8 | 7 |
|
||||||
| main.go:35:8:37:4 | function call | main.go:35:8:37:4 | function call |
|
| main.go:35:8:37:4 | function call | main.go:35:8:37:4 | function call |
|
||||||
| main.go:36:3:36:9 | SSA def(res) | main.go:36:9:36:9 | 8 |
|
| main.go:36:3:36:5 | SSA def(res) | main.go:36:9:36:9 | 8 |
|
||||||
| main.go:36:9:36:9 | 8 | main.go:36:9:36:9 | 8 |
|
| main.go:36:9:36:9 | 8 | main.go:36:9:36:9 | 8 |
|
||||||
| main.go:38:9:38:9 | 9 | main.go:38:9:38:9 | 9 |
|
| main.go:38:9:38:9 | 9 | main.go:38:9:38:9 | 9 |
|
||||||
|
| main.go:38:9:38:9 | SSA def(res) | main.go:38:9:38:9 | 9 |
|
||||||
| regressions.go:5:11:5:31 | call to Sizeof | regressions.go:5:11:5:31 | call to Sizeof |
|
| regressions.go:5:11:5:31 | call to Sizeof | regressions.go:5:11:5:31 | call to Sizeof |
|
||||||
| regressions.go:5:25:5:30 | call to test | regressions.go:5:25:5:30 | call to test |
|
|
||||||
| regressions.go:7:11:7:15 | false | regressions.go:7:11:7:15 | false |
|
| regressions.go:7:11:7:15 | false | regressions.go:7:11:7:15 | false |
|
||||||
| regressions.go:9:12:9:12 | d | regressions.go:7:11:7:15 | false |
|
| regressions.go:9:11:9:12 | !... | regressions.go:11:11:11:14 | true |
|
||||||
| regressions.go:11:11:11:14 | true | regressions.go:11:11:11:14 | true |
|
| regressions.go:11:11:11:14 | true | regressions.go:11:11:11:14 | true |
|
||||||
| regressions.go:30:9:30:22 | call to getPayload | regressions.go:30:9:30:22 | call to getPayload |
|
| regressions.go:30:9:30:22 | call to getPayload | regressions.go:30:9:30:22 | call to getPayload |
|
||||||
| regressions.go:30:26:30:39 | call to getPayload | regressions.go:30:26:30:39 | call to getPayload |
|
| regressions.go:30:26:30:39 | call to getPayload | regressions.go:30:26:30:39 | call to getPayload |
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
| tst.go:19:10:19:14 | index expression | tst.go:19:10:19:11 | xs | tst.go:19:13:19:13 | 1 |
|
| tst.go:19:10:19:14 | index expression | tst.go:19:10:19:11 | xs | tst.go:19:13:19:13 | 1 |
|
||||||
| tst.go:20:10:20:14 | index expression | tst.go:20:10:20:11 | implicit-deref ps | tst.go:20:13:20:13 | 1 |
|
| tst.go:20:10:20:14 | index expression | tst.go:20:10:20:11 | implicit dereference | tst.go:20:13:20:13 | 1 |
|
||||||
| tst.go:20:10:20:14 | index expression | tst.go:20:10:20:11 | ps | tst.go:20:13:20:13 | 1 |
|
| tst.go:20:10:20:14 | index expression | tst.go:20:10:20:11 | ps | tst.go:20:13:20:13 | 1 |
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
| tst.go:8:8:8:10 | selection of f | tst.go:8:8:8:8 | implicit-deref t | tst.go:4:2:4:2 | f |
|
| tst.go:8:8:8:10 | selection of f | tst.go:8:8:8:8 | implicit dereference | tst.go:4:2:4:2 | f |
|
||||||
| tst.go:8:8:8:10 | selection of f | tst.go:8:8:8:8 | t | tst.go:4:2:4:2 | f |
|
| tst.go:8:8:8:10 | selection of f | tst.go:8:8:8:8 | t | tst.go:4:2:4:2 | f |
|
||||||
| tst.go:13:9:13:11 | selection of f | tst.go:13:9:13:9 | t | tst.go:4:2:4:2 | f |
|
| tst.go:13:9:13:11 | selection of f | tst.go:13:9:13:9 | t | tst.go:4:2:4:2 | f |
|
||||||
| tst.go:17:8:17:10 | selection of f | tst.go:17:8:17:8 | x | tst.go:4:2:4:2 | f |
|
| tst.go:17:8:17:10 | selection of f | tst.go:17:8:17:8 | x | tst.go:4:2:4:2 | f |
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
| tst.go:9:9:9:13 | selection of get | tst.go:9:9:9:9 | implicit-deref t | tst.go:12:12:12:14 | get |
|
| tst.go:9:9:9:13 | selection of get | tst.go:9:9:9:9 | implicit dereference | tst.go:12:12:12:14 | get |
|
||||||
| tst.go:9:9:9:13 | selection of get | tst.go:9:9:9:9 | t | tst.go:12:12:12:14 | get |
|
| tst.go:9:9:9:13 | selection of get | tst.go:9:9:9:9 | t | tst.go:12:12:12:14 | get |
|
||||||
| tst.go:18:2:18:7 | selection of bump | tst.go:18:2:18:2 | x | tst.go:7:13:7:16 | bump |
|
| tst.go:18:2:18:7 | selection of bump | tst.go:18:2:18:2 | x | tst.go:7:13:7:16 | bump |
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
| tst.go:19:2:19:14 | assign:0 ... = ... | tst.go:19:2:19:3 | xs [postupdate] | tst.go:19:5:19:5 | 0 | tst.go:19:10:19:14 | index expression |
|
| tst.go:19:2:19:6 | assignment to element | tst.go:19:2:19:3 | xs [postupdate] | tst.go:19:5:19:5 | 0 | tst.go:19:10:19:14 | index expression |
|
||||||
| tst.go:20:2:20:14 | assign:0 ... = ... | tst.go:20:2:20:3 | implicit-deref ps [postupdate] | tst.go:20:5:20:5 | 0 | tst.go:20:10:20:14 | index expression |
|
| tst.go:20:2:20:6 | assignment to element | tst.go:20:2:20:3 | implicit dereference [postupdate] | tst.go:20:5:20:5 | 0 | tst.go:20:10:20:14 | index expression |
|
||||||
| tst.go:20:2:20:14 | assign:0 ... = ... | tst.go:20:2:20:3 | ps [postupdate] | tst.go:20:5:20:5 | 0 | tst.go:20:10:20:14 | index expression |
|
| tst.go:20:2:20:6 | assignment to element | tst.go:20:2:20:3 | ps [postupdate] | tst.go:20:5:20:5 | 0 | tst.go:20:10:20:14 | index expression |
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
| tst.go:8:2:8:14 | assign:0 ... = ... | tst.go:8:2:8:2 | implicit-deref t [postupdate] | tst.go:4:2:4:2 | f | tst.go:8:8:8:14 | ...+... |
|
| tst.go:8:2:8:4 | assignment to field f | tst.go:8:2:8:2 | implicit dereference [postupdate] | tst.go:4:2:4:2 | f | tst.go:8:8:8:14 | ...+... |
|
||||||
| tst.go:8:2:8:14 | assign:0 ... = ... | tst.go:8:2:8:2 | t [postupdate] | tst.go:4:2:4:2 | f | tst.go:8:8:8:14 | ...+... |
|
| tst.go:8:2:8:4 | assignment to field f | tst.go:8:2:8:2 | t [postupdate] | tst.go:4:2:4:2 | f | tst.go:8:8:8:14 | ...+... |
|
||||||
| tst.go:17:2:17:14 | assign:0 ... = ... | tst.go:17:2:17:2 | x [postupdate] | tst.go:4:2:4:2 | f | tst.go:17:8:17:14 | ...+... |
|
| tst.go:17:2:17:4 | assignment to field f | tst.go:17:2:17:2 | x [postupdate] | tst.go:4:2:4:2 | f | tst.go:17:8:17:14 | ...+... |
|
||||||
|
|||||||
@@ -5,11 +5,11 @@
|
|||||||
| test.go:34:16:34:20 | param | test.go:33:11:33:27 | call to QueryParams | test.go:34:16:34:20 | param | Cross-site scripting vulnerability due to $@. | test.go:33:11:33:27 | call to QueryParams | user-provided value | test.go:0:0:0:0 | test.go | |
|
| test.go:34:16:34:20 | param | test.go:33:11:33:27 | call to QueryParams | test.go:34:16:34:20 | param | Cross-site scripting vulnerability due to $@. | test.go:33:11:33:27 | call to QueryParams | user-provided value | test.go:0:0:0:0 | test.go | |
|
||||||
| test.go:40:16:40:19 | qstr | test.go:39:10:39:26 | call to QueryString | test.go:40:16:40:19 | qstr | Cross-site scripting vulnerability due to $@. | test.go:39:10:39:26 | call to QueryString | user-provided value | test.go:0:0:0:0 | test.go | |
|
| test.go:40:16:40:19 | qstr | test.go:39:10:39:26 | call to QueryString | test.go:40:16:40:19 | qstr | Cross-site scripting vulnerability due to $@. | test.go:39:10:39:26 | call to QueryString | user-provided value | test.go:0:0:0:0 | test.go | |
|
||||||
| test.go:46:16:46:18 | val | test.go:45:9:45:34 | call to FormValue | test.go:46:16:46:18 | val | Cross-site scripting vulnerability due to $@. | test.go:45:9:45:34 | call to FormValue | user-provided value | test.go:0:0:0:0 | test.go | |
|
| test.go:46:16:46:18 | val | test.go:45:9:45:34 | call to FormValue | test.go:46:16:46:18 | val | Cross-site scripting vulnerability due to $@. | test.go:45:9:45:34 | call to FormValue | user-provided value | test.go:0:0:0:0 | test.go | |
|
||||||
| test.go:52:16:52:37 | index expression | test.go:51:2:51:30 | extract:0 ... := ... | test.go:52:16:52:37 | index expression | Cross-site scripting vulnerability due to $@. | test.go:51:2:51:30 | extract:0 ... := ... | user-provided value | test.go:0:0:0:0 | test.go | |
|
| test.go:52:16:52:37 | index expression | test.go:51:2:51:30 | ... := ...[0] | test.go:52:16:52:37 | index expression | Cross-site scripting vulnerability due to $@. | test.go:51:2:51:30 | ... := ...[0] | user-provided value | test.go:0:0:0:0 | test.go | |
|
||||||
| test.go:61:20:61:25 | buffer | test.go:57:2:57:46 | extract:0 ... := ... | test.go:61:20:61:25 | buffer | Cross-site scripting vulnerability due to $@. | test.go:57:2:57:46 | extract:0 ... := ... | user-provided value | test.go:0:0:0:0 | test.go | |
|
| test.go:61:20:61:25 | buffer | test.go:57:2:57:46 | ... := ...[0] | test.go:61:20:61:25 | buffer | Cross-site scripting vulnerability due to $@. | test.go:57:2:57:46 | ... := ...[0] | user-provided value | test.go:0:0:0:0 | test.go | |
|
||||||
| test.go:67:16:67:41 | index expression | test.go:66:2:66:31 | extract:0 ... := ... | test.go:67:16:67:41 | index expression | Cross-site scripting vulnerability due to $@. | test.go:66:2:66:31 | extract:0 ... := ... | user-provided value | test.go:0:0:0:0 | test.go | |
|
| test.go:67:16:67:41 | index expression | test.go:66:2:66:31 | ... := ...[0] | test.go:67:16:67:41 | index expression | Cross-site scripting vulnerability due to $@. | test.go:66:2:66:31 | ... := ...[0] | user-provided value | test.go:0:0:0:0 | test.go | |
|
||||||
| test.go:77:20:77:25 | buffer | test.go:72:2:72:31 | extract:0 ... := ... | test.go:77:20:77:25 | buffer | Cross-site scripting vulnerability due to $@. | test.go:72:2:72:31 | extract:0 ... := ... | user-provided value | test.go:0:0:0:0 | test.go | |
|
| test.go:77:20:77:25 | buffer | test.go:72:2:72:31 | ... := ...[0] | test.go:77:20:77:25 | buffer | Cross-site scripting vulnerability due to $@. | test.go:72:2:72:31 | ... := ...[0] | user-provided value | test.go:0:0:0:0 | test.go | |
|
||||||
| test.go:83:16:83:24 | selection of Value | test.go:82:2:82:32 | extract:0 ... := ... | test.go:83:16:83:24 | selection of Value | Cross-site scripting vulnerability due to $@. | test.go:82:2:82:32 | extract:0 ... := ... | user-provided value | test.go:0:0:0:0 | test.go | |
|
| test.go:83:16:83:24 | selection of Value | test.go:82:2:82:32 | ... := ...[0] | test.go:83:16:83:24 | selection of Value | Cross-site scripting vulnerability due to $@. | test.go:82:2:82:32 | ... := ...[0] | user-provided value | test.go:0:0:0:0 | test.go | |
|
||||||
| test.go:89:16:89:31 | selection of Value | test.go:88:13:88:25 | call to Cookies | test.go:89:16:89:31 | selection of Value | Cross-site scripting vulnerability due to $@. | test.go:88:13:88:25 | call to Cookies | user-provided value | test.go:0:0:0:0 | test.go | |
|
| test.go:89:16:89:31 | selection of Value | test.go:88:13:88:25 | call to Cookies | test.go:89:16:89:31 | selection of Value | Cross-site scripting vulnerability due to $@. | test.go:88:13:88:25 | call to Cookies | user-provided value | test.go:0:0:0:0 | test.go | |
|
||||||
| test.go:100:16:100:21 | selection of s | test.go:99:11:99:15 | &... [postupdate] | test.go:100:16:100:21 | selection of s | Cross-site scripting vulnerability due to $@. | test.go:99:11:99:15 | &... [postupdate] | user-provided value | test.go:0:0:0:0 | test.go | |
|
| test.go:100:16:100:21 | selection of s | test.go:99:11:99:15 | &... [postupdate] | test.go:100:16:100:21 | selection of s | Cross-site scripting vulnerability due to $@. | test.go:99:11:99:15 | &... [postupdate] | user-provided value | test.go:0:0:0:0 | test.go | |
|
||||||
| test.go:114:16:114:42 | type assertion | test.go:113:21:113:42 | call to Param | test.go:114:16:114:42 | type assertion | Cross-site scripting vulnerability due to $@. | test.go:113:21:113:42 | call to Param | user-provided value | test.go:0:0:0:0 | test.go | |
|
| test.go:114:16:114:42 | type assertion | test.go:113:21:113:42 | call to Param | test.go:114:16:114:42 | type assertion | Cross-site scripting vulnerability due to $@. | test.go:113:21:113:42 | call to Param | user-provided value | test.go:0:0:0:0 | test.go | |
|
||||||
@@ -25,23 +25,23 @@ edges
|
|||||||
| test.go:33:11:33:27 | call to QueryParams | test.go:34:16:34:20 | param | provenance | Src:MaD:11 |
|
| test.go:33:11:33:27 | call to QueryParams | test.go:34:16:34:20 | param | provenance | Src:MaD:11 |
|
||||||
| test.go:39:10:39:26 | call to QueryString | test.go:40:16:40:19 | qstr | provenance | Src:MaD:12 |
|
| test.go:39:10:39:26 | call to QueryString | test.go:40:16:40:19 | qstr | provenance | Src:MaD:12 |
|
||||||
| test.go:45:9:45:34 | call to FormValue | test.go:46:16:46:18 | val | provenance | Src:MaD:6 |
|
| test.go:45:9:45:34 | call to FormValue | test.go:46:16:46:18 | val | provenance | Src:MaD:6 |
|
||||||
| test.go:51:2:51:30 | extract:0 ... := ... | test.go:52:16:52:37 | index expression | provenance | Src:MaD:5 |
|
| test.go:51:2:51:30 | ... := ...[0] | test.go:52:16:52:37 | index expression | provenance | Src:MaD:5 |
|
||||||
| test.go:57:2:57:46 | extract:0 ... := ... | test.go:58:13:58:22 | fileHeader | provenance | Src:MaD:4 |
|
| test.go:57:2:57:46 | ... := ...[0] | test.go:58:13:58:22 | fileHeader | provenance | Src:MaD:4 |
|
||||||
| test.go:58:2:58:29 | extract:0 ... := ... | test.go:60:2:60:5 | file | provenance | |
|
| test.go:58:2:58:29 | ... := ...[0] | test.go:60:2:60:5 | file | provenance | |
|
||||||
| test.go:58:13:58:22 | fileHeader | test.go:58:2:58:29 | extract:0 ... := ... | provenance | MaD:17 |
|
| test.go:58:13:58:22 | fileHeader | test.go:58:2:58:29 | ... := ...[0] | provenance | MaD:17 |
|
||||||
| test.go:60:2:60:5 | file | test.go:60:12:60:17 | buffer [postupdate] | provenance | MaD:15 |
|
| test.go:60:2:60:5 | file | test.go:60:12:60:17 | buffer [postupdate] | provenance | MaD:15 |
|
||||||
| test.go:60:2:60:5 | file | test.go:60:12:60:17 | buffer [postupdate] | provenance | MaD:16 |
|
| test.go:60:2:60:5 | file | test.go:60:12:60:17 | buffer [postupdate] | provenance | MaD:16 |
|
||||||
| test.go:60:2:60:5 | file | test.go:60:12:60:17 | buffer [postupdate] | provenance | MaD:18 |
|
| test.go:60:2:60:5 | file | test.go:60:12:60:17 | buffer [postupdate] | provenance | MaD:18 |
|
||||||
| test.go:60:12:60:17 | buffer [postupdate] | test.go:61:20:61:25 | buffer | provenance | |
|
| test.go:60:12:60:17 | buffer [postupdate] | test.go:61:20:61:25 | buffer | provenance | |
|
||||||
| test.go:66:2:66:31 | extract:0 ... := ... | test.go:67:16:67:41 | index expression | provenance | Src:MaD:7 |
|
| test.go:66:2:66:31 | ... := ...[0] | test.go:67:16:67:41 | index expression | provenance | Src:MaD:7 |
|
||||||
| test.go:72:2:72:31 | extract:0 ... := ... | test.go:74:13:74:22 | fileHeader | provenance | Src:MaD:7 |
|
| test.go:72:2:72:31 | ... := ...[0] | test.go:74:13:74:22 | fileHeader | provenance | Src:MaD:7 |
|
||||||
| test.go:74:2:74:29 | extract:0 ... := ... | test.go:76:2:76:5 | file | provenance | |
|
| test.go:74:2:74:29 | ... := ...[0] | test.go:76:2:76:5 | file | provenance | |
|
||||||
| test.go:74:13:74:22 | fileHeader | test.go:74:2:74:29 | extract:0 ... := ... | provenance | MaD:17 |
|
| test.go:74:13:74:22 | fileHeader | test.go:74:2:74:29 | ... := ...[0] | provenance | MaD:17 |
|
||||||
| test.go:76:2:76:5 | file | test.go:76:12:76:17 | buffer [postupdate] | provenance | MaD:15 |
|
| test.go:76:2:76:5 | file | test.go:76:12:76:17 | buffer [postupdate] | provenance | MaD:15 |
|
||||||
| test.go:76:2:76:5 | file | test.go:76:12:76:17 | buffer [postupdate] | provenance | MaD:16 |
|
| test.go:76:2:76:5 | file | test.go:76:12:76:17 | buffer [postupdate] | provenance | MaD:16 |
|
||||||
| test.go:76:2:76:5 | file | test.go:76:12:76:17 | buffer [postupdate] | provenance | MaD:18 |
|
| test.go:76:2:76:5 | file | test.go:76:12:76:17 | buffer [postupdate] | provenance | MaD:18 |
|
||||||
| test.go:76:12:76:17 | buffer [postupdate] | test.go:77:20:77:25 | buffer | provenance | |
|
| test.go:76:12:76:17 | buffer [postupdate] | test.go:77:20:77:25 | buffer | provenance | |
|
||||||
| test.go:82:2:82:32 | extract:0 ... := ... | test.go:83:16:83:24 | selection of Value | provenance | Src:MaD:2 |
|
| test.go:82:2:82:32 | ... := ...[0] | test.go:83:16:83:24 | selection of Value | provenance | Src:MaD:2 |
|
||||||
| test.go:88:13:88:25 | call to Cookies | test.go:89:16:89:31 | selection of Value | provenance | Src:MaD:3 |
|
| test.go:88:13:88:25 | call to Cookies | test.go:89:16:89:31 | selection of Value | provenance | Src:MaD:3 |
|
||||||
| test.go:99:11:99:15 | &... [postupdate] | test.go:100:16:100:21 | selection of s | provenance | Src:MaD:1 |
|
| test.go:99:11:99:15 | &... [postupdate] | test.go:100:16:100:21 | selection of s | provenance | Src:MaD:1 |
|
||||||
| test.go:113:2:113:4 | ctx [postupdate] | test.go:114:16:114:18 | ctx | provenance | |
|
| test.go:113:2:113:4 | ctx [postupdate] | test.go:114:16:114:18 | ctx | provenance | |
|
||||||
@@ -88,23 +88,23 @@ nodes
|
|||||||
| test.go:40:16:40:19 | qstr | semmle.label | qstr |
|
| test.go:40:16:40:19 | qstr | semmle.label | qstr |
|
||||||
| test.go:45:9:45:34 | call to FormValue | semmle.label | call to FormValue |
|
| test.go:45:9:45:34 | call to FormValue | semmle.label | call to FormValue |
|
||||||
| test.go:46:16:46:18 | val | semmle.label | val |
|
| test.go:46:16:46:18 | val | semmle.label | val |
|
||||||
| test.go:51:2:51:30 | extract:0 ... := ... | semmle.label | extract:0 ... := ... |
|
| test.go:51:2:51:30 | ... := ...[0] | semmle.label | ... := ...[0] |
|
||||||
| test.go:52:16:52:37 | index expression | semmle.label | index expression |
|
| test.go:52:16:52:37 | index expression | semmle.label | index expression |
|
||||||
| test.go:57:2:57:46 | extract:0 ... := ... | semmle.label | extract:0 ... := ... |
|
| test.go:57:2:57:46 | ... := ...[0] | semmle.label | ... := ...[0] |
|
||||||
| test.go:58:2:58:29 | extract:0 ... := ... | semmle.label | extract:0 ... := ... |
|
| test.go:58:2:58:29 | ... := ...[0] | semmle.label | ... := ...[0] |
|
||||||
| test.go:58:13:58:22 | fileHeader | semmle.label | fileHeader |
|
| test.go:58:13:58:22 | fileHeader | semmle.label | fileHeader |
|
||||||
| test.go:60:2:60:5 | file | semmle.label | file |
|
| test.go:60:2:60:5 | file | semmle.label | file |
|
||||||
| test.go:60:12:60:17 | buffer [postupdate] | semmle.label | buffer [postupdate] |
|
| test.go:60:12:60:17 | buffer [postupdate] | semmle.label | buffer [postupdate] |
|
||||||
| test.go:61:20:61:25 | buffer | semmle.label | buffer |
|
| test.go:61:20:61:25 | buffer | semmle.label | buffer |
|
||||||
| test.go:66:2:66:31 | extract:0 ... := ... | semmle.label | extract:0 ... := ... |
|
| test.go:66:2:66:31 | ... := ...[0] | semmle.label | ... := ...[0] |
|
||||||
| test.go:67:16:67:41 | index expression | semmle.label | index expression |
|
| test.go:67:16:67:41 | index expression | semmle.label | index expression |
|
||||||
| test.go:72:2:72:31 | extract:0 ... := ... | semmle.label | extract:0 ... := ... |
|
| test.go:72:2:72:31 | ... := ...[0] | semmle.label | ... := ...[0] |
|
||||||
| test.go:74:2:74:29 | extract:0 ... := ... | semmle.label | extract:0 ... := ... |
|
| test.go:74:2:74:29 | ... := ...[0] | semmle.label | ... := ...[0] |
|
||||||
| test.go:74:13:74:22 | fileHeader | semmle.label | fileHeader |
|
| test.go:74:13:74:22 | fileHeader | semmle.label | fileHeader |
|
||||||
| test.go:76:2:76:5 | file | semmle.label | file |
|
| test.go:76:2:76:5 | file | semmle.label | file |
|
||||||
| test.go:76:12:76:17 | buffer [postupdate] | semmle.label | buffer [postupdate] |
|
| test.go:76:12:76:17 | buffer [postupdate] | semmle.label | buffer [postupdate] |
|
||||||
| test.go:77:20:77:25 | buffer | semmle.label | buffer |
|
| test.go:77:20:77:25 | buffer | semmle.label | buffer |
|
||||||
| test.go:82:2:82:32 | extract:0 ... := ... | semmle.label | extract:0 ... := ... |
|
| test.go:82:2:82:32 | ... := ...[0] | semmle.label | ... := ...[0] |
|
||||||
| test.go:83:16:83:24 | selection of Value | semmle.label | selection of Value |
|
| test.go:83:16:83:24 | selection of Value | semmle.label | selection of Value |
|
||||||
| test.go:88:13:88:25 | call to Cookies | semmle.label | call to Cookies |
|
| test.go:88:13:88:25 | call to Cookies | semmle.label | call to Cookies |
|
||||||
| test.go:89:16:89:31 | selection of Value | semmle.label | selection of Value |
|
| test.go:89:16:89:31 | selection of Value | semmle.label | selection of Value |
|
||||||
|
|||||||
@@ -7,18 +7,18 @@
|
|||||||
| Gin.go:58:10:58:25 | call to Param |
|
| Gin.go:58:10:58:25 | call to Param |
|
||||||
| Gin.go:62:10:62:34 | call to GetStringSlice |
|
| Gin.go:62:10:62:34 | call to GetStringSlice |
|
||||||
| Gin.go:66:10:66:29 | call to GetString |
|
| Gin.go:66:10:66:29 | call to GetString |
|
||||||
| Gin.go:70:3:70:28 | extract:0 ... := ... |
|
| Gin.go:70:3:70:28 | ... := ...[0] |
|
||||||
| Gin.go:74:10:74:23 | call to ClientIP |
|
| Gin.go:74:10:74:23 | call to ClientIP |
|
||||||
| Gin.go:78:10:78:26 | call to ContentType |
|
| Gin.go:78:10:78:26 | call to ContentType |
|
||||||
| Gin.go:82:3:82:29 | extract:0 ... := ... |
|
| Gin.go:82:3:82:29 | ... := ...[0] |
|
||||||
| Gin.go:86:3:86:36 | extract:0 ... := ... |
|
| Gin.go:86:3:86:36 | ... := ...[0] |
|
||||||
| Gin.go:90:3:90:31 | extract:0 ... := ... |
|
| Gin.go:90:3:90:31 | ... := ...[0] |
|
||||||
| Gin.go:94:3:94:39 | extract:0 ... := ... |
|
| Gin.go:94:3:94:39 | ... := ...[0] |
|
||||||
| Gin.go:98:3:98:34 | extract:0 ... := ... |
|
| Gin.go:98:3:98:34 | ... := ...[0] |
|
||||||
| Gin.go:102:10:102:52 | call to DefaultPostForm |
|
| Gin.go:102:10:102:52 | call to DefaultPostForm |
|
||||||
| Gin.go:106:10:106:49 | call to DefaultQuery |
|
| Gin.go:106:10:106:49 | call to DefaultQuery |
|
||||||
| Gin.go:110:3:110:37 | extract:0 ... := ... |
|
| Gin.go:110:3:110:37 | ... := ...[0] |
|
||||||
| Gin.go:114:3:114:34 | extract:0 ... := ... |
|
| Gin.go:114:3:114:34 | ... := ...[0] |
|
||||||
| Gin.go:118:10:118:32 | call to GetStringMap |
|
| Gin.go:118:10:118:32 | call to GetStringMap |
|
||||||
| Gin.go:122:10:122:38 | call to GetStringMapString |
|
| Gin.go:122:10:122:38 | call to GetStringMapString |
|
||||||
| Gin.go:126:10:126:43 | call to GetStringMapStringSlice |
|
| Gin.go:126:10:126:43 | call to GetStringMapStringSlice |
|
||||||
|
|||||||
@@ -6,18 +6,18 @@ models
|
|||||||
| 5 | Source: github.com/emicklei/go-restful; Request; true; ReadEntity; ; ; Argument[0]; remote; manual |
|
| 5 | Source: github.com/emicklei/go-restful; Request; true; ReadEntity; ; ; Argument[0]; remote; manual |
|
||||||
edges
|
edges
|
||||||
| gorestful.go:15:15:15:44 | call to QueryParameters | gorestful.go:15:15:15:47 | index expression | provenance | Src:MaD:4 Sink:MaD:1 |
|
| gorestful.go:15:15:15:44 | call to QueryParameters | gorestful.go:15:15:15:47 | index expression | provenance | Src:MaD:4 Sink:MaD:1 |
|
||||||
| gorestful.go:17:2:17:39 | extract:0 ... := ... | gorestful.go:18:15:18:17 | val | provenance | Src:MaD:2 Sink:MaD:1 |
|
| gorestful.go:17:2:17:39 | ... := ...[0] | gorestful.go:18:15:18:17 | val | provenance | Src:MaD:2 Sink:MaD:1 |
|
||||||
| gorestful.go:21:15:21:38 | call to PathParameters | gorestful.go:21:15:21:45 | index expression | provenance | Src:MaD:3 Sink:MaD:1 |
|
| gorestful.go:21:15:21:38 | call to PathParameters | gorestful.go:21:15:21:45 | index expression | provenance | Src:MaD:3 Sink:MaD:1 |
|
||||||
| gorestful.go:23:21:23:24 | &... [postupdate] | gorestful.go:24:15:24:21 | selection of cmd | provenance | Src:MaD:5 Sink:MaD:1 |
|
| gorestful.go:23:21:23:24 | &... [postupdate] | gorestful.go:24:15:24:21 | selection of cmd | provenance | Src:MaD:5 Sink:MaD:1 |
|
||||||
| gorestful_v2.go:15:15:15:44 | call to QueryParameters | gorestful_v2.go:15:15:15:47 | index expression | provenance | Src:MaD:4 Sink:MaD:1 |
|
| gorestful_v2.go:15:15:15:44 | call to QueryParameters | gorestful_v2.go:15:15:15:47 | index expression | provenance | Src:MaD:4 Sink:MaD:1 |
|
||||||
| gorestful_v2.go:17:2:17:39 | extract:0 ... := ... | gorestful_v2.go:18:15:18:17 | val | provenance | Src:MaD:2 Sink:MaD:1 |
|
| gorestful_v2.go:17:2:17:39 | ... := ...[0] | gorestful_v2.go:18:15:18:17 | val | provenance | Src:MaD:2 Sink:MaD:1 |
|
||||||
| gorestful_v2.go:21:15:21:38 | call to PathParameters | gorestful_v2.go:21:15:21:45 | index expression | provenance | Src:MaD:3 Sink:MaD:1 |
|
| gorestful_v2.go:21:15:21:38 | call to PathParameters | gorestful_v2.go:21:15:21:45 | index expression | provenance | Src:MaD:3 Sink:MaD:1 |
|
||||||
| gorestful_v2.go:23:21:23:24 | &... [postupdate] | gorestful_v2.go:24:15:24:21 | selection of cmd | provenance | Src:MaD:5 Sink:MaD:1 |
|
| gorestful_v2.go:23:21:23:24 | &... [postupdate] | gorestful_v2.go:24:15:24:21 | selection of cmd | provenance | Src:MaD:5 Sink:MaD:1 |
|
||||||
nodes
|
nodes
|
||||||
| gorestful.go:15:15:15:44 | call to QueryParameters | semmle.label | call to QueryParameters |
|
| gorestful.go:15:15:15:44 | call to QueryParameters | semmle.label | call to QueryParameters |
|
||||||
| gorestful.go:15:15:15:47 | index expression | semmle.label | index expression |
|
| gorestful.go:15:15:15:47 | index expression | semmle.label | index expression |
|
||||||
| gorestful.go:16:15:16:43 | call to QueryParameter | semmle.label | call to QueryParameter |
|
| gorestful.go:16:15:16:43 | call to QueryParameter | semmle.label | call to QueryParameter |
|
||||||
| gorestful.go:17:2:17:39 | extract:0 ... := ... | semmle.label | extract:0 ... := ... |
|
| gorestful.go:17:2:17:39 | ... := ...[0] | semmle.label | ... := ...[0] |
|
||||||
| gorestful.go:18:15:18:17 | val | semmle.label | val |
|
| gorestful.go:18:15:18:17 | val | semmle.label | val |
|
||||||
| gorestful.go:19:15:19:44 | call to HeaderParameter | semmle.label | call to HeaderParameter |
|
| gorestful.go:19:15:19:44 | call to HeaderParameter | semmle.label | call to HeaderParameter |
|
||||||
| gorestful.go:20:15:20:42 | call to PathParameter | semmle.label | call to PathParameter |
|
| gorestful.go:20:15:20:42 | call to PathParameter | semmle.label | call to PathParameter |
|
||||||
@@ -28,7 +28,7 @@ nodes
|
|||||||
| gorestful_v2.go:15:15:15:44 | call to QueryParameters | semmle.label | call to QueryParameters |
|
| gorestful_v2.go:15:15:15:44 | call to QueryParameters | semmle.label | call to QueryParameters |
|
||||||
| gorestful_v2.go:15:15:15:47 | index expression | semmle.label | index expression |
|
| gorestful_v2.go:15:15:15:47 | index expression | semmle.label | index expression |
|
||||||
| gorestful_v2.go:16:15:16:43 | call to QueryParameter | semmle.label | call to QueryParameter |
|
| gorestful_v2.go:16:15:16:43 | call to QueryParameter | semmle.label | call to QueryParameter |
|
||||||
| gorestful_v2.go:17:2:17:39 | extract:0 ... := ... | semmle.label | extract:0 ... := ... |
|
| gorestful_v2.go:17:2:17:39 | ... := ...[0] | semmle.label | ... := ...[0] |
|
||||||
| gorestful_v2.go:18:15:18:17 | val | semmle.label | val |
|
| gorestful_v2.go:18:15:18:17 | val | semmle.label | val |
|
||||||
| gorestful_v2.go:19:15:19:44 | call to HeaderParameter | semmle.label | call to HeaderParameter |
|
| gorestful_v2.go:19:15:19:44 | call to HeaderParameter | semmle.label | call to HeaderParameter |
|
||||||
| gorestful_v2.go:20:15:20:42 | call to PathParameter | semmle.label | call to PathParameter |
|
| gorestful_v2.go:20:15:20:42 | call to PathParameter | semmle.label | call to PathParameter |
|
||||||
@@ -41,14 +41,14 @@ invalidModelRow
|
|||||||
#select
|
#select
|
||||||
| gorestful.go:15:15:15:47 | index expression | gorestful.go:15:15:15:44 | call to QueryParameters | gorestful.go:15:15:15:47 | index expression | This command depends on $@. | gorestful.go:15:15:15:44 | call to QueryParameters | a user-provided value |
|
| gorestful.go:15:15:15:47 | index expression | gorestful.go:15:15:15:44 | call to QueryParameters | gorestful.go:15:15:15:47 | index expression | This command depends on $@. | gorestful.go:15:15:15:44 | call to QueryParameters | a user-provided value |
|
||||||
| gorestful.go:16:15:16:43 | call to QueryParameter | gorestful.go:16:15:16:43 | call to QueryParameter | gorestful.go:16:15:16:43 | call to QueryParameter | This command depends on $@. | gorestful.go:16:15:16:43 | call to QueryParameter | a user-provided value |
|
| gorestful.go:16:15:16:43 | call to QueryParameter | gorestful.go:16:15:16:43 | call to QueryParameter | gorestful.go:16:15:16:43 | call to QueryParameter | This command depends on $@. | gorestful.go:16:15:16:43 | call to QueryParameter | a user-provided value |
|
||||||
| gorestful.go:18:15:18:17 | val | gorestful.go:17:2:17:39 | extract:0 ... := ... | gorestful.go:18:15:18:17 | val | This command depends on $@. | gorestful.go:17:2:17:39 | extract:0 ... := ... | a user-provided value |
|
| gorestful.go:18:15:18:17 | val | gorestful.go:17:2:17:39 | ... := ...[0] | gorestful.go:18:15:18:17 | val | This command depends on $@. | gorestful.go:17:2:17:39 | ... := ...[0] | a user-provided value |
|
||||||
| gorestful.go:19:15:19:44 | call to HeaderParameter | gorestful.go:19:15:19:44 | call to HeaderParameter | gorestful.go:19:15:19:44 | call to HeaderParameter | This command depends on $@. | gorestful.go:19:15:19:44 | call to HeaderParameter | a user-provided value |
|
| gorestful.go:19:15:19:44 | call to HeaderParameter | gorestful.go:19:15:19:44 | call to HeaderParameter | gorestful.go:19:15:19:44 | call to HeaderParameter | This command depends on $@. | gorestful.go:19:15:19:44 | call to HeaderParameter | a user-provided value |
|
||||||
| gorestful.go:20:15:20:42 | call to PathParameter | gorestful.go:20:15:20:42 | call to PathParameter | gorestful.go:20:15:20:42 | call to PathParameter | This command depends on $@. | gorestful.go:20:15:20:42 | call to PathParameter | a user-provided value |
|
| gorestful.go:20:15:20:42 | call to PathParameter | gorestful.go:20:15:20:42 | call to PathParameter | gorestful.go:20:15:20:42 | call to PathParameter | This command depends on $@. | gorestful.go:20:15:20:42 | call to PathParameter | a user-provided value |
|
||||||
| gorestful.go:21:15:21:45 | index expression | gorestful.go:21:15:21:38 | call to PathParameters | gorestful.go:21:15:21:45 | index expression | This command depends on $@. | gorestful.go:21:15:21:38 | call to PathParameters | a user-provided value |
|
| gorestful.go:21:15:21:45 | index expression | gorestful.go:21:15:21:38 | call to PathParameters | gorestful.go:21:15:21:45 | index expression | This command depends on $@. | gorestful.go:21:15:21:38 | call to PathParameters | a user-provided value |
|
||||||
| gorestful.go:24:15:24:21 | selection of cmd | gorestful.go:23:21:23:24 | &... [postupdate] | gorestful.go:24:15:24:21 | selection of cmd | This command depends on $@. | gorestful.go:23:21:23:24 | &... [postupdate] | a user-provided value |
|
| gorestful.go:24:15:24:21 | selection of cmd | gorestful.go:23:21:23:24 | &... [postupdate] | gorestful.go:24:15:24:21 | selection of cmd | This command depends on $@. | gorestful.go:23:21:23:24 | &... [postupdate] | a user-provided value |
|
||||||
| gorestful_v2.go:15:15:15:47 | index expression | gorestful_v2.go:15:15:15:44 | call to QueryParameters | gorestful_v2.go:15:15:15:47 | index expression | This command depends on $@. | gorestful_v2.go:15:15:15:44 | call to QueryParameters | a user-provided value |
|
| gorestful_v2.go:15:15:15:47 | index expression | gorestful_v2.go:15:15:15:44 | call to QueryParameters | gorestful_v2.go:15:15:15:47 | index expression | This command depends on $@. | gorestful_v2.go:15:15:15:44 | call to QueryParameters | a user-provided value |
|
||||||
| gorestful_v2.go:16:15:16:43 | call to QueryParameter | gorestful_v2.go:16:15:16:43 | call to QueryParameter | gorestful_v2.go:16:15:16:43 | call to QueryParameter | This command depends on $@. | gorestful_v2.go:16:15:16:43 | call to QueryParameter | a user-provided value |
|
| gorestful_v2.go:16:15:16:43 | call to QueryParameter | gorestful_v2.go:16:15:16:43 | call to QueryParameter | gorestful_v2.go:16:15:16:43 | call to QueryParameter | This command depends on $@. | gorestful_v2.go:16:15:16:43 | call to QueryParameter | a user-provided value |
|
||||||
| gorestful_v2.go:18:15:18:17 | val | gorestful_v2.go:17:2:17:39 | extract:0 ... := ... | gorestful_v2.go:18:15:18:17 | val | This command depends on $@. | gorestful_v2.go:17:2:17:39 | extract:0 ... := ... | a user-provided value |
|
| gorestful_v2.go:18:15:18:17 | val | gorestful_v2.go:17:2:17:39 | ... := ...[0] | gorestful_v2.go:18:15:18:17 | val | This command depends on $@. | gorestful_v2.go:17:2:17:39 | ... := ...[0] | a user-provided value |
|
||||||
| gorestful_v2.go:19:15:19:44 | call to HeaderParameter | gorestful_v2.go:19:15:19:44 | call to HeaderParameter | gorestful_v2.go:19:15:19:44 | call to HeaderParameter | This command depends on $@. | gorestful_v2.go:19:15:19:44 | call to HeaderParameter | a user-provided value |
|
| gorestful_v2.go:19:15:19:44 | call to HeaderParameter | gorestful_v2.go:19:15:19:44 | call to HeaderParameter | gorestful_v2.go:19:15:19:44 | call to HeaderParameter | This command depends on $@. | gorestful_v2.go:19:15:19:44 | call to HeaderParameter | a user-provided value |
|
||||||
| gorestful_v2.go:20:15:20:42 | call to PathParameter | gorestful_v2.go:20:15:20:42 | call to PathParameter | gorestful_v2.go:20:15:20:42 | call to PathParameter | This command depends on $@. | gorestful_v2.go:20:15:20:42 | call to PathParameter | a user-provided value |
|
| gorestful_v2.go:20:15:20:42 | call to PathParameter | gorestful_v2.go:20:15:20:42 | call to PathParameter | gorestful_v2.go:20:15:20:42 | call to PathParameter | This command depends on $@. | gorestful_v2.go:20:15:20:42 | call to PathParameter | a user-provided value |
|
||||||
| gorestful_v2.go:21:15:21:45 | index expression | gorestful_v2.go:21:15:21:38 | call to PathParameters | gorestful_v2.go:21:15:21:45 | index expression | This command depends on $@. | gorestful_v2.go:21:15:21:38 | call to PathParameters | a user-provided value |
|
| gorestful_v2.go:21:15:21:45 | index expression | gorestful_v2.go:21:15:21:38 | call to PathParameters | gorestful_v2.go:21:15:21:45 | index expression | This command depends on $@. | gorestful_v2.go:21:15:21:38 | call to PathParameters | a user-provided value |
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
#select
|
#select
|
||||||
| EndToEnd.go:95:20:95:49 | call to Get | EndToEnd.go:95:20:95:27 | selection of Params | EndToEnd.go:95:20:95:49 | call to Get | This path to an untrusted URL redirection depends on a $@. | EndToEnd.go:95:20:95:27 | selection of Params | user-provided value |
|
| EndToEnd.go:95:20:95:49 | call to Get | EndToEnd.go:95:20:95:27 | selection of Params | EndToEnd.go:95:20:95:49 | call to Get | This path to an untrusted URL redirection depends on a $@. | EndToEnd.go:95:20:95:27 | selection of Params | user-provided value |
|
||||||
edges
|
edges
|
||||||
| EndToEnd.go:95:20:95:27 | implicit-deref selection of Params | EndToEnd.go:95:20:95:27 | selection of Params [postupdate] | provenance | Config |
|
| EndToEnd.go:95:20:95:27 | implicit dereference | EndToEnd.go:95:20:95:27 | selection of Params [postupdate] | provenance | Config |
|
||||||
| EndToEnd.go:95:20:95:27 | implicit-deref selection of Params | EndToEnd.go:95:20:95:32 | selection of Form | provenance | Config |
|
| EndToEnd.go:95:20:95:27 | implicit dereference | EndToEnd.go:95:20:95:32 | selection of Form | provenance | Config |
|
||||||
| EndToEnd.go:95:20:95:27 | selection of Params | EndToEnd.go:95:20:95:27 | implicit-deref selection of Params | provenance | Src:MaD:2 Config |
|
| EndToEnd.go:95:20:95:27 | selection of Params | EndToEnd.go:95:20:95:27 | implicit dereference | provenance | Src:MaD:2 Config |
|
||||||
| EndToEnd.go:95:20:95:27 | selection of Params | EndToEnd.go:95:20:95:32 | selection of Form | provenance | Src:MaD:2 Config |
|
| EndToEnd.go:95:20:95:27 | selection of Params | EndToEnd.go:95:20:95:32 | selection of Form | provenance | Src:MaD:2 Config |
|
||||||
| EndToEnd.go:95:20:95:27 | selection of Params [postupdate] | EndToEnd.go:95:20:95:27 | implicit-deref selection of Params | provenance | Config |
|
| EndToEnd.go:95:20:95:27 | selection of Params [postupdate] | EndToEnd.go:95:20:95:27 | implicit dereference | provenance | Config |
|
||||||
| EndToEnd.go:95:20:95:32 | selection of Form | EndToEnd.go:95:20:95:49 | call to Get | provenance | Config Sink:MaD:1 |
|
| EndToEnd.go:95:20:95:32 | selection of Form | EndToEnd.go:95:20:95:49 | call to Get | provenance | Config Sink:MaD:1 |
|
||||||
models
|
models
|
||||||
| 1 | Sink: group:revel; Controller; true; Redirect; ; ; Argument[0]; url-redirection; manual |
|
| 1 | Sink: group:revel; Controller; true; Redirect; ; ; Argument[0]; url-redirection; manual |
|
||||||
| 2 | Source: group:revel; Controller; true; Params; ; ; ; remote; manual |
|
| 2 | Source: group:revel; Controller; true; Params; ; ; ; remote; manual |
|
||||||
nodes
|
nodes
|
||||||
| EndToEnd.go:95:20:95:27 | implicit-deref selection of Params | semmle.label | implicit-deref selection of Params |
|
| EndToEnd.go:95:20:95:27 | implicit dereference | semmle.label | implicit dereference |
|
||||||
| EndToEnd.go:95:20:95:27 | selection of Params | semmle.label | selection of Params |
|
| EndToEnd.go:95:20:95:27 | selection of Params | semmle.label | selection of Params |
|
||||||
| EndToEnd.go:95:20:95:27 | selection of Params [postupdate] | semmle.label | selection of Params [postupdate] |
|
| EndToEnd.go:95:20:95:27 | selection of Params [postupdate] | semmle.label | selection of Params [postupdate] |
|
||||||
| EndToEnd.go:95:20:95:32 | selection of Form | semmle.label | selection of Form |
|
| EndToEnd.go:95:20:95:32 | selection of Form | semmle.label | selection of Form |
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
invalidModelRow
|
invalidModelRow
|
||||||
#select
|
#select
|
||||||
| crypto.go:9:14:9:31 | call to NewCipher | crypto.go:9:2:9:31 | extract:0 ... := ... |
|
| crypto.go:9:14:9:31 | call to NewCipher | crypto.go:9:2:9:31 | ... := ...[0] |
|
||||||
| crypto.go:9:14:9:31 | call to NewCipher | crypto.go:9:2:9:31 | extract:1 ... := ... |
|
| crypto.go:9:14:9:31 | call to NewCipher | crypto.go:9:2:9:31 | ... := ...[1] |
|
||||||
| crypto.go:10:15:10:34 | call to NewGCM | crypto.go:10:2:10:34 | extract:0 ... := ... |
|
| crypto.go:10:15:10:34 | call to NewGCM | crypto.go:10:2:10:34 | ... := ...[0] |
|
||||||
| crypto.go:10:15:10:34 | call to NewGCM | crypto.go:10:2:10:34 | extract:1 ... := ... |
|
| crypto.go:10:15:10:34 | call to NewGCM | crypto.go:10:2:10:34 | ... := ...[1] |
|
||||||
| crypto.go:11:18:11:57 | call to Open | crypto.go:11:2:11:57 | extract:0 ... := ... |
|
| crypto.go:11:18:11:57 | call to Open | crypto.go:11:2:11:57 | ... := ...[0] |
|
||||||
| crypto.go:11:18:11:57 | call to Open | crypto.go:11:2:11:57 | extract:1 ... := ... |
|
| crypto.go:11:18:11:57 | call to Open | crypto.go:11:2:11:57 | ... := ...[1] |
|
||||||
| crypto.go:11:42:11:51 | ciphertext | crypto.go:11:2:11:57 | extract:0 ... := ... |
|
| crypto.go:11:42:11:51 | ciphertext | crypto.go:11:2:11:57 | ... := ...[0] |
|
||||||
| io.go:14:31:14:43 | "some string" | io.go:14:13:14:44 | call to NewReader |
|
| io.go:14:31:14:43 | "some string" | io.go:14:13:14:44 | call to NewReader |
|
||||||
| io.go:16:23:16:27 | &... | io.go:16:24:16:27 | buf1 [postupdate] |
|
| io.go:16:23:16:27 | &... | io.go:16:24:16:27 | buf1 [postupdate] |
|
||||||
| io.go:16:23:16:27 | &... [postupdate] | io.go:16:24:16:27 | buf1 [postupdate] |
|
| io.go:16:23:16:27 | &... [postupdate] | io.go:16:24:16:27 | buf1 [postupdate] |
|
||||||
@@ -31,9 +31,9 @@ invalidModelRow
|
|||||||
| io.go:33:20:33:23 | buf1 | io.go:33:19:33:23 | &... |
|
| io.go:33:20:33:23 | buf1 | io.go:33:19:33:23 | &... |
|
||||||
| io.go:33:20:33:23 | buf1 [postupdate] | io.go:33:19:33:23 | &... |
|
| io.go:33:20:33:23 | buf1 [postupdate] | io.go:33:19:33:23 | &... |
|
||||||
| io.go:35:16:35:21 | reader | io.go:35:12:35:13 | w2 [postupdate] |
|
| io.go:35:16:35:21 | reader | io.go:35:12:35:13 | w2 [postupdate] |
|
||||||
| io.go:39:11:39:19 | call to Pipe | io.go:39:3:39:19 | extract:0 ... := ... |
|
| io.go:39:11:39:19 | call to Pipe | io.go:39:3:39:19 | ... := ...[0] |
|
||||||
| io.go:39:11:39:19 | call to Pipe | io.go:39:3:39:19 | extract:1 ... := ... |
|
| io.go:39:11:39:19 | call to Pipe | io.go:39:3:39:19 | ... := ...[1] |
|
||||||
| io.go:40:14:40:14 | w [postupdate] | io.go:39:3:39:19 | extract:0 ... := ... |
|
| io.go:40:14:40:14 | w [postupdate] | io.go:39:3:39:19 | ... := ...[0] |
|
||||||
| io.go:40:17:40:31 | "some string\\n" | io.go:40:14:40:14 | w [postupdate] |
|
| io.go:40:17:40:31 | "some string\\n" | io.go:40:14:40:14 | w [postupdate] |
|
||||||
| io.go:43:16:43:16 | r | io.go:43:3:43:5 | buf [postupdate] |
|
| io.go:43:16:43:16 | r | io.go:43:3:43:5 | buf [postupdate] |
|
||||||
| io.go:44:13:44:15 | buf | io.go:44:13:44:24 | call to String |
|
| io.go:44:13:44:15 | buf | io.go:44:13:44:24 | call to String |
|
||||||
@@ -74,35 +74,35 @@ invalidModelRow
|
|||||||
| io.go:101:26:101:38 | "some string" | io.go:101:8:101:39 | call to NewReader |
|
| io.go:101:26:101:38 | "some string" | io.go:101:8:101:39 | call to NewReader |
|
||||||
| io.go:102:3:102:3 | r | io.go:102:13:102:21 | selection of Stdout [postupdate] |
|
| io.go:102:3:102:3 | r | io.go:102:13:102:21 | selection of Stdout [postupdate] |
|
||||||
| io.go:108:30:108:42 | "some string" | io.go:108:12:108:43 | call to NewReader |
|
| io.go:108:30:108:42 | "some string" | io.go:108:12:108:43 | call to NewReader |
|
||||||
| io.go:109:12:109:33 | call to ReadAll | io.go:109:2:109:33 | extract:0 ... := ... |
|
| io.go:109:12:109:33 | call to ReadAll | io.go:109:2:109:33 | ... := ...[0] |
|
||||||
| io.go:109:12:109:33 | call to ReadAll | io.go:109:2:109:33 | extract:1 ... := ... |
|
| io.go:109:12:109:33 | call to ReadAll | io.go:109:2:109:33 | ... := ...[1] |
|
||||||
| io.go:109:27:109:32 | reader | io.go:109:2:109:33 | extract:0 ... := ... |
|
| io.go:109:27:109:32 | reader | io.go:109:2:109:33 | ... := ...[0] |
|
||||||
| io.go:110:18:110:20 | buf | io.go:110:2:110:10 | selection of Stdout [postupdate] |
|
| io.go:110:18:110:20 | buf | io.go:110:2:110:10 | selection of Stdout [postupdate] |
|
||||||
| main.go:11:12:11:26 | call to Marshal | main.go:11:2:11:26 | extract:0 ... := ... |
|
| main.go:11:12:11:26 | call to Marshal | main.go:11:2:11:26 | ... := ...[0] |
|
||||||
| main.go:11:12:11:26 | call to Marshal | main.go:11:2:11:26 | extract:1 ... := ... |
|
| main.go:11:12:11:26 | call to Marshal | main.go:11:2:11:26 | ... := ...[1] |
|
||||||
| main.go:11:25:11:25 | v | main.go:11:2:11:26 | extract:0 ... := ... |
|
| main.go:11:25:11:25 | v | main.go:11:2:11:26 | ... := ...[0] |
|
||||||
| main.go:13:14:13:52 | call to MarshalIndent | main.go:13:2:13:52 | extract:0 ... := ... |
|
| main.go:13:14:13:52 | call to MarshalIndent | main.go:13:2:13:52 | ... := ...[0] |
|
||||||
| main.go:13:14:13:52 | call to MarshalIndent | main.go:13:2:13:52 | extract:1 ... := ... |
|
| main.go:13:14:13:52 | call to MarshalIndent | main.go:13:2:13:52 | ... := ...[1] |
|
||||||
| main.go:13:33:13:33 | v | main.go:13:2:13:52 | extract:0 ... := ... |
|
| main.go:13:33:13:33 | v | main.go:13:2:13:52 | ... := ...[0] |
|
||||||
| main.go:13:36:13:45 | "/*JSON*/" | main.go:13:2:13:52 | extract:0 ... := ... |
|
| main.go:13:36:13:45 | "/*JSON*/" | main.go:13:2:13:52 | ... := ...[0] |
|
||||||
| main.go:13:48:13:51 | " " | main.go:13:2:13:52 | extract:0 ... := ... |
|
| main.go:13:48:13:51 | " " | main.go:13:2:13:52 | ... := ...[0] |
|
||||||
| main.go:14:25:14:25 | b | main.go:14:9:14:41 | slice literal |
|
| main.go:14:25:14:25 | b | main.go:14:9:14:41 | slice literal |
|
||||||
| main.go:14:28:14:30 | err | main.go:14:9:14:41 | slice literal |
|
| main.go:14:28:14:30 | err | main.go:14:9:14:41 | slice literal |
|
||||||
| main.go:14:33:14:34 | b2 | main.go:14:9:14:41 | slice literal |
|
| main.go:14:33:14:34 | b2 | main.go:14:9:14:41 | slice literal |
|
||||||
| main.go:14:37:14:40 | err2 | main.go:14:9:14:41 | slice literal |
|
| main.go:14:37:14:40 | err2 | main.go:14:9:14:41 | slice literal |
|
||||||
| main.go:19:18:19:42 | call to DecodeString | main.go:19:2:19:42 | extract:0 ... := ... |
|
| main.go:19:18:19:42 | call to DecodeString | main.go:19:2:19:42 | ... := ...[0] |
|
||||||
| main.go:19:18:19:42 | call to DecodeString | main.go:19:2:19:42 | extract:1 ... := ... |
|
| main.go:19:18:19:42 | call to DecodeString | main.go:19:2:19:42 | ... := ...[1] |
|
||||||
| main.go:19:35:19:41 | encoded | main.go:19:2:19:42 | extract:0 ... := ... |
|
| main.go:19:35:19:41 | encoded | main.go:19:2:19:42 | ... := ...[0] |
|
||||||
| main.go:23:25:23:31 | decoded | main.go:23:9:23:48 | slice literal |
|
| main.go:23:25:23:31 | decoded | main.go:23:9:23:48 | slice literal |
|
||||||
| main.go:23:34:23:36 | err | main.go:23:9:23:48 | slice literal |
|
| main.go:23:34:23:36 | err | main.go:23:9:23:48 | slice literal |
|
||||||
| main.go:23:39:23:47 | reEncoded | main.go:23:9:23:48 | slice literal |
|
| main.go:23:39:23:47 | reEncoded | main.go:23:9:23:48 | slice literal |
|
||||||
| main.go:28:2:28:4 | implicit-deref req | main.go:28:2:28:4 | req [postupdate] |
|
| main.go:28:2:28:4 | implicit dereference | main.go:28:2:28:4 | req [postupdate] |
|
||||||
| main.go:28:2:28:4 | implicit-deref req | main.go:28:2:28:9 | selection of Body |
|
| main.go:28:2:28:4 | implicit dereference | main.go:28:2:28:9 | selection of Body |
|
||||||
| main.go:28:2:28:4 | req | main.go:28:2:28:4 | implicit-deref req |
|
| main.go:28:2:28:4 | req | main.go:28:2:28:4 | implicit dereference |
|
||||||
| main.go:28:2:28:4 | req [postupdate] | main.go:28:2:28:4 | implicit-deref req |
|
| main.go:28:2:28:4 | req [postupdate] | main.go:28:2:28:4 | implicit dereference |
|
||||||
| main.go:28:2:28:9 | selection of Body | main.go:28:16:28:16 | b [postupdate] |
|
| main.go:28:2:28:9 | selection of Body | main.go:28:16:28:16 | b [postupdate] |
|
||||||
| main.go:34:2:34:4 | implicit-deref req | main.go:34:2:34:4 | req [postupdate] |
|
| main.go:34:2:34:4 | implicit dereference | main.go:34:2:34:4 | req [postupdate] |
|
||||||
| main.go:34:2:34:4 | implicit-deref req | main.go:34:2:34:9 | selection of Body |
|
| main.go:34:2:34:4 | implicit dereference | main.go:34:2:34:9 | selection of Body |
|
||||||
| main.go:34:2:34:4 | req | main.go:34:2:34:4 | implicit-deref req |
|
| main.go:34:2:34:4 | req | main.go:34:2:34:4 | implicit dereference |
|
||||||
| main.go:34:2:34:4 | req [postupdate] | main.go:34:2:34:4 | implicit-deref req |
|
| main.go:34:2:34:4 | req [postupdate] | main.go:34:2:34:4 | implicit dereference |
|
||||||
| main.go:34:2:34:9 | selection of Body | main.go:34:16:34:16 | b [postupdate] |
|
| main.go:34:2:34:9 | selection of Body | main.go:34:16:34:16 | b [postupdate] |
|
||||||
|
|||||||
@@ -1,19 +1,19 @@
|
|||||||
#select
|
#select
|
||||||
| server/main.go:30:38:30:48 | selection of Text | rpc/notes/service.twirp.go:538:25:538:32 | selection of Body | server/main.go:30:38:30:48 | selection of Text | The $@ of this request depends on a $@. | server/main.go:30:38:30:48 | selection of Text | URL | rpc/notes/service.twirp.go:538:25:538:32 | selection of Body | user-provided value |
|
| server/main.go:30:38:30:48 | selection of Text | rpc/notes/service.twirp.go:538:25:538:32 | selection of Body | server/main.go:30:38:30:48 | selection of Text | The $@ of this request depends on a $@. | server/main.go:30:38:30:48 | selection of Text | URL | rpc/notes/service.twirp.go:538:25:538:32 | selection of Body | user-provided value |
|
||||||
| server/main.go:30:38:30:48 | selection of Text | server/main.go:19:109:38:1 | SSA def(params) | server/main.go:30:38:30:48 | selection of Text | The $@ of this request depends on a $@. | server/main.go:30:38:30:48 | selection of Text | URL | server/main.go:19:109:38:1 | SSA def(params) | user-provided value |
|
| server/main.go:30:38:30:48 | selection of Text | server/main.go:19:56:19:61 | SSA def(params) | server/main.go:30:38:30:48 | selection of Text | The $@ of this request depends on a $@. | server/main.go:30:38:30:48 | selection of Text | URL | server/main.go:19:56:19:61 | SSA def(params) | user-provided value |
|
||||||
edges
|
edges
|
||||||
| client/main.go:16:35:16:78 | &... | server/main.go:19:109:38:1 | SSA def(params) | provenance | |
|
| client/main.go:16:35:16:78 | &... | server/main.go:19:56:19:61 | SSA def(params) | provenance | |
|
||||||
| client/main.go:16:35:16:78 | &... [postupdate] | client/main.go:16:35:16:78 | &... | provenance | |
|
| client/main.go:16:35:16:78 | &... [postupdate] | client/main.go:16:35:16:78 | &... | provenance | |
|
||||||
| rpc/notes/service.twirp.go:538:2:538:33 | extract:0 ... := ... | rpc/notes/service.twirp.go:544:27:544:29 | buf | provenance | |
|
| rpc/notes/service.twirp.go:538:2:538:33 | ... := ...[0] | rpc/notes/service.twirp.go:544:27:544:29 | buf | provenance | |
|
||||||
| rpc/notes/service.twirp.go:538:25:538:32 | selection of Body | rpc/notes/service.twirp.go:538:2:538:33 | extract:0 ... := ... | provenance | Src:MaD:1 MaD:3 |
|
| rpc/notes/service.twirp.go:538:25:538:32 | selection of Body | rpc/notes/service.twirp.go:538:2:538:33 | ... := ...[0] | provenance | Src:MaD:1 MaD:3 |
|
||||||
| rpc/notes/service.twirp.go:544:27:544:29 | buf | rpc/notes/service.twirp.go:544:32:544:41 | reqContent [postupdate] | provenance | MaD:2 |
|
| rpc/notes/service.twirp.go:544:27:544:29 | buf | rpc/notes/service.twirp.go:544:32:544:41 | reqContent [postupdate] | provenance | MaD:2 |
|
||||||
| rpc/notes/service.twirp.go:544:32:544:41 | reqContent [postupdate] | rpc/notes/service.twirp.go:574:2:577:2 | SSA def(reqContent) | provenance | |
|
| rpc/notes/service.twirp.go:544:32:544:41 | reqContent [postupdate] | rpc/notes/service.twirp.go:574:2:577:2 | SSA def(reqContent) | provenance | |
|
||||||
| rpc/notes/service.twirp.go:574:2:577:2 | SSA def(reqContent) | rpc/notes/service.twirp.go:576:35:576:44 | reqContent | provenance | |
|
| rpc/notes/service.twirp.go:574:2:577:2 | SSA def(reqContent) | rpc/notes/service.twirp.go:576:35:576:44 | reqContent | provenance | |
|
||||||
| rpc/notes/service.twirp.go:576:35:576:44 | reqContent | server/main.go:19:109:38:1 | SSA def(params) | provenance | |
|
| rpc/notes/service.twirp.go:576:35:576:44 | reqContent | server/main.go:19:56:19:61 | SSA def(params) | provenance | |
|
||||||
| server/main.go:19:109:38:1 | SSA def(params) | server/main.go:19:109:38:1 | SSA def(params) [Return] | provenance | |
|
| server/main.go:19:56:19:61 | SSA def(params) | server/main.go:19:56:19:61 | SSA def(params) [Return] | provenance | |
|
||||||
| server/main.go:19:109:38:1 | SSA def(params) | server/main.go:30:38:30:48 | selection of Text | provenance | |
|
| server/main.go:19:56:19:61 | SSA def(params) | server/main.go:30:38:30:48 | selection of Text | provenance | |
|
||||||
| server/main.go:19:109:38:1 | SSA def(params) | server/main.go:30:38:30:48 | selection of Text | provenance | |
|
| server/main.go:19:56:19:61 | SSA def(params) | server/main.go:30:38:30:48 | selection of Text | provenance | |
|
||||||
| server/main.go:19:109:38:1 | SSA def(params) [Return] | client/main.go:16:35:16:78 | &... [postupdate] | provenance | |
|
| server/main.go:19:56:19:61 | SSA def(params) [Return] | client/main.go:16:35:16:78 | &... [postupdate] | provenance | |
|
||||||
models
|
models
|
||||||
| 1 | Source: net/http; Request; true; Body; ; ; ; remote; manual |
|
| 1 | Source: net/http; Request; true; Body; ; ; ; remote; manual |
|
||||||
| 2 | Summary: google.golang.org/protobuf/proto; ; false; Unmarshal; ; ; Argument[0]; Argument[1]; taint; manual |
|
| 2 | Summary: google.golang.org/protobuf/proto; ; false; Unmarshal; ; ; Argument[0]; Argument[1]; taint; manual |
|
||||||
@@ -21,17 +21,14 @@ models
|
|||||||
nodes
|
nodes
|
||||||
| client/main.go:16:35:16:78 | &... | semmle.label | &... |
|
| client/main.go:16:35:16:78 | &... | semmle.label | &... |
|
||||||
| client/main.go:16:35:16:78 | &... [postupdate] | semmle.label | &... [postupdate] |
|
| client/main.go:16:35:16:78 | &... [postupdate] | semmle.label | &... [postupdate] |
|
||||||
| rpc/notes/service.twirp.go:538:2:538:33 | extract:0 ... := ... | semmle.label | extract:0 ... := ... |
|
| rpc/notes/service.twirp.go:538:2:538:33 | ... := ...[0] | semmle.label | ... := ...[0] |
|
||||||
| rpc/notes/service.twirp.go:538:25:538:32 | selection of Body | semmle.label | selection of Body |
|
| rpc/notes/service.twirp.go:538:25:538:32 | selection of Body | semmle.label | selection of Body |
|
||||||
| rpc/notes/service.twirp.go:544:27:544:29 | buf | semmle.label | buf |
|
| rpc/notes/service.twirp.go:544:27:544:29 | buf | semmle.label | buf |
|
||||||
| rpc/notes/service.twirp.go:544:32:544:41 | reqContent [postupdate] | semmle.label | reqContent [postupdate] |
|
| rpc/notes/service.twirp.go:544:32:544:41 | reqContent [postupdate] | semmle.label | reqContent [postupdate] |
|
||||||
| rpc/notes/service.twirp.go:574:2:577:2 | SSA def(reqContent) | semmle.label | SSA def(reqContent) |
|
| rpc/notes/service.twirp.go:574:2:577:2 | SSA def(reqContent) | semmle.label | SSA def(reqContent) |
|
||||||
| rpc/notes/service.twirp.go:576:35:576:44 | reqContent | semmle.label | reqContent |
|
| rpc/notes/service.twirp.go:576:35:576:44 | reqContent | semmle.label | reqContent |
|
||||||
| server/main.go:19:109:38:1 | SSA def(params) | semmle.label | SSA def(params) |
|
| server/main.go:19:56:19:61 | SSA def(params) | semmle.label | SSA def(params) |
|
||||||
| server/main.go:19:109:38:1 | SSA def(params) | semmle.label | SSA def(params) |
|
| server/main.go:19:56:19:61 | SSA def(params) | semmle.label | SSA def(params) |
|
||||||
| server/main.go:19:109:38:1 | SSA def(params) [Return] | semmle.label | SSA def(params) [Return] |
|
| server/main.go:19:56:19:61 | SSA def(params) [Return] | semmle.label | SSA def(params) [Return] |
|
||||||
| server/main.go:30:38:30:48 | selection of Text | semmle.label | selection of Text |
|
| server/main.go:30:38:30:48 | selection of Text | semmle.label | selection of Text |
|
||||||
subpaths
|
subpaths
|
||||||
testFailures
|
|
||||||
| server/main.go:19:109:38:1 | SSA def(params) | Unexpected result: Source |
|
|
||||||
| server/main.go:19:111:19:154 | comment | Missing result: Source |
|
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
| tests.go:61:30:61:35 | result | $@ may be nil at this dereference because $@ may not have been checked. | tests.go:59:2:59:30 | SSA def(result) | result | tests.go:59:2:59:30 | SSA def(err) | err |
|
| tests.go:61:30:61:35 | result | $@ may be nil at this dereference because $@ may not have been checked. | tests.go:59:2:59:7 | SSA def(result) | result | tests.go:59:10:59:12 | SSA def(err) | err |
|
||||||
| tests.go:243:27:243:32 | result | $@ may be nil at this dereference because $@ may not have been checked. | tests.go:241:2:241:37 | SSA def(result) | result | tests.go:241:2:241:37 | SSA def(err) | err |
|
| tests.go:243:27:243:32 | result | $@ may be nil at this dereference because $@ may not have been checked. | tests.go:241:2:241:7 | SSA def(result) | result | tests.go:241:10:241:12 | SSA def(err) | err |
|
||||||
|
|||||||
@@ -1,52 +1,52 @@
|
|||||||
#select
|
#select
|
||||||
| tests.go:10:8:10:8 | f | tests.go:32:5:32:78 | extract:0 ... := ... | tests.go:10:8:10:8 | f | File handle may be writable as a result of data flow from a $@ and closing it may result in data loss upon failure, which is not handled explicitly. | tests.go:32:15:32:78 | call to OpenFile | call to OpenFile |
|
| tests.go:10:8:10:8 | f | tests.go:32:5:32:78 | ... := ...[0] | tests.go:10:8:10:8 | f | File handle may be writable as a result of data flow from a $@ and closing it may result in data loss upon failure, which is not handled explicitly. | tests.go:32:15:32:78 | call to OpenFile | call to OpenFile |
|
||||||
| tests.go:10:8:10:8 | f | tests.go:46:5:46:76 | extract:0 ... := ... | tests.go:10:8:10:8 | f | File handle may be writable as a result of data flow from a $@ and closing it may result in data loss upon failure, which is not handled explicitly. | tests.go:46:15:46:76 | call to OpenFile | call to OpenFile |
|
| tests.go:10:8:10:8 | f | tests.go:46:5:46:76 | ... := ...[0] | tests.go:10:8:10:8 | f | File handle may be writable as a result of data flow from a $@ and closing it may result in data loss upon failure, which is not handled explicitly. | tests.go:46:15:46:76 | call to OpenFile | call to OpenFile |
|
||||||
| tests.go:15:3:15:3 | f | tests.go:32:5:32:78 | extract:0 ... := ... | tests.go:15:3:15:3 | f | File handle may be writable as a result of data flow from a $@ and closing it may result in data loss upon failure, which is not handled explicitly. | tests.go:32:15:32:78 | call to OpenFile | call to OpenFile |
|
| tests.go:15:3:15:3 | f | tests.go:32:5:32:78 | ... := ...[0] | tests.go:15:3:15:3 | f | File handle may be writable as a result of data flow from a $@ and closing it may result in data loss upon failure, which is not handled explicitly. | tests.go:32:15:32:78 | call to OpenFile | call to OpenFile |
|
||||||
| tests.go:15:3:15:3 | f | tests.go:46:5:46:76 | extract:0 ... := ... | tests.go:15:3:15:3 | f | File handle may be writable as a result of data flow from a $@ and closing it may result in data loss upon failure, which is not handled explicitly. | tests.go:46:15:46:76 | call to OpenFile | call to OpenFile |
|
| tests.go:15:3:15:3 | f | tests.go:46:5:46:76 | ... := ...[0] | tests.go:15:3:15:3 | f | File handle may be writable as a result of data flow from a $@ and closing it may result in data loss upon failure, which is not handled explicitly. | tests.go:46:15:46:76 | call to OpenFile | call to OpenFile |
|
||||||
| tests.go:57:3:57:3 | f | tests.go:55:5:55:78 | extract:0 ... := ... | tests.go:57:3:57:3 | f | File handle may be writable as a result of data flow from a $@ and closing it may result in data loss upon failure, which is not handled explicitly. | tests.go:55:15:55:78 | call to OpenFile | call to OpenFile |
|
| tests.go:57:3:57:3 | f | tests.go:55:5:55:78 | ... := ...[0] | tests.go:57:3:57:3 | f | File handle may be writable as a result of data flow from a $@ and closing it may result in data loss upon failure, which is not handled explicitly. | tests.go:55:15:55:78 | call to OpenFile | call to OpenFile |
|
||||||
| tests.go:69:3:69:3 | f | tests.go:67:5:67:76 | extract:0 ... := ... | tests.go:69:3:69:3 | f | File handle may be writable as a result of data flow from a $@ and closing it may result in data loss upon failure, which is not handled explicitly. | tests.go:67:15:67:76 | call to OpenFile | call to OpenFile |
|
| tests.go:69:3:69:3 | f | tests.go:67:5:67:76 | ... := ...[0] | tests.go:69:3:69:3 | f | File handle may be writable as a result of data flow from a $@ and closing it may result in data loss upon failure, which is not handled explicitly. | tests.go:67:15:67:76 | call to OpenFile | call to OpenFile |
|
||||||
| tests.go:126:9:126:9 | f | tests.go:124:5:124:78 | extract:0 ... := ... | tests.go:126:9:126:9 | f | File handle may be writable as a result of data flow from a $@ and closing it may result in data loss upon failure, which is not handled explicitly. | tests.go:124:15:124:78 | call to OpenFile | call to OpenFile |
|
| tests.go:126:9:126:9 | f | tests.go:124:5:124:78 | ... := ...[0] | tests.go:126:9:126:9 | f | File handle may be writable as a result of data flow from a $@ and closing it may result in data loss upon failure, which is not handled explicitly. | tests.go:124:15:124:78 | call to OpenFile | call to OpenFile |
|
||||||
| tests.go:145:3:145:3 | f | tests.go:141:5:141:78 | extract:0 ... := ... | tests.go:145:3:145:3 | f | File handle may be writable as a result of data flow from a $@ and closing it may result in data loss upon failure, which is not handled explicitly. | tests.go:141:15:141:78 | call to OpenFile | call to OpenFile |
|
| tests.go:145:3:145:3 | f | tests.go:141:5:141:78 | ... := ...[0] | tests.go:145:3:145:3 | f | File handle may be writable as a result of data flow from a $@ and closing it may result in data loss upon failure, which is not handled explicitly. | tests.go:141:15:141:78 | call to OpenFile | call to OpenFile |
|
||||||
| tests.go:166:8:166:8 | f | tests.go:162:2:162:74 | extract:0 ... := ... | tests.go:166:8:166:8 | f | File handle may be writable as a result of data flow from a $@ and closing it may result in data loss upon failure, which is not handled explicitly. | tests.go:162:12:162:74 | call to OpenFile | call to OpenFile |
|
| tests.go:166:8:166:8 | f | tests.go:162:2:162:74 | ... := ...[0] | tests.go:166:8:166:8 | f | File handle may be writable as a result of data flow from a $@ and closing it may result in data loss upon failure, which is not handled explicitly. | tests.go:162:12:162:74 | call to OpenFile | call to OpenFile |
|
||||||
edges
|
edges
|
||||||
| tests.go:9:36:11:1 | SSA def(f) | tests.go:10:8:10:8 | f | provenance | |
|
| tests.go:9:24:9:24 | SSA def(f) | tests.go:10:8:10:8 | f | provenance | |
|
||||||
| tests.go:13:44:19:1 | SSA def(f) | tests.go:14:13:16:2 | SSA def(f) | provenance | |
|
| tests.go:13:32:13:32 | SSA def(f) | tests.go:14:13:16:2 | SSA def(f) | provenance | |
|
||||||
| tests.go:14:13:16:2 | SSA def(f) | tests.go:15:3:15:3 | f | provenance | |
|
| tests.go:14:13:16:2 | SSA def(f) | tests.go:15:3:15:3 | f | provenance | |
|
||||||
| tests.go:32:5:32:78 | extract:0 ... := ... | tests.go:33:21:33:21 | f | provenance | Src:MaD:1 |
|
| tests.go:32:5:32:78 | ... := ...[0] | tests.go:33:21:33:21 | f | provenance | Src:MaD:1 |
|
||||||
| tests.go:32:5:32:78 | extract:0 ... := ... | tests.go:34:29:34:29 | f | provenance | Src:MaD:1 |
|
| tests.go:32:5:32:78 | ... := ...[0] | tests.go:34:29:34:29 | f | provenance | Src:MaD:1 |
|
||||||
| tests.go:33:21:33:21 | f | tests.go:9:36:11:1 | SSA def(f) | provenance | |
|
| tests.go:33:21:33:21 | f | tests.go:9:24:9:24 | SSA def(f) | provenance | |
|
||||||
| tests.go:34:29:34:29 | f | tests.go:13:44:19:1 | SSA def(f) | provenance | |
|
| tests.go:34:29:34:29 | f | tests.go:13:32:13:32 | SSA def(f) | provenance | |
|
||||||
| tests.go:46:5:46:76 | extract:0 ... := ... | tests.go:47:21:47:21 | f | provenance | Src:MaD:1 |
|
| tests.go:46:5:46:76 | ... := ...[0] | tests.go:47:21:47:21 | f | provenance | Src:MaD:1 |
|
||||||
| tests.go:46:5:46:76 | extract:0 ... := ... | tests.go:48:29:48:29 | f | provenance | Src:MaD:1 |
|
| tests.go:46:5:46:76 | ... := ...[0] | tests.go:48:29:48:29 | f | provenance | Src:MaD:1 |
|
||||||
| tests.go:47:21:47:21 | f | tests.go:9:36:11:1 | SSA def(f) | provenance | |
|
| tests.go:47:21:47:21 | f | tests.go:9:24:9:24 | SSA def(f) | provenance | |
|
||||||
| tests.go:48:29:48:29 | f | tests.go:13:44:19:1 | SSA def(f) | provenance | |
|
| tests.go:48:29:48:29 | f | tests.go:13:32:13:32 | SSA def(f) | provenance | |
|
||||||
| tests.go:55:5:55:78 | extract:0 ... := ... | tests.go:57:3:57:3 | f | provenance | Src:MaD:1 |
|
| tests.go:55:5:55:78 | ... := ...[0] | tests.go:57:3:57:3 | f | provenance | Src:MaD:1 |
|
||||||
| tests.go:67:5:67:76 | extract:0 ... := ... | tests.go:69:3:69:3 | f | provenance | Src:MaD:1 |
|
| tests.go:67:5:67:76 | ... := ...[0] | tests.go:69:3:69:3 | f | provenance | Src:MaD:1 |
|
||||||
| tests.go:124:5:124:78 | extract:0 ... := ... | tests.go:126:9:126:9 | f | provenance | Src:MaD:1 |
|
| tests.go:124:5:124:78 | ... := ...[0] | tests.go:126:9:126:9 | f | provenance | Src:MaD:1 |
|
||||||
| tests.go:141:5:141:78 | extract:0 ... := ... | tests.go:145:3:145:3 | f | provenance | Src:MaD:1 |
|
| tests.go:141:5:141:78 | ... := ...[0] | tests.go:145:3:145:3 | f | provenance | Src:MaD:1 |
|
||||||
| tests.go:162:2:162:74 | extract:0 ... := ... | tests.go:166:8:166:8 | f | provenance | Src:MaD:1 |
|
| tests.go:162:2:162:74 | ... := ...[0] | tests.go:166:8:166:8 | f | provenance | Src:MaD:1 |
|
||||||
models
|
models
|
||||||
| 1 | Source: os; ; false; OpenFile; ; ; ReturnValue[0]; file; manual |
|
| 1 | Source: os; ; false; OpenFile; ; ; ReturnValue[0]; file; manual |
|
||||||
nodes
|
nodes
|
||||||
| tests.go:9:36:11:1 | SSA def(f) | semmle.label | SSA def(f) |
|
| tests.go:9:24:9:24 | SSA def(f) | semmle.label | SSA def(f) |
|
||||||
| tests.go:10:8:10:8 | f | semmle.label | f |
|
| tests.go:10:8:10:8 | f | semmle.label | f |
|
||||||
| tests.go:13:44:19:1 | SSA def(f) | semmle.label | SSA def(f) |
|
| tests.go:13:32:13:32 | SSA def(f) | semmle.label | SSA def(f) |
|
||||||
| tests.go:14:13:16:2 | SSA def(f) | semmle.label | SSA def(f) |
|
| tests.go:14:13:16:2 | SSA def(f) | semmle.label | SSA def(f) |
|
||||||
| tests.go:15:3:15:3 | f | semmle.label | f |
|
| tests.go:15:3:15:3 | f | semmle.label | f |
|
||||||
| tests.go:32:5:32:78 | extract:0 ... := ... | semmle.label | extract:0 ... := ... |
|
| tests.go:32:5:32:78 | ... := ...[0] | semmle.label | ... := ...[0] |
|
||||||
| tests.go:33:21:33:21 | f | semmle.label | f |
|
| tests.go:33:21:33:21 | f | semmle.label | f |
|
||||||
| tests.go:34:29:34:29 | f | semmle.label | f |
|
| tests.go:34:29:34:29 | f | semmle.label | f |
|
||||||
| tests.go:46:5:46:76 | extract:0 ... := ... | semmle.label | extract:0 ... := ... |
|
| tests.go:46:5:46:76 | ... := ...[0] | semmle.label | ... := ...[0] |
|
||||||
| tests.go:47:21:47:21 | f | semmle.label | f |
|
| tests.go:47:21:47:21 | f | semmle.label | f |
|
||||||
| tests.go:48:29:48:29 | f | semmle.label | f |
|
| tests.go:48:29:48:29 | f | semmle.label | f |
|
||||||
| tests.go:55:5:55:78 | extract:0 ... := ... | semmle.label | extract:0 ... := ... |
|
| tests.go:55:5:55:78 | ... := ...[0] | semmle.label | ... := ...[0] |
|
||||||
| tests.go:57:3:57:3 | f | semmle.label | f |
|
| tests.go:57:3:57:3 | f | semmle.label | f |
|
||||||
| tests.go:67:5:67:76 | extract:0 ... := ... | semmle.label | extract:0 ... := ... |
|
| tests.go:67:5:67:76 | ... := ...[0] | semmle.label | ... := ...[0] |
|
||||||
| tests.go:69:3:69:3 | f | semmle.label | f |
|
| tests.go:69:3:69:3 | f | semmle.label | f |
|
||||||
| tests.go:124:5:124:78 | extract:0 ... := ... | semmle.label | extract:0 ... := ... |
|
| tests.go:124:5:124:78 | ... := ...[0] | semmle.label | ... := ...[0] |
|
||||||
| tests.go:126:9:126:9 | f | semmle.label | f |
|
| tests.go:126:9:126:9 | f | semmle.label | f |
|
||||||
| tests.go:141:5:141:78 | extract:0 ... := ... | semmle.label | extract:0 ... := ... |
|
| tests.go:141:5:141:78 | ... := ...[0] | semmle.label | ... := ...[0] |
|
||||||
| tests.go:145:3:145:3 | f | semmle.label | f |
|
| tests.go:145:3:145:3 | f | semmle.label | f |
|
||||||
| tests.go:162:2:162:74 | extract:0 ... := ... | semmle.label | extract:0 ... := ... |
|
| tests.go:162:2:162:74 | ... := ...[0] | semmle.label | ... := ...[0] |
|
||||||
| tests.go:166:8:166:8 | f | semmle.label | f |
|
| tests.go:166:8:166:8 | f | semmle.label | f |
|
||||||
subpaths
|
subpaths
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
| DeadStoreOfField.go:8:2:8:10 | assign:0 ... = ... | This assignment to val is useless since its value is never read. |
|
| DeadStoreOfField.go:8:2:8:6 | assignment to field val | This assignment to val is useless since its value is never read. |
|
||||||
|
|||||||
@@ -5,18 +5,18 @@
|
|||||||
| UnsafeUnzipSymlink.go:126:17:126:31 | selection of Linkname | UnsafeUnzipSymlink.go:126:17:126:31 | selection of Linkname | UnsafeUnzipSymlink.go:112:13:112:20 | linkName | Unresolved path from an archive header, which may point outside the archive root, is used in $@. | UnsafeUnzipSymlink.go:112:13:112:20 | linkName | symlink creation |
|
| UnsafeUnzipSymlink.go:126:17:126:31 | selection of Linkname | UnsafeUnzipSymlink.go:126:17:126:31 | selection of Linkname | UnsafeUnzipSymlink.go:112:13:112:20 | linkName | Unresolved path from an archive header, which may point outside the archive root, is used in $@. | UnsafeUnzipSymlink.go:112:13:112:20 | linkName | symlink creation |
|
||||||
| UnsafeUnzipSymlink.go:126:34:126:44 | selection of Name | UnsafeUnzipSymlink.go:126:34:126:44 | selection of Name | UnsafeUnzipSymlink.go:112:23:112:30 | fileName | Unresolved path from an archive header, which may point outside the archive root, is used in $@. | UnsafeUnzipSymlink.go:112:23:112:30 | fileName | symlink creation |
|
| UnsafeUnzipSymlink.go:126:34:126:44 | selection of Name | UnsafeUnzipSymlink.go:126:34:126:44 | selection of Name | UnsafeUnzipSymlink.go:112:23:112:30 | fileName | Unresolved path from an archive header, which may point outside the archive root, is used in $@. | UnsafeUnzipSymlink.go:112:23:112:30 | fileName | symlink creation |
|
||||||
edges
|
edges
|
||||||
| UnsafeUnzipSymlink.go:111:46:113:1 | SSA def(fileName) | UnsafeUnzipSymlink.go:112:23:112:30 | fileName | provenance | Sink:MaD:1 |
|
| UnsafeUnzipSymlink.go:111:19:111:26 | SSA def(linkName) | UnsafeUnzipSymlink.go:112:13:112:20 | linkName | provenance | Sink:MaD:1 |
|
||||||
| UnsafeUnzipSymlink.go:111:46:113:1 | SSA def(linkName) | UnsafeUnzipSymlink.go:112:13:112:20 | linkName | provenance | Sink:MaD:1 |
|
| UnsafeUnzipSymlink.go:111:29:111:36 | SSA def(fileName) | UnsafeUnzipSymlink.go:112:23:112:30 | fileName | provenance | Sink:MaD:1 |
|
||||||
| UnsafeUnzipSymlink.go:126:17:126:31 | selection of Linkname | UnsafeUnzipSymlink.go:111:46:113:1 | SSA def(linkName) | provenance | |
|
| UnsafeUnzipSymlink.go:126:17:126:31 | selection of Linkname | UnsafeUnzipSymlink.go:111:19:111:26 | SSA def(linkName) | provenance | |
|
||||||
| UnsafeUnzipSymlink.go:126:34:126:44 | selection of Name | UnsafeUnzipSymlink.go:111:46:113:1 | SSA def(fileName) | provenance | |
|
| UnsafeUnzipSymlink.go:126:34:126:44 | selection of Name | UnsafeUnzipSymlink.go:111:29:111:36 | SSA def(fileName) | provenance | |
|
||||||
models
|
models
|
||||||
| 1 | Sink: os; ; false; Symlink; ; ; Argument[0..1]; path-injection; manual |
|
| 1 | Sink: os; ; false; Symlink; ; ; Argument[0..1]; path-injection; manual |
|
||||||
nodes
|
nodes
|
||||||
| UnsafeUnzipSymlink.go:31:15:31:29 | selection of Linkname | semmle.label | selection of Linkname |
|
| UnsafeUnzipSymlink.go:31:15:31:29 | selection of Linkname | semmle.label | selection of Linkname |
|
||||||
| UnsafeUnzipSymlink.go:31:32:31:42 | selection of Name | semmle.label | selection of Name |
|
| UnsafeUnzipSymlink.go:31:32:31:42 | selection of Name | semmle.label | selection of Name |
|
||||||
| UnsafeUnzipSymlink.go:43:25:43:35 | selection of Name | semmle.label | selection of Name |
|
| UnsafeUnzipSymlink.go:43:25:43:35 | selection of Name | semmle.label | selection of Name |
|
||||||
| UnsafeUnzipSymlink.go:111:46:113:1 | SSA def(fileName) | semmle.label | SSA def(fileName) |
|
| UnsafeUnzipSymlink.go:111:19:111:26 | SSA def(linkName) | semmle.label | SSA def(linkName) |
|
||||||
| UnsafeUnzipSymlink.go:111:46:113:1 | SSA def(linkName) | semmle.label | SSA def(linkName) |
|
| UnsafeUnzipSymlink.go:111:29:111:36 | SSA def(fileName) | semmle.label | SSA def(fileName) |
|
||||||
| UnsafeUnzipSymlink.go:112:13:112:20 | linkName | semmle.label | linkName |
|
| UnsafeUnzipSymlink.go:112:13:112:20 | linkName | semmle.label | linkName |
|
||||||
| UnsafeUnzipSymlink.go:112:23:112:30 | fileName | semmle.label | fileName |
|
| UnsafeUnzipSymlink.go:112:23:112:30 | fileName | semmle.label | fileName |
|
||||||
| UnsafeUnzipSymlink.go:126:17:126:31 | selection of Linkname | semmle.label | selection of Linkname |
|
| UnsafeUnzipSymlink.go:126:17:126:31 | selection of Linkname | semmle.label | selection of Linkname |
|
||||||
|
|||||||
@@ -1,21 +1,21 @@
|
|||||||
#select
|
#select
|
||||||
| UnsafeUnzipSymlinkGood.go:72:3:72:25 | extract:0 ... := ... | UnsafeUnzipSymlinkGood.go:72:3:72:25 | extract:0 ... := ... | UnsafeUnzipSymlinkGood.go:61:31:61:62 | call to Join | Unsanitized archive entry, which may contain '..', is used in a $@. | UnsafeUnzipSymlinkGood.go:61:31:61:62 | call to Join | file system operation |
|
| UnsafeUnzipSymlinkGood.go:72:3:72:25 | ... := ...[0] | UnsafeUnzipSymlinkGood.go:72:3:72:25 | ... := ...[0] | UnsafeUnzipSymlinkGood.go:61:31:61:62 | call to Join | Unsanitized archive entry, which may contain '..', is used in a $@. | UnsafeUnzipSymlinkGood.go:61:31:61:62 | call to Join | file system operation |
|
||||||
| ZipSlip.go:11:2:15:2 | extract:1 range statement | ZipSlip.go:11:2:15:2 | extract:1 range statement | ZipSlip.go:14:20:14:20 | p | Unsanitized archive entry, which may contain '..', is used in a $@. | ZipSlip.go:14:20:14:20 | p | file system operation |
|
| ZipSlip.go:11:2:15:2 | range statement[1] | ZipSlip.go:11:2:15:2 | range statement[1] | ZipSlip.go:14:20:14:20 | p | Unsanitized archive entry, which may contain '..', is used in a $@. | ZipSlip.go:14:20:14:20 | p | file system operation |
|
||||||
| tarslip.go:15:2:15:30 | extract:0 ... := ... | tarslip.go:15:2:15:30 | extract:0 ... := ... | tarslip.go:16:14:16:34 | call to Dir | Unsanitized archive entry, which may contain '..', is used in a $@. | tarslip.go:16:14:16:34 | call to Dir | file system operation |
|
| tarslip.go:15:2:15:30 | ... := ...[0] | tarslip.go:15:2:15:30 | ... := ...[0] | tarslip.go:16:14:16:34 | call to Dir | Unsanitized archive entry, which may contain '..', is used in a $@. | tarslip.go:16:14:16:34 | call to Dir | file system operation |
|
||||||
| tst.go:23:2:43:2 | extract:1 range statement | tst.go:23:2:43:2 | extract:1 range statement | tst.go:29:20:29:23 | path | Unsanitized archive entry, which may contain '..', is used in a $@. | tst.go:29:20:29:23 | path | file system operation |
|
| tst.go:23:2:43:2 | range statement[1] | tst.go:23:2:43:2 | range statement[1] | tst.go:29:20:29:23 | path | Unsanitized archive entry, which may contain '..', is used in a $@. | tst.go:29:20:29:23 | path | file system operation |
|
||||||
edges
|
edges
|
||||||
| UnsafeUnzipSymlinkGood.go:52:55:67:1 | SSA def(candidate) | UnsafeUnzipSymlinkGood.go:61:53:61:61 | candidate | provenance | |
|
| UnsafeUnzipSymlinkGood.go:52:24:52:32 | SSA def(candidate) | UnsafeUnzipSymlinkGood.go:61:53:61:61 | candidate | provenance | |
|
||||||
| UnsafeUnzipSymlinkGood.go:61:53:61:61 | candidate | UnsafeUnzipSymlinkGood.go:61:31:61:62 | call to Join | provenance | FunctionModel Sink:MaD:3 |
|
| UnsafeUnzipSymlinkGood.go:61:53:61:61 | candidate | UnsafeUnzipSymlinkGood.go:61:31:61:62 | call to Join | provenance | FunctionModel Sink:MaD:3 |
|
||||||
| UnsafeUnzipSymlinkGood.go:72:3:72:25 | extract:0 ... := ... | UnsafeUnzipSymlinkGood.go:76:24:76:38 | selection of Linkname | provenance | |
|
| UnsafeUnzipSymlinkGood.go:72:3:72:25 | ... := ...[0] | UnsafeUnzipSymlinkGood.go:76:24:76:38 | selection of Linkname | provenance | |
|
||||||
| UnsafeUnzipSymlinkGood.go:72:3:72:25 | extract:0 ... := ... | UnsafeUnzipSymlinkGood.go:76:70:76:80 | selection of Name | provenance | |
|
| UnsafeUnzipSymlinkGood.go:72:3:72:25 | ... := ...[0] | UnsafeUnzipSymlinkGood.go:76:70:76:80 | selection of Name | provenance | |
|
||||||
| UnsafeUnzipSymlinkGood.go:76:24:76:38 | selection of Linkname | UnsafeUnzipSymlinkGood.go:52:55:67:1 | SSA def(candidate) | provenance | |
|
| UnsafeUnzipSymlinkGood.go:76:24:76:38 | selection of Linkname | UnsafeUnzipSymlinkGood.go:52:24:52:32 | SSA def(candidate) | provenance | |
|
||||||
| UnsafeUnzipSymlinkGood.go:76:70:76:80 | selection of Name | UnsafeUnzipSymlinkGood.go:52:55:67:1 | SSA def(candidate) | provenance | |
|
| UnsafeUnzipSymlinkGood.go:76:70:76:80 | selection of Name | UnsafeUnzipSymlinkGood.go:52:24:52:32 | SSA def(candidate) | provenance | |
|
||||||
| ZipSlip.go:11:2:15:2 | extract:1 range statement | ZipSlip.go:12:24:12:29 | selection of Name | provenance | |
|
| ZipSlip.go:11:2:15:2 | range statement[1] | ZipSlip.go:12:24:12:29 | selection of Name | provenance | |
|
||||||
| ZipSlip.go:12:3:12:30 | extract:0 ... := ... | ZipSlip.go:14:20:14:20 | p | provenance | Sink:MaD:1 |
|
| ZipSlip.go:12:3:12:30 | ... := ...[0] | ZipSlip.go:14:20:14:20 | p | provenance | Sink:MaD:1 |
|
||||||
| ZipSlip.go:12:24:12:29 | selection of Name | ZipSlip.go:12:3:12:30 | extract:0 ... := ... | provenance | MaD:4 |
|
| ZipSlip.go:12:24:12:29 | selection of Name | ZipSlip.go:12:3:12:30 | ... := ...[0] | provenance | MaD:4 |
|
||||||
| tarslip.go:15:2:15:30 | extract:0 ... := ... | tarslip.go:16:23:16:33 | selection of Name | provenance | |
|
| tarslip.go:15:2:15:30 | ... := ...[0] | tarslip.go:16:23:16:33 | selection of Name | provenance | |
|
||||||
| tarslip.go:16:23:16:33 | selection of Name | tarslip.go:16:14:16:34 | call to Dir | provenance | MaD:5 Sink:MaD:2 |
|
| tarslip.go:16:23:16:33 | selection of Name | tarslip.go:16:14:16:34 | call to Dir | provenance | MaD:5 Sink:MaD:2 |
|
||||||
| tst.go:23:2:43:2 | extract:1 range statement | tst.go:29:20:29:23 | path | provenance | Sink:MaD:1 |
|
| tst.go:23:2:43:2 | range statement[1] | tst.go:29:20:29:23 | path | provenance | Sink:MaD:1 |
|
||||||
models
|
models
|
||||||
| 1 | Sink: io/ioutil; ; false; WriteFile; ; ; Argument[0]; path-injection; manual |
|
| 1 | Sink: io/ioutil; ; false; WriteFile; ; ; Argument[0]; path-injection; manual |
|
||||||
| 2 | Sink: os; ; false; MkdirAll; ; ; Argument[0]; path-injection; manual |
|
| 2 | Sink: os; ; false; MkdirAll; ; ; Argument[0]; path-injection; manual |
|
||||||
@@ -23,19 +23,19 @@ models
|
|||||||
| 4 | Summary: path/filepath; ; false; Abs; ; ; Argument[0]; ReturnValue[0]; taint; manual |
|
| 4 | Summary: path/filepath; ; false; Abs; ; ; Argument[0]; ReturnValue[0]; taint; manual |
|
||||||
| 5 | Summary: path; ; false; Dir; ; ; Argument[0]; ReturnValue; taint; manual |
|
| 5 | Summary: path; ; false; Dir; ; ; Argument[0]; ReturnValue; taint; manual |
|
||||||
nodes
|
nodes
|
||||||
| UnsafeUnzipSymlinkGood.go:52:55:67:1 | SSA def(candidate) | semmle.label | SSA def(candidate) |
|
| UnsafeUnzipSymlinkGood.go:52:24:52:32 | SSA def(candidate) | semmle.label | SSA def(candidate) |
|
||||||
| UnsafeUnzipSymlinkGood.go:61:31:61:62 | call to Join | semmle.label | call to Join |
|
| UnsafeUnzipSymlinkGood.go:61:31:61:62 | call to Join | semmle.label | call to Join |
|
||||||
| UnsafeUnzipSymlinkGood.go:61:53:61:61 | candidate | semmle.label | candidate |
|
| UnsafeUnzipSymlinkGood.go:61:53:61:61 | candidate | semmle.label | candidate |
|
||||||
| UnsafeUnzipSymlinkGood.go:72:3:72:25 | extract:0 ... := ... | semmle.label | extract:0 ... := ... |
|
| UnsafeUnzipSymlinkGood.go:72:3:72:25 | ... := ...[0] | semmle.label | ... := ...[0] |
|
||||||
| UnsafeUnzipSymlinkGood.go:76:24:76:38 | selection of Linkname | semmle.label | selection of Linkname |
|
| UnsafeUnzipSymlinkGood.go:76:24:76:38 | selection of Linkname | semmle.label | selection of Linkname |
|
||||||
| UnsafeUnzipSymlinkGood.go:76:70:76:80 | selection of Name | semmle.label | selection of Name |
|
| UnsafeUnzipSymlinkGood.go:76:70:76:80 | selection of Name | semmle.label | selection of Name |
|
||||||
| ZipSlip.go:11:2:15:2 | extract:1 range statement | semmle.label | extract:1 range statement |
|
| ZipSlip.go:11:2:15:2 | range statement[1] | semmle.label | range statement[1] |
|
||||||
| ZipSlip.go:12:3:12:30 | extract:0 ... := ... | semmle.label | extract:0 ... := ... |
|
| ZipSlip.go:12:3:12:30 | ... := ...[0] | semmle.label | ... := ...[0] |
|
||||||
| ZipSlip.go:12:24:12:29 | selection of Name | semmle.label | selection of Name |
|
| ZipSlip.go:12:24:12:29 | selection of Name | semmle.label | selection of Name |
|
||||||
| ZipSlip.go:14:20:14:20 | p | semmle.label | p |
|
| ZipSlip.go:14:20:14:20 | p | semmle.label | p |
|
||||||
| tarslip.go:15:2:15:30 | extract:0 ... := ... | semmle.label | extract:0 ... := ... |
|
| tarslip.go:15:2:15:30 | ... := ...[0] | semmle.label | ... := ...[0] |
|
||||||
| tarslip.go:16:14:16:34 | call to Dir | semmle.label | call to Dir |
|
| tarslip.go:16:14:16:34 | call to Dir | semmle.label | call to Dir |
|
||||||
| tarslip.go:16:23:16:33 | selection of Name | semmle.label | selection of Name |
|
| tarslip.go:16:23:16:33 | selection of Name | semmle.label | selection of Name |
|
||||||
| tst.go:23:2:43:2 | extract:1 range statement | semmle.label | extract:1 range statement |
|
| tst.go:23:2:43:2 | range statement[1] | semmle.label | range statement[1] |
|
||||||
| tst.go:29:20:29:23 | path | semmle.label | path |
|
| tst.go:29:20:29:23 | path | semmle.label | path |
|
||||||
subpaths
|
subpaths
|
||||||
|
|||||||
@@ -31,16 +31,16 @@ edges
|
|||||||
| SqlInjection.go:11:3:11:17 | call to Query | SqlInjection.go:11:3:11:29 | index expression | provenance | |
|
| SqlInjection.go:11:3:11:17 | call to Query | SqlInjection.go:11:3:11:29 | index expression | provenance | |
|
||||||
| SqlInjection.go:11:3:11:29 | index expression | SqlInjection.go:10:7:11:30 | []type{args} [array] | provenance | |
|
| SqlInjection.go:11:3:11:29 | index expression | SqlInjection.go:10:7:11:30 | []type{args} [array] | provenance | |
|
||||||
| SqlInjection.go:11:3:11:29 | index expression | SqlInjection.go:10:7:11:30 | call to Sprintf | provenance | FunctionModel |
|
| SqlInjection.go:11:3:11:29 | index expression | SqlInjection.go:10:7:11:30 | call to Sprintf | provenance | FunctionModel |
|
||||||
| issue48.go:17:2:17:33 | extract:0 ... := ... | issue48.go:18:17:18:17 | b | provenance | |
|
| issue48.go:17:2:17:33 | ... := ...[0] | issue48.go:18:17:18:17 | b | provenance | |
|
||||||
| issue48.go:17:25:17:32 | selection of Body | issue48.go:17:2:17:33 | extract:0 ... := ... | provenance | Src:MaD:17 MaD:24 |
|
| issue48.go:17:25:17:32 | selection of Body | issue48.go:17:2:17:33 | ... := ...[0] | provenance | Src:MaD:17 MaD:24 |
|
||||||
| issue48.go:18:17:18:17 | b | issue48.go:18:20:18:39 | &... [postupdate] | provenance | MaD:22 |
|
| issue48.go:18:17:18:17 | b | issue48.go:18:20:18:39 | &... [postupdate] | provenance | MaD:22 |
|
||||||
| issue48.go:18:20:18:39 | &... [postupdate] | issue48.go:21:3:21:33 | index expression | provenance | |
|
| issue48.go:18:20:18:39 | &... [postupdate] | issue48.go:21:3:21:33 | index expression | provenance | |
|
||||||
| issue48.go:20:8:21:34 | []type{args} [array] | issue48.go:20:8:21:34 | call to Sprintf | provenance | MaD:23 |
|
| issue48.go:20:8:21:34 | []type{args} [array] | issue48.go:20:8:21:34 | call to Sprintf | provenance | MaD:23 |
|
||||||
| issue48.go:20:8:21:34 | call to Sprintf | issue48.go:22:11:22:12 | q3 | provenance | Sink:MaD:1 |
|
| issue48.go:20:8:21:34 | call to Sprintf | issue48.go:22:11:22:12 | q3 | provenance | Sink:MaD:1 |
|
||||||
| issue48.go:21:3:21:33 | index expression | issue48.go:20:8:21:34 | []type{args} [array] | provenance | |
|
| issue48.go:21:3:21:33 | index expression | issue48.go:20:8:21:34 | []type{args} [array] | provenance | |
|
||||||
| issue48.go:21:3:21:33 | index expression | issue48.go:20:8:21:34 | call to Sprintf | provenance | FunctionModel |
|
| issue48.go:21:3:21:33 | index expression | issue48.go:20:8:21:34 | call to Sprintf | provenance | FunctionModel |
|
||||||
| issue48.go:27:2:27:34 | extract:0 ... := ... | issue48.go:28:17:28:18 | b2 | provenance | |
|
| issue48.go:27:2:27:34 | ... := ...[0] | issue48.go:28:17:28:18 | b2 | provenance | |
|
||||||
| issue48.go:27:26:27:33 | selection of Body | issue48.go:27:2:27:34 | extract:0 ... := ... | provenance | Src:MaD:17 MaD:24 |
|
| issue48.go:27:26:27:33 | selection of Body | issue48.go:27:2:27:34 | ... := ...[0] | provenance | Src:MaD:17 MaD:24 |
|
||||||
| issue48.go:28:17:28:18 | b2 | issue48.go:28:21:28:41 | &... [postupdate] | provenance | MaD:22 |
|
| issue48.go:28:17:28:18 | b2 | issue48.go:28:21:28:41 | &... [postupdate] | provenance | MaD:22 |
|
||||||
| issue48.go:28:21:28:41 | &... [postupdate] | issue48.go:31:3:31:31 | selection of Category | provenance | |
|
| issue48.go:28:21:28:41 | &... [postupdate] | issue48.go:31:3:31:31 | selection of Category | provenance | |
|
||||||
| issue48.go:30:8:31:32 | []type{args} [array] | issue48.go:30:8:31:32 | call to Sprintf | provenance | MaD:23 |
|
| issue48.go:30:8:31:32 | []type{args} [array] | issue48.go:30:8:31:32 | call to Sprintf | provenance | MaD:23 |
|
||||||
@@ -72,19 +72,19 @@ edges
|
|||||||
| main.go:30:13:30:39 | index expression | main.go:28:18:31:2 | struct literal [Category] | provenance | |
|
| main.go:30:13:30:39 | index expression | main.go:28:18:31:2 | struct literal [Category] | provenance | |
|
||||||
| main.go:33:7:34:23 | []type{args} [array] | main.go:33:7:34:23 | call to Sprintf | provenance | MaD:23 |
|
| main.go:33:7:34:23 | []type{args} [array] | main.go:33:7:34:23 | call to Sprintf | provenance | MaD:23 |
|
||||||
| main.go:33:7:34:23 | call to Sprintf | main.go:35:11:35:11 | q | provenance | Sink:MaD:1 |
|
| main.go:33:7:34:23 | call to Sprintf | main.go:35:11:35:11 | q | provenance | Sink:MaD:1 |
|
||||||
| main.go:34:3:34:13 | RequestData [pointer, Category] | main.go:34:3:34:13 | implicit-deref RequestData [Category] | provenance | |
|
| main.go:34:3:34:13 | RequestData [pointer, Category] | main.go:34:3:34:13 | implicit dereference [Category] | provenance | |
|
||||||
| main.go:34:3:34:13 | implicit-deref RequestData [Category] | main.go:34:3:34:22 | selection of Category | provenance | |
|
| main.go:34:3:34:13 | implicit dereference [Category] | main.go:34:3:34:22 | selection of Category | provenance | |
|
||||||
| main.go:34:3:34:22 | selection of Category | main.go:33:7:34:23 | []type{args} [array] | provenance | |
|
| main.go:34:3:34:22 | selection of Category | main.go:33:7:34:23 | []type{args} [array] | provenance | |
|
||||||
| main.go:34:3:34:22 | selection of Category | main.go:33:7:34:23 | call to Sprintf | provenance | FunctionModel |
|
| main.go:34:3:34:22 | selection of Category | main.go:33:7:34:23 | call to Sprintf | provenance | FunctionModel |
|
||||||
| main.go:40:2:40:12 | RequestData [postupdate] [pointer, Category] | main.go:43:3:43:13 | RequestData [pointer, Category] | provenance | |
|
| main.go:40:2:40:12 | RequestData [postupdate] [pointer, Category] | main.go:43:3:43:13 | RequestData [pointer, Category] | provenance | |
|
||||||
| main.go:40:2:40:12 | implicit-deref RequestData [postupdate] [Category] | main.go:40:2:40:12 | RequestData [postupdate] [pointer, Category] | provenance | |
|
| main.go:40:2:40:12 | implicit dereference [postupdate] [Category] | main.go:40:2:40:12 | RequestData [postupdate] [pointer, Category] | provenance | |
|
||||||
| main.go:40:25:40:31 | selection of URL | main.go:40:25:40:39 | call to Query | provenance | Src:MaD:21 MaD:26 |
|
| main.go:40:25:40:31 | selection of URL | main.go:40:25:40:39 | call to Query | provenance | Src:MaD:21 MaD:26 |
|
||||||
| main.go:40:25:40:39 | call to Query | main.go:40:25:40:51 | index expression | provenance | |
|
| main.go:40:25:40:39 | call to Query | main.go:40:25:40:51 | index expression | provenance | |
|
||||||
| main.go:40:25:40:51 | index expression | main.go:40:2:40:12 | implicit-deref RequestData [postupdate] [Category] | provenance | |
|
| main.go:40:25:40:51 | index expression | main.go:40:2:40:12 | implicit dereference [postupdate] [Category] | provenance | |
|
||||||
| main.go:42:7:43:23 | []type{args} [array] | main.go:42:7:43:23 | call to Sprintf | provenance | MaD:23 |
|
| main.go:42:7:43:23 | []type{args} [array] | main.go:42:7:43:23 | call to Sprintf | provenance | MaD:23 |
|
||||||
| main.go:42:7:43:23 | call to Sprintf | main.go:44:11:44:11 | q | provenance | Sink:MaD:1 |
|
| main.go:42:7:43:23 | call to Sprintf | main.go:44:11:44:11 | q | provenance | Sink:MaD:1 |
|
||||||
| main.go:43:3:43:13 | RequestData [pointer, Category] | main.go:43:3:43:13 | implicit-deref RequestData [Category] | provenance | |
|
| main.go:43:3:43:13 | RequestData [pointer, Category] | main.go:43:3:43:13 | implicit dereference [Category] | provenance | |
|
||||||
| main.go:43:3:43:13 | implicit-deref RequestData [Category] | main.go:43:3:43:22 | selection of Category | provenance | |
|
| main.go:43:3:43:13 | implicit dereference [Category] | main.go:43:3:43:22 | selection of Category | provenance | |
|
||||||
| main.go:43:3:43:22 | selection of Category | main.go:42:7:43:23 | []type{args} [array] | provenance | |
|
| main.go:43:3:43:22 | selection of Category | main.go:42:7:43:23 | []type{args} [array] | provenance | |
|
||||||
| main.go:43:3:43:22 | selection of Category | main.go:42:7:43:23 | call to Sprintf | provenance | FunctionModel |
|
| main.go:43:3:43:22 | selection of Category | main.go:42:7:43:23 | call to Sprintf | provenance | FunctionModel |
|
||||||
| main.go:49:3:49:14 | star expression [postupdate] [Category] | main.go:49:4:49:14 | RequestData [postupdate] [pointer, Category] | provenance | |
|
| main.go:49:3:49:14 | star expression [postupdate] [Category] | main.go:49:4:49:14 | RequestData [postupdate] [pointer, Category] | provenance | |
|
||||||
@@ -94,8 +94,8 @@ edges
|
|||||||
| main.go:49:28:49:54 | index expression | main.go:49:3:49:14 | star expression [postupdate] [Category] | provenance | |
|
| main.go:49:28:49:54 | index expression | main.go:49:3:49:14 | star expression [postupdate] [Category] | provenance | |
|
||||||
| main.go:51:7:52:23 | []type{args} [array] | main.go:51:7:52:23 | call to Sprintf | provenance | MaD:23 |
|
| main.go:51:7:52:23 | []type{args} [array] | main.go:51:7:52:23 | call to Sprintf | provenance | MaD:23 |
|
||||||
| main.go:51:7:52:23 | call to Sprintf | main.go:53:11:53:11 | q | provenance | Sink:MaD:1 |
|
| main.go:51:7:52:23 | call to Sprintf | main.go:53:11:53:11 | q | provenance | Sink:MaD:1 |
|
||||||
| main.go:52:3:52:13 | RequestData [pointer, Category] | main.go:52:3:52:13 | implicit-deref RequestData [Category] | provenance | |
|
| main.go:52:3:52:13 | RequestData [pointer, Category] | main.go:52:3:52:13 | implicit dereference [Category] | provenance | |
|
||||||
| main.go:52:3:52:13 | implicit-deref RequestData [Category] | main.go:52:3:52:22 | selection of Category | provenance | |
|
| main.go:52:3:52:13 | implicit dereference [Category] | main.go:52:3:52:22 | selection of Category | provenance | |
|
||||||
| main.go:52:3:52:22 | selection of Category | main.go:51:7:52:23 | []type{args} [array] | provenance | |
|
| main.go:52:3:52:22 | selection of Category | main.go:51:7:52:23 | []type{args} [array] | provenance | |
|
||||||
| main.go:52:3:52:22 | selection of Category | main.go:51:7:52:23 | call to Sprintf | provenance | FunctionModel |
|
| main.go:52:3:52:22 | selection of Category | main.go:51:7:52:23 | call to Sprintf | provenance | FunctionModel |
|
||||||
| main.go:58:3:58:14 | star expression [postupdate] [Category] | main.go:58:4:58:14 | RequestData [postupdate] [pointer, Category] | provenance | |
|
| main.go:58:3:58:14 | star expression [postupdate] [Category] | main.go:58:4:58:14 | RequestData [postupdate] [pointer, Category] | provenance | |
|
||||||
@@ -161,7 +161,7 @@ nodes
|
|||||||
| SqlInjection.go:11:3:11:17 | call to Query | semmle.label | call to Query |
|
| SqlInjection.go:11:3:11:17 | call to Query | semmle.label | call to Query |
|
||||||
| SqlInjection.go:11:3:11:29 | index expression | semmle.label | index expression |
|
| SqlInjection.go:11:3:11:29 | index expression | semmle.label | index expression |
|
||||||
| SqlInjection.go:12:11:12:11 | q | semmle.label | q |
|
| SqlInjection.go:12:11:12:11 | q | semmle.label | q |
|
||||||
| issue48.go:17:2:17:33 | extract:0 ... := ... | semmle.label | extract:0 ... := ... |
|
| issue48.go:17:2:17:33 | ... := ...[0] | semmle.label | ... := ...[0] |
|
||||||
| issue48.go:17:25:17:32 | selection of Body | semmle.label | selection of Body |
|
| issue48.go:17:25:17:32 | selection of Body | semmle.label | selection of Body |
|
||||||
| issue48.go:18:17:18:17 | b | semmle.label | b |
|
| issue48.go:18:17:18:17 | b | semmle.label | b |
|
||||||
| issue48.go:18:20:18:39 | &... [postupdate] | semmle.label | &... [postupdate] |
|
| issue48.go:18:20:18:39 | &... [postupdate] | semmle.label | &... [postupdate] |
|
||||||
@@ -169,7 +169,7 @@ nodes
|
|||||||
| issue48.go:20:8:21:34 | call to Sprintf | semmle.label | call to Sprintf |
|
| issue48.go:20:8:21:34 | call to Sprintf | semmle.label | call to Sprintf |
|
||||||
| issue48.go:21:3:21:33 | index expression | semmle.label | index expression |
|
| issue48.go:21:3:21:33 | index expression | semmle.label | index expression |
|
||||||
| issue48.go:22:11:22:12 | q3 | semmle.label | q3 |
|
| issue48.go:22:11:22:12 | q3 | semmle.label | q3 |
|
||||||
| issue48.go:27:2:27:34 | extract:0 ... := ... | semmle.label | extract:0 ... := ... |
|
| issue48.go:27:2:27:34 | ... := ...[0] | semmle.label | ... := ...[0] |
|
||||||
| issue48.go:27:26:27:33 | selection of Body | semmle.label | selection of Body |
|
| issue48.go:27:26:27:33 | selection of Body | semmle.label | selection of Body |
|
||||||
| issue48.go:28:17:28:18 | b2 | semmle.label | b2 |
|
| issue48.go:28:17:28:18 | b2 | semmle.label | b2 |
|
||||||
| issue48.go:28:21:28:41 | &... [postupdate] | semmle.label | &... [postupdate] |
|
| issue48.go:28:21:28:41 | &... [postupdate] | semmle.label | &... [postupdate] |
|
||||||
@@ -204,18 +204,18 @@ nodes
|
|||||||
| main.go:33:7:34:23 | []type{args} [array] | semmle.label | []type{args} [array] |
|
| main.go:33:7:34:23 | []type{args} [array] | semmle.label | []type{args} [array] |
|
||||||
| main.go:33:7:34:23 | call to Sprintf | semmle.label | call to Sprintf |
|
| main.go:33:7:34:23 | call to Sprintf | semmle.label | call to Sprintf |
|
||||||
| main.go:34:3:34:13 | RequestData [pointer, Category] | semmle.label | RequestData [pointer, Category] |
|
| main.go:34:3:34:13 | RequestData [pointer, Category] | semmle.label | RequestData [pointer, Category] |
|
||||||
| main.go:34:3:34:13 | implicit-deref RequestData [Category] | semmle.label | implicit-deref RequestData [Category] |
|
| main.go:34:3:34:13 | implicit dereference [Category] | semmle.label | implicit dereference [Category] |
|
||||||
| main.go:34:3:34:22 | selection of Category | semmle.label | selection of Category |
|
| main.go:34:3:34:22 | selection of Category | semmle.label | selection of Category |
|
||||||
| main.go:35:11:35:11 | q | semmle.label | q |
|
| main.go:35:11:35:11 | q | semmle.label | q |
|
||||||
| main.go:40:2:40:12 | RequestData [postupdate] [pointer, Category] | semmle.label | RequestData [postupdate] [pointer, Category] |
|
| main.go:40:2:40:12 | RequestData [postupdate] [pointer, Category] | semmle.label | RequestData [postupdate] [pointer, Category] |
|
||||||
| main.go:40:2:40:12 | implicit-deref RequestData [postupdate] [Category] | semmle.label | implicit-deref RequestData [postupdate] [Category] |
|
| main.go:40:2:40:12 | implicit dereference [postupdate] [Category] | semmle.label | implicit dereference [postupdate] [Category] |
|
||||||
| main.go:40:25:40:31 | selection of URL | semmle.label | selection of URL |
|
| main.go:40:25:40:31 | selection of URL | semmle.label | selection of URL |
|
||||||
| main.go:40:25:40:39 | call to Query | semmle.label | call to Query |
|
| main.go:40:25:40:39 | call to Query | semmle.label | call to Query |
|
||||||
| main.go:40:25:40:51 | index expression | semmle.label | index expression |
|
| main.go:40:25:40:51 | index expression | semmle.label | index expression |
|
||||||
| main.go:42:7:43:23 | []type{args} [array] | semmle.label | []type{args} [array] |
|
| main.go:42:7:43:23 | []type{args} [array] | semmle.label | []type{args} [array] |
|
||||||
| main.go:42:7:43:23 | call to Sprintf | semmle.label | call to Sprintf |
|
| main.go:42:7:43:23 | call to Sprintf | semmle.label | call to Sprintf |
|
||||||
| main.go:43:3:43:13 | RequestData [pointer, Category] | semmle.label | RequestData [pointer, Category] |
|
| main.go:43:3:43:13 | RequestData [pointer, Category] | semmle.label | RequestData [pointer, Category] |
|
||||||
| main.go:43:3:43:13 | implicit-deref RequestData [Category] | semmle.label | implicit-deref RequestData [Category] |
|
| main.go:43:3:43:13 | implicit dereference [Category] | semmle.label | implicit dereference [Category] |
|
||||||
| main.go:43:3:43:22 | selection of Category | semmle.label | selection of Category |
|
| main.go:43:3:43:22 | selection of Category | semmle.label | selection of Category |
|
||||||
| main.go:44:11:44:11 | q | semmle.label | q |
|
| main.go:44:11:44:11 | q | semmle.label | q |
|
||||||
| main.go:49:3:49:14 | star expression [postupdate] [Category] | semmle.label | star expression [postupdate] [Category] |
|
| main.go:49:3:49:14 | star expression [postupdate] [Category] | semmle.label | star expression [postupdate] [Category] |
|
||||||
@@ -226,7 +226,7 @@ nodes
|
|||||||
| main.go:51:7:52:23 | []type{args} [array] | semmle.label | []type{args} [array] |
|
| main.go:51:7:52:23 | []type{args} [array] | semmle.label | []type{args} [array] |
|
||||||
| main.go:51:7:52:23 | call to Sprintf | semmle.label | call to Sprintf |
|
| main.go:51:7:52:23 | call to Sprintf | semmle.label | call to Sprintf |
|
||||||
| main.go:52:3:52:13 | RequestData [pointer, Category] | semmle.label | RequestData [pointer, Category] |
|
| main.go:52:3:52:13 | RequestData [pointer, Category] | semmle.label | RequestData [pointer, Category] |
|
||||||
| main.go:52:3:52:13 | implicit-deref RequestData [Category] | semmle.label | implicit-deref RequestData [Category] |
|
| main.go:52:3:52:13 | implicit dereference [Category] | semmle.label | implicit dereference [Category] |
|
||||||
| main.go:52:3:52:22 | selection of Category | semmle.label | selection of Category |
|
| main.go:52:3:52:22 | selection of Category | semmle.label | selection of Category |
|
||||||
| main.go:53:11:53:11 | q | semmle.label | q |
|
| main.go:53:11:53:11 | q | semmle.label | q |
|
||||||
| main.go:58:3:58:14 | star expression [postupdate] [Category] | semmle.label | star expression [postupdate] [Category] |
|
| main.go:58:3:58:14 | star expression [postupdate] [Category] | semmle.label | star expression [postupdate] [Category] |
|
||||||
|
|||||||
@@ -1,25 +1,25 @@
|
|||||||
#select
|
#select
|
||||||
| StringBreak.go:15:47:15:57 | versionJSON | StringBreak.go:11:2:11:40 | extract:0 ... := ... | StringBreak.go:15:47:15:57 | versionJSON | If this $@ contains a single quote, it could break out of the enclosing quotes. | StringBreak.go:11:2:11:40 | extract:0 ... := ... | JSON value |
|
| StringBreak.go:15:47:15:57 | versionJSON | StringBreak.go:11:2:11:40 | ... := ...[0] | StringBreak.go:15:47:15:57 | versionJSON | If this $@ contains a single quote, it could break out of the enclosing quotes. | StringBreak.go:11:2:11:40 | ... := ...[0] | JSON value |
|
||||||
| StringBreakMismatched.go:18:26:18:32 | escaped | StringBreakMismatched.go:13:2:13:40 | extract:0 ... := ... | StringBreakMismatched.go:18:26:18:32 | escaped | If this $@ contains a single quote, it could break out of the enclosing quotes. | StringBreakMismatched.go:13:2:13:40 | extract:0 ... := ... | JSON value |
|
| StringBreakMismatched.go:18:26:18:32 | escaped | StringBreakMismatched.go:13:2:13:40 | ... := ...[0] | StringBreakMismatched.go:18:26:18:32 | escaped | If this $@ contains a single quote, it could break out of the enclosing quotes. | StringBreakMismatched.go:13:2:13:40 | ... := ...[0] | JSON value |
|
||||||
| StringBreakMismatched.go:30:27:30:33 | escaped | StringBreakMismatched.go:25:2:25:40 | extract:0 ... := ... | StringBreakMismatched.go:30:27:30:33 | escaped | If this $@ contains a double quote, it could break out of the enclosing quotes. | StringBreakMismatched.go:25:2:25:40 | extract:0 ... := ... | JSON value |
|
| StringBreakMismatched.go:30:27:30:33 | escaped | StringBreakMismatched.go:25:2:25:40 | ... := ...[0] | StringBreakMismatched.go:30:27:30:33 | escaped | If this $@ contains a double quote, it could break out of the enclosing quotes. | StringBreakMismatched.go:25:2:25:40 | ... := ...[0] | JSON value |
|
||||||
edges
|
edges
|
||||||
| StringBreak.go:11:2:11:40 | extract:0 ... := ... | StringBreak.go:15:47:15:57 | versionJSON | provenance | |
|
| StringBreak.go:11:2:11:40 | ... := ...[0] | StringBreak.go:15:47:15:57 | versionJSON | provenance | |
|
||||||
| StringBreakMismatched.go:13:2:13:40 | extract:0 ... := ... | StringBreakMismatched.go:14:29:14:47 | type conversion | provenance | |
|
| StringBreakMismatched.go:13:2:13:40 | ... := ...[0] | StringBreakMismatched.go:14:29:14:47 | type conversion | provenance | |
|
||||||
| StringBreakMismatched.go:14:13:14:62 | call to Replace | StringBreakMismatched.go:18:26:18:32 | escaped | provenance | |
|
| StringBreakMismatched.go:14:13:14:62 | call to Replace | StringBreakMismatched.go:18:26:18:32 | escaped | provenance | |
|
||||||
| StringBreakMismatched.go:14:29:14:47 | type conversion | StringBreakMismatched.go:14:13:14:62 | call to Replace | provenance | MaD:1 |
|
| StringBreakMismatched.go:14:29:14:47 | type conversion | StringBreakMismatched.go:14:13:14:62 | call to Replace | provenance | MaD:1 |
|
||||||
| StringBreakMismatched.go:25:2:25:40 | extract:0 ... := ... | StringBreakMismatched.go:26:29:26:47 | type conversion | provenance | |
|
| StringBreakMismatched.go:25:2:25:40 | ... := ...[0] | StringBreakMismatched.go:26:29:26:47 | type conversion | provenance | |
|
||||||
| StringBreakMismatched.go:26:13:26:61 | call to Replace | StringBreakMismatched.go:30:27:30:33 | escaped | provenance | |
|
| StringBreakMismatched.go:26:13:26:61 | call to Replace | StringBreakMismatched.go:30:27:30:33 | escaped | provenance | |
|
||||||
| StringBreakMismatched.go:26:29:26:47 | type conversion | StringBreakMismatched.go:26:13:26:61 | call to Replace | provenance | MaD:1 |
|
| StringBreakMismatched.go:26:29:26:47 | type conversion | StringBreakMismatched.go:26:13:26:61 | call to Replace | provenance | MaD:1 |
|
||||||
models
|
models
|
||||||
| 1 | Summary: strings; ; false; Replace; ; ; Argument[0]; ReturnValue; taint; manual |
|
| 1 | Summary: strings; ; false; Replace; ; ; Argument[0]; ReturnValue; taint; manual |
|
||||||
nodes
|
nodes
|
||||||
| StringBreak.go:11:2:11:40 | extract:0 ... := ... | semmle.label | extract:0 ... := ... |
|
| StringBreak.go:11:2:11:40 | ... := ...[0] | semmle.label | ... := ...[0] |
|
||||||
| StringBreak.go:15:47:15:57 | versionJSON | semmle.label | versionJSON |
|
| StringBreak.go:15:47:15:57 | versionJSON | semmle.label | versionJSON |
|
||||||
| StringBreakMismatched.go:13:2:13:40 | extract:0 ... := ... | semmle.label | extract:0 ... := ... |
|
| StringBreakMismatched.go:13:2:13:40 | ... := ...[0] | semmle.label | ... := ...[0] |
|
||||||
| StringBreakMismatched.go:14:13:14:62 | call to Replace | semmle.label | call to Replace |
|
| StringBreakMismatched.go:14:13:14:62 | call to Replace | semmle.label | call to Replace |
|
||||||
| StringBreakMismatched.go:14:29:14:47 | type conversion | semmle.label | type conversion |
|
| StringBreakMismatched.go:14:29:14:47 | type conversion | semmle.label | type conversion |
|
||||||
| StringBreakMismatched.go:18:26:18:32 | escaped | semmle.label | escaped |
|
| StringBreakMismatched.go:18:26:18:32 | escaped | semmle.label | escaped |
|
||||||
| StringBreakMismatched.go:25:2:25:40 | extract:0 ... := ... | semmle.label | extract:0 ... := ... |
|
| StringBreakMismatched.go:25:2:25:40 | ... := ...[0] | semmle.label | ... := ...[0] |
|
||||||
| StringBreakMismatched.go:26:13:26:61 | call to Replace | semmle.label | call to Replace |
|
| StringBreakMismatched.go:26:13:26:61 | call to Replace | semmle.label | call to Replace |
|
||||||
| StringBreakMismatched.go:26:29:26:47 | type conversion | semmle.label | type conversion |
|
| StringBreakMismatched.go:26:29:26:47 | type conversion | semmle.label | type conversion |
|
||||||
| StringBreakMismatched.go:30:27:30:33 | escaped | semmle.label | escaped |
|
| StringBreakMismatched.go:30:27:30:33 | escaped | semmle.label | escaped |
|
||||||
|
|||||||
@@ -1,22 +1,22 @@
|
|||||||
#select
|
#select
|
||||||
| AllocationSizeOverflow.go:10:10:10:22 | call to len | AllocationSizeOverflow.go:6:2:6:33 | extract:0 ... := ... | AllocationSizeOverflow.go:10:10:10:22 | call to len | This operation, which is used in an $@, involves a $@ and might overflow. | AllocationSizeOverflow.go:11:25:11:28 | size | allocation | AllocationSizeOverflow.go:6:2:6:33 | extract:0 ... := ... | potentially large value |
|
| AllocationSizeOverflow.go:10:10:10:22 | call to len | AllocationSizeOverflow.go:6:2:6:33 | ... := ...[0] | AllocationSizeOverflow.go:10:10:10:22 | call to len | This operation, which is used in an $@, involves a $@ and might overflow. | AllocationSizeOverflow.go:11:25:11:28 | size | allocation | AllocationSizeOverflow.go:6:2:6:33 | ... := ...[0] | potentially large value |
|
||||||
| tst2.go:10:22:10:30 | call to len | tst2.go:9:2:9:37 | extract:0 ... := ... | tst2.go:10:22:10:30 | call to len | This operation, which is used in an $@, involves a $@ and might overflow. | tst2.go:10:22:10:32 | ...+... | allocation | tst2.go:9:2:9:37 | extract:0 ... := ... | potentially large value |
|
| tst2.go:10:22:10:30 | call to len | tst2.go:9:2:9:37 | ... := ...[0] | tst2.go:10:22:10:30 | call to len | This operation, which is used in an $@, involves a $@ and might overflow. | tst2.go:10:22:10:32 | ...+... | allocation | tst2.go:9:2:9:37 | ... := ...[0] | potentially large value |
|
||||||
| tst2.go:15:22:15:30 | call to len | tst2.go:14:2:14:29 | extract:0 ... := ... | tst2.go:15:22:15:30 | call to len | This operation, which is used in an $@, involves a $@ and might overflow. | tst2.go:15:22:15:32 | ...+... | allocation | tst2.go:14:2:14:29 | extract:0 ... := ... | potentially large value |
|
| tst2.go:15:22:15:30 | call to len | tst2.go:14:2:14:29 | ... := ...[0] | tst2.go:15:22:15:30 | call to len | This operation, which is used in an $@, involves a $@ and might overflow. | tst2.go:15:22:15:32 | ...+... | allocation | tst2.go:14:2:14:29 | ... := ...[0] | potentially large value |
|
||||||
| tst3.go:7:22:7:34 | call to len | tst3.go:6:2:6:31 | extract:0 ... := ... | tst3.go:7:22:7:34 | call to len | This operation, which is used in an $@, involves a $@ and might overflow. | tst3.go:7:22:7:36 | ...+... | allocation | tst3.go:6:2:6:31 | extract:0 ... := ... | potentially large value |
|
| tst3.go:7:22:7:34 | call to len | tst3.go:6:2:6:31 | ... := ...[0] | tst3.go:7:22:7:34 | call to len | This operation, which is used in an $@, involves a $@ and might overflow. | tst3.go:7:22:7:36 | ...+... | allocation | tst3.go:6:2:6:31 | ... := ...[0] | potentially large value |
|
||||||
| tst3.go:24:16:24:28 | call to len | tst3.go:6:2:6:31 | extract:0 ... := ... | tst3.go:24:16:24:28 | call to len | This operation, which is used in an $@, involves a $@ and might overflow. | tst3.go:27:24:27:32 | newlength | allocation | tst3.go:6:2:6:31 | extract:0 ... := ... | potentially large value |
|
| tst3.go:24:16:24:28 | call to len | tst3.go:6:2:6:31 | ... := ...[0] | tst3.go:24:16:24:28 | call to len | This operation, which is used in an $@, involves a $@ and might overflow. | tst3.go:27:24:27:32 | newlength | allocation | tst3.go:6:2:6:31 | ... := ...[0] | potentially large value |
|
||||||
| tst3.go:32:16:32:28 | call to len | tst3.go:6:2:6:31 | extract:0 ... := ... | tst3.go:32:16:32:28 | call to len | This operation, which is used in an $@, involves a $@ and might overflow. | tst3.go:36:23:36:31 | newlength | allocation | tst3.go:6:2:6:31 | extract:0 ... := ... | potentially large value |
|
| tst3.go:32:16:32:28 | call to len | tst3.go:6:2:6:31 | ... := ...[0] | tst3.go:32:16:32:28 | call to len | This operation, which is used in an $@, involves a $@ and might overflow. | tst3.go:36:23:36:31 | newlength | allocation | tst3.go:6:2:6:31 | ... := ...[0] | potentially large value |
|
||||||
| tst.go:15:22:15:34 | call to len | tst.go:14:2:14:30 | extract:0 ... = ... | tst.go:15:22:15:34 | call to len | This operation, which is used in an $@, involves a $@ and might overflow. | tst.go:15:22:15:36 | ...+... | allocation | tst.go:14:2:14:30 | extract:0 ... = ... | potentially large value |
|
| tst.go:15:22:15:34 | call to len | tst.go:14:2:14:30 | ... = ...[0] | tst.go:15:22:15:34 | call to len | This operation, which is used in an $@, involves a $@ and might overflow. | tst.go:15:22:15:36 | ...+... | allocation | tst.go:14:2:14:30 | ... = ...[0] | potentially large value |
|
||||||
| tst.go:21:22:21:34 | call to len | tst.go:20:2:20:31 | extract:0 ... = ... | tst.go:21:22:21:34 | call to len | This operation, which is used in an $@, involves a $@ and might overflow. | tst.go:21:22:21:36 | ...+... | allocation | tst.go:20:2:20:31 | extract:0 ... = ... | potentially large value |
|
| tst.go:21:22:21:34 | call to len | tst.go:20:2:20:31 | ... = ...[0] | tst.go:21:22:21:34 | call to len | This operation, which is used in an $@, involves a $@ and might overflow. | tst.go:21:22:21:36 | ...+... | allocation | tst.go:20:2:20:31 | ... = ...[0] | potentially large value |
|
||||||
| tst.go:27:26:27:38 | call to len | tst.go:26:2:26:31 | extract:0 ... = ... | tst.go:27:26:27:38 | call to len | This operation, which is used in an $@, involves a $@ and might overflow. | tst.go:27:26:27:40 | ...+... | allocation | tst.go:26:2:26:31 | extract:0 ... = ... | potentially large value |
|
| tst.go:27:26:27:38 | call to len | tst.go:26:2:26:31 | ... = ...[0] | tst.go:27:26:27:38 | call to len | This operation, which is used in an $@, involves a $@ and might overflow. | tst.go:27:26:27:40 | ...+... | allocation | tst.go:26:2:26:31 | ... = ...[0] | potentially large value |
|
||||||
| tst.go:35:22:35:34 | call to len | tst.go:34:2:34:30 | extract:0 ... = ... | tst.go:35:22:35:34 | call to len | This operation, which is used in an $@, involves a $@ and might overflow. | tst.go:35:22:35:36 | ...+... | allocation | tst.go:34:2:34:30 | extract:0 ... = ... | potentially large value |
|
| tst.go:35:22:35:34 | call to len | tst.go:34:2:34:30 | ... = ...[0] | tst.go:35:22:35:34 | call to len | This operation, which is used in an $@, involves a $@ and might overflow. | tst.go:35:22:35:36 | ...+... | allocation | tst.go:34:2:34:30 | ... = ...[0] | potentially large value |
|
||||||
edges
|
edges
|
||||||
| AllocationSizeOverflow.go:6:2:6:33 | extract:0 ... := ... | AllocationSizeOverflow.go:10:14:10:21 | jsonData | provenance | |
|
| AllocationSizeOverflow.go:6:2:6:33 | ... := ...[0] | AllocationSizeOverflow.go:10:14:10:21 | jsonData | provenance | |
|
||||||
| AllocationSizeOverflow.go:10:14:10:21 | jsonData | AllocationSizeOverflow.go:10:10:10:22 | call to len | provenance | Config |
|
| AllocationSizeOverflow.go:10:14:10:21 | jsonData | AllocationSizeOverflow.go:10:10:10:22 | call to len | provenance | Config |
|
||||||
| tst2.go:9:2:9:37 | extract:0 ... := ... | tst2.go:10:26:10:29 | data | provenance | Src:MaD:1 |
|
| tst2.go:9:2:9:37 | ... := ...[0] | tst2.go:10:26:10:29 | data | provenance | Src:MaD:1 |
|
||||||
| tst2.go:10:26:10:29 | data | tst2.go:10:22:10:30 | call to len | provenance | Config |
|
| tst2.go:10:26:10:29 | data | tst2.go:10:22:10:30 | call to len | provenance | Config |
|
||||||
| tst2.go:14:2:14:29 | extract:0 ... := ... | tst2.go:15:26:15:29 | data | provenance | |
|
| tst2.go:14:2:14:29 | ... := ...[0] | tst2.go:15:26:15:29 | data | provenance | |
|
||||||
| tst2.go:15:26:15:29 | data | tst2.go:15:22:15:30 | call to len | provenance | Config |
|
| tst2.go:15:26:15:29 | data | tst2.go:15:22:15:30 | call to len | provenance | Config |
|
||||||
| tst3.go:6:2:6:31 | extract:0 ... := ... | tst3.go:7:26:7:33 | jsonData | provenance | |
|
| tst3.go:6:2:6:31 | ... := ...[0] | tst3.go:7:26:7:33 | jsonData | provenance | |
|
||||||
| tst3.go:7:26:7:33 | jsonData | tst3.go:7:22:7:34 | call to len | provenance | Config |
|
| tst3.go:7:26:7:33 | jsonData | tst3.go:7:22:7:34 | call to len | provenance | Config |
|
||||||
| tst3.go:7:26:7:33 | jsonData | tst3.go:9:32:9:39 | jsonData | provenance | |
|
| tst3.go:7:26:7:33 | jsonData | tst3.go:9:32:9:39 | jsonData | provenance | |
|
||||||
| tst3.go:9:32:9:39 | jsonData | tst3.go:11:9:11:16 | jsonData | provenance | |
|
| tst3.go:9:32:9:39 | jsonData | tst3.go:11:9:11:16 | jsonData | provenance | |
|
||||||
@@ -25,27 +25,27 @@ edges
|
|||||||
| tst3.go:24:20:24:27 | jsonData | tst3.go:24:16:24:28 | call to len | provenance | Config |
|
| tst3.go:24:20:24:27 | jsonData | tst3.go:24:16:24:28 | call to len | provenance | Config |
|
||||||
| tst3.go:24:20:24:27 | jsonData | tst3.go:32:20:32:27 | jsonData | provenance | |
|
| tst3.go:24:20:24:27 | jsonData | tst3.go:32:20:32:27 | jsonData | provenance | |
|
||||||
| tst3.go:32:20:32:27 | jsonData | tst3.go:32:16:32:28 | call to len | provenance | Config |
|
| tst3.go:32:20:32:27 | jsonData | tst3.go:32:16:32:28 | call to len | provenance | Config |
|
||||||
| tst.go:14:2:14:30 | extract:0 ... = ... | tst.go:15:26:15:33 | jsonData | provenance | |
|
| tst.go:14:2:14:30 | ... = ...[0] | tst.go:15:26:15:33 | jsonData | provenance | |
|
||||||
| tst.go:15:26:15:33 | jsonData | tst.go:15:22:15:34 | call to len | provenance | Config |
|
| tst.go:15:26:15:33 | jsonData | tst.go:15:22:15:34 | call to len | provenance | Config |
|
||||||
| tst.go:20:2:20:31 | extract:0 ... = ... | tst.go:21:26:21:33 | jsonData | provenance | |
|
| tst.go:20:2:20:31 | ... = ...[0] | tst.go:21:26:21:33 | jsonData | provenance | |
|
||||||
| tst.go:21:26:21:33 | jsonData | tst.go:21:22:21:34 | call to len | provenance | Config |
|
| tst.go:21:26:21:33 | jsonData | tst.go:21:22:21:34 | call to len | provenance | Config |
|
||||||
| tst.go:26:2:26:31 | extract:0 ... = ... | tst.go:27:30:27:37 | jsonData | provenance | |
|
| tst.go:26:2:26:31 | ... = ...[0] | tst.go:27:30:27:37 | jsonData | provenance | |
|
||||||
| tst.go:27:30:27:37 | jsonData | tst.go:27:26:27:38 | call to len | provenance | Config |
|
| tst.go:27:30:27:37 | jsonData | tst.go:27:26:27:38 | call to len | provenance | Config |
|
||||||
| tst.go:34:2:34:30 | extract:0 ... = ... | tst.go:35:26:35:33 | jsonData | provenance | |
|
| tst.go:34:2:34:30 | ... = ...[0] | tst.go:35:26:35:33 | jsonData | provenance | |
|
||||||
| tst.go:35:26:35:33 | jsonData | tst.go:35:22:35:34 | call to len | provenance | Config |
|
| tst.go:35:26:35:33 | jsonData | tst.go:35:22:35:34 | call to len | provenance | Config |
|
||||||
models
|
models
|
||||||
| 1 | Source: io/ioutil; ; false; ReadFile; ; ; ReturnValue[0]; file; manual |
|
| 1 | Source: io/ioutil; ; false; ReadFile; ; ; ReturnValue[0]; file; manual |
|
||||||
nodes
|
nodes
|
||||||
| AllocationSizeOverflow.go:6:2:6:33 | extract:0 ... := ... | semmle.label | extract:0 ... := ... |
|
| AllocationSizeOverflow.go:6:2:6:33 | ... := ...[0] | semmle.label | ... := ...[0] |
|
||||||
| AllocationSizeOverflow.go:10:10:10:22 | call to len | semmle.label | call to len |
|
| AllocationSizeOverflow.go:10:10:10:22 | call to len | semmle.label | call to len |
|
||||||
| AllocationSizeOverflow.go:10:14:10:21 | jsonData | semmle.label | jsonData |
|
| AllocationSizeOverflow.go:10:14:10:21 | jsonData | semmle.label | jsonData |
|
||||||
| tst2.go:9:2:9:37 | extract:0 ... := ... | semmle.label | extract:0 ... := ... |
|
| tst2.go:9:2:9:37 | ... := ...[0] | semmle.label | ... := ...[0] |
|
||||||
| tst2.go:10:22:10:30 | call to len | semmle.label | call to len |
|
| tst2.go:10:22:10:30 | call to len | semmle.label | call to len |
|
||||||
| tst2.go:10:26:10:29 | data | semmle.label | data |
|
| tst2.go:10:26:10:29 | data | semmle.label | data |
|
||||||
| tst2.go:14:2:14:29 | extract:0 ... := ... | semmle.label | extract:0 ... := ... |
|
| tst2.go:14:2:14:29 | ... := ...[0] | semmle.label | ... := ...[0] |
|
||||||
| tst2.go:15:22:15:30 | call to len | semmle.label | call to len |
|
| tst2.go:15:22:15:30 | call to len | semmle.label | call to len |
|
||||||
| tst2.go:15:26:15:29 | data | semmle.label | data |
|
| tst2.go:15:26:15:29 | data | semmle.label | data |
|
||||||
| tst3.go:6:2:6:31 | extract:0 ... := ... | semmle.label | extract:0 ... := ... |
|
| tst3.go:6:2:6:31 | ... := ...[0] | semmle.label | ... := ...[0] |
|
||||||
| tst3.go:7:22:7:34 | call to len | semmle.label | call to len |
|
| tst3.go:7:22:7:34 | call to len | semmle.label | call to len |
|
||||||
| tst3.go:7:26:7:33 | jsonData | semmle.label | jsonData |
|
| tst3.go:7:26:7:33 | jsonData | semmle.label | jsonData |
|
||||||
| tst3.go:9:32:9:39 | jsonData | semmle.label | jsonData |
|
| tst3.go:9:32:9:39 | jsonData | semmle.label | jsonData |
|
||||||
@@ -55,16 +55,16 @@ nodes
|
|||||||
| tst3.go:24:20:24:27 | jsonData | semmle.label | jsonData |
|
| tst3.go:24:20:24:27 | jsonData | semmle.label | jsonData |
|
||||||
| tst3.go:32:16:32:28 | call to len | semmle.label | call to len |
|
| tst3.go:32:16:32:28 | call to len | semmle.label | call to len |
|
||||||
| tst3.go:32:20:32:27 | jsonData | semmle.label | jsonData |
|
| tst3.go:32:20:32:27 | jsonData | semmle.label | jsonData |
|
||||||
| tst.go:14:2:14:30 | extract:0 ... = ... | semmle.label | extract:0 ... = ... |
|
| tst.go:14:2:14:30 | ... = ...[0] | semmle.label | ... = ...[0] |
|
||||||
| tst.go:15:22:15:34 | call to len | semmle.label | call to len |
|
| tst.go:15:22:15:34 | call to len | semmle.label | call to len |
|
||||||
| tst.go:15:26:15:33 | jsonData | semmle.label | jsonData |
|
| tst.go:15:26:15:33 | jsonData | semmle.label | jsonData |
|
||||||
| tst.go:20:2:20:31 | extract:0 ... = ... | semmle.label | extract:0 ... = ... |
|
| tst.go:20:2:20:31 | ... = ...[0] | semmle.label | ... = ...[0] |
|
||||||
| tst.go:21:22:21:34 | call to len | semmle.label | call to len |
|
| tst.go:21:22:21:34 | call to len | semmle.label | call to len |
|
||||||
| tst.go:21:26:21:33 | jsonData | semmle.label | jsonData |
|
| tst.go:21:26:21:33 | jsonData | semmle.label | jsonData |
|
||||||
| tst.go:26:2:26:31 | extract:0 ... = ... | semmle.label | extract:0 ... = ... |
|
| tst.go:26:2:26:31 | ... = ...[0] | semmle.label | ... = ...[0] |
|
||||||
| tst.go:27:26:27:38 | call to len | semmle.label | call to len |
|
| tst.go:27:26:27:38 | call to len | semmle.label | call to len |
|
||||||
| tst.go:27:30:27:37 | jsonData | semmle.label | jsonData |
|
| tst.go:27:30:27:37 | jsonData | semmle.label | jsonData |
|
||||||
| tst.go:34:2:34:30 | extract:0 ... = ... | semmle.label | extract:0 ... = ... |
|
| tst.go:34:2:34:30 | ... = ...[0] | semmle.label | ... = ...[0] |
|
||||||
| tst.go:35:22:35:34 | call to len | semmle.label | call to len |
|
| tst.go:35:22:35:34 | call to len | semmle.label | call to len |
|
||||||
| tst.go:35:26:35:33 | jsonData | semmle.label | jsonData |
|
| tst.go:35:26:35:33 | jsonData | semmle.label | jsonData |
|
||||||
subpaths
|
subpaths
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
| DisabledCertificateCheck.go:10:32:10:55 | lit-init key-value pair | InsecureSkipVerify should not be used in production code. |
|
| DisabledCertificateCheck.go:10:32:10:55 | init of key-value pair | InsecureSkipVerify should not be used in production code. |
|
||||||
| main.go:9:2:9:30 | assign:0 ... = ... | InsecureSkipVerify should not be used in production code. |
|
| main.go:9:2:9:23 | assignment to field InsecureSkipVerify | InsecureSkipVerify should not be used in production code. |
|
||||||
| main.go:57:21:57:44 | lit-init key-value pair | InsecureSkipVerify should not be used in production code. |
|
| main.go:57:21:57:44 | init of key-value pair | InsecureSkipVerify should not be used in production code. |
|
||||||
| main.go:62:32:62:55 | lit-init key-value pair | InsecureSkipVerify should not be used in production code. |
|
| main.go:62:32:62:55 | init of key-value pair | InsecureSkipVerify should not be used in production code. |
|
||||||
|
|||||||
@@ -1,85 +1,80 @@
|
|||||||
#select
|
#select
|
||||||
| klog.go:23:15:23:20 | header | klog.go:21:30:21:37 | selection of Header | klog.go:23:15:23:20 | header | $@ flows to a logging call. | klog.go:21:30:21:37 | selection of Header | Sensitive data returned by HTTP request headers |
|
| klog.go:23:15:23:20 | header | klog.go:21:30:21:37 | selection of Header | klog.go:23:15:23:20 | header | $@ flows to a logging call. | klog.go:21:30:21:37 | selection of Header | Sensitive data returned by HTTP request headers |
|
||||||
| klog.go:29:13:29:41 | call to Get | klog.go:29:13:29:20 | selection of Header | klog.go:29:13:29:41 | call to Get | $@ flows to a logging call. | klog.go:29:13:29:20 | selection of Header | Sensitive data returned by HTTP request headers |
|
| klog.go:29:13:29:41 | call to Get | klog.go:29:13:29:20 | selection of Header | klog.go:29:13:29:41 | call to Get | $@ flows to a logging call. | klog.go:29:13:29:20 | selection of Header | Sensitive data returned by HTTP request headers |
|
||||||
| main.go:19:12:19:19 | password | main.go:17:2:17:23 | SSA def(password) | main.go:19:12:19:19 | password | $@ flows to a logging call. | main.go:17:2:17:23 | SSA def(password) | Sensitive data returned by an access to password |
|
| main.go:19:12:19:19 | password | main.go:17:2:17:9 | SSA def(password) | main.go:19:12:19:19 | password | $@ flows to a logging call. | main.go:17:2:17:9 | SSA def(password) | Sensitive data returned by an access to password |
|
||||||
| main.go:20:19:20:26 | password | main.go:17:2:17:23 | SSA def(password) | main.go:20:19:20:26 | password | $@ flows to a logging call. | main.go:17:2:17:23 | SSA def(password) | Sensitive data returned by an access to password |
|
| main.go:20:19:20:26 | password | main.go:17:2:17:9 | SSA def(password) | main.go:20:19:20:26 | password | $@ flows to a logging call. | main.go:17:2:17:9 | SSA def(password) | Sensitive data returned by an access to password |
|
||||||
| main.go:21:13:21:20 | password | main.go:17:2:17:23 | SSA def(password) | main.go:21:13:21:20 | password | $@ flows to a logging call. | main.go:17:2:17:23 | SSA def(password) | Sensitive data returned by an access to password |
|
| main.go:21:13:21:20 | password | main.go:17:2:17:9 | SSA def(password) | main.go:21:13:21:20 | password | $@ flows to a logging call. | main.go:17:2:17:9 | SSA def(password) | Sensitive data returned by an access to password |
|
||||||
| main.go:22:14:22:21 | password | main.go:17:2:17:23 | SSA def(password) | main.go:22:14:22:21 | password | $@ flows to a logging call. | main.go:17:2:17:23 | SSA def(password) | Sensitive data returned by an access to password |
|
| main.go:22:14:22:21 | password | main.go:17:2:17:9 | SSA def(password) | main.go:22:14:22:21 | password | $@ flows to a logging call. | main.go:17:2:17:9 | SSA def(password) | Sensitive data returned by an access to password |
|
||||||
| main.go:24:13:24:20 | password | main.go:17:2:17:23 | SSA def(password) | main.go:24:13:24:20 | password | $@ flows to a logging call. | main.go:17:2:17:23 | SSA def(password) | Sensitive data returned by an access to password |
|
| main.go:24:13:24:20 | password | main.go:17:2:17:9 | SSA def(password) | main.go:24:13:24:20 | password | $@ flows to a logging call. | main.go:17:2:17:9 | SSA def(password) | Sensitive data returned by an access to password |
|
||||||
| main.go:27:20:27:27 | password | main.go:17:2:17:23 | SSA def(password) | main.go:27:20:27:27 | password | $@ flows to a logging call. | main.go:17:2:17:23 | SSA def(password) | Sensitive data returned by an access to password |
|
| main.go:27:20:27:27 | password | main.go:17:2:17:9 | SSA def(password) | main.go:27:20:27:27 | password | $@ flows to a logging call. | main.go:17:2:17:9 | SSA def(password) | Sensitive data returned by an access to password |
|
||||||
| main.go:30:14:30:21 | password | main.go:17:2:17:23 | SSA def(password) | main.go:30:14:30:21 | password | $@ flows to a logging call. | main.go:17:2:17:23 | SSA def(password) | Sensitive data returned by an access to password |
|
| main.go:30:14:30:21 | password | main.go:17:2:17:9 | SSA def(password) | main.go:30:14:30:21 | password | $@ flows to a logging call. | main.go:17:2:17:9 | SSA def(password) | Sensitive data returned by an access to password |
|
||||||
| main.go:33:15:33:22 | password | main.go:17:2:17:23 | SSA def(password) | main.go:33:15:33:22 | password | $@ flows to a logging call. | main.go:17:2:17:23 | SSA def(password) | Sensitive data returned by an access to password |
|
| main.go:33:15:33:22 | password | main.go:17:2:17:9 | SSA def(password) | main.go:33:15:33:22 | password | $@ flows to a logging call. | main.go:17:2:17:9 | SSA def(password) | Sensitive data returned by an access to password |
|
||||||
| main.go:36:13:36:20 | password | main.go:17:2:17:23 | SSA def(password) | main.go:36:13:36:20 | password | $@ flows to a logging call. | main.go:17:2:17:23 | SSA def(password) | Sensitive data returned by an access to password |
|
| main.go:36:13:36:20 | password | main.go:17:2:17:9 | SSA def(password) | main.go:36:13:36:20 | password | $@ flows to a logging call. | main.go:17:2:17:9 | SSA def(password) | Sensitive data returned by an access to password |
|
||||||
| main.go:39:20:39:27 | password | main.go:17:2:17:23 | SSA def(password) | main.go:39:20:39:27 | password | $@ flows to a logging call. | main.go:17:2:17:23 | SSA def(password) | Sensitive data returned by an access to password |
|
| main.go:39:20:39:27 | password | main.go:17:2:17:9 | SSA def(password) | main.go:39:20:39:27 | password | $@ flows to a logging call. | main.go:17:2:17:9 | SSA def(password) | Sensitive data returned by an access to password |
|
||||||
| main.go:42:14:42:21 | password | main.go:17:2:17:23 | SSA def(password) | main.go:42:14:42:21 | password | $@ flows to a logging call. | main.go:17:2:17:23 | SSA def(password) | Sensitive data returned by an access to password |
|
| main.go:42:14:42:21 | password | main.go:17:2:17:9 | SSA def(password) | main.go:42:14:42:21 | password | $@ flows to a logging call. | main.go:17:2:17:9 | SSA def(password) | Sensitive data returned by an access to password |
|
||||||
| main.go:45:15:45:22 | password | main.go:17:2:17:23 | SSA def(password) | main.go:45:15:45:22 | password | $@ flows to a logging call. | main.go:17:2:17:23 | SSA def(password) | Sensitive data returned by an access to password |
|
| main.go:45:15:45:22 | password | main.go:17:2:17:9 | SSA def(password) | main.go:45:15:45:22 | password | $@ flows to a logging call. | main.go:17:2:17:9 | SSA def(password) | Sensitive data returned by an access to password |
|
||||||
| main.go:47:16:47:23 | password | main.go:17:2:17:23 | SSA def(password) | main.go:47:16:47:23 | password | $@ flows to a logging call. | main.go:17:2:17:23 | SSA def(password) | Sensitive data returned by an access to password |
|
| main.go:47:16:47:23 | password | main.go:17:2:17:9 | SSA def(password) | main.go:47:16:47:23 | password | $@ flows to a logging call. | main.go:17:2:17:9 | SSA def(password) | Sensitive data returned by an access to password |
|
||||||
| main.go:51:10:51:17 | password | main.go:17:2:17:23 | SSA def(password) | main.go:51:10:51:17 | password | $@ flows to a logging call. | main.go:17:2:17:23 | SSA def(password) | Sensitive data returned by an access to password |
|
| main.go:51:10:51:17 | password | main.go:17:2:17:9 | SSA def(password) | main.go:51:10:51:17 | password | $@ flows to a logging call. | main.go:17:2:17:9 | SSA def(password) | Sensitive data returned by an access to password |
|
||||||
| main.go:52:17:52:24 | password | main.go:17:2:17:23 | SSA def(password) | main.go:52:17:52:24 | password | $@ flows to a logging call. | main.go:17:2:17:23 | SSA def(password) | Sensitive data returned by an access to password |
|
| main.go:52:17:52:24 | password | main.go:17:2:17:9 | SSA def(password) | main.go:52:17:52:24 | password | $@ flows to a logging call. | main.go:17:2:17:9 | SSA def(password) | Sensitive data returned by an access to password |
|
||||||
| main.go:53:11:53:18 | password | main.go:17:2:17:23 | SSA def(password) | main.go:53:11:53:18 | password | $@ flows to a logging call. | main.go:17:2:17:23 | SSA def(password) | Sensitive data returned by an access to password |
|
| main.go:53:11:53:18 | password | main.go:17:2:17:9 | SSA def(password) | main.go:53:11:53:18 | password | $@ flows to a logging call. | main.go:17:2:17:9 | SSA def(password) | Sensitive data returned by an access to password |
|
||||||
| main.go:54:12:54:19 | password | main.go:17:2:17:23 | SSA def(password) | main.go:54:12:54:19 | password | $@ flows to a logging call. | main.go:17:2:17:23 | SSA def(password) | Sensitive data returned by an access to password |
|
| main.go:54:12:54:19 | password | main.go:17:2:17:9 | SSA def(password) | main.go:54:12:54:19 | password | $@ flows to a logging call. | main.go:17:2:17:9 | SSA def(password) | Sensitive data returned by an access to password |
|
||||||
| main.go:56:11:56:18 | password | main.go:17:2:17:23 | SSA def(password) | main.go:56:11:56:18 | password | $@ flows to a logging call. | main.go:17:2:17:23 | SSA def(password) | Sensitive data returned by an access to password |
|
| main.go:56:11:56:18 | password | main.go:17:2:17:9 | SSA def(password) | main.go:56:11:56:18 | password | $@ flows to a logging call. | main.go:17:2:17:9 | SSA def(password) | Sensitive data returned by an access to password |
|
||||||
| main.go:59:18:59:25 | password | main.go:17:2:17:23 | SSA def(password) | main.go:59:18:59:25 | password | $@ flows to a logging call. | main.go:17:2:17:23 | SSA def(password) | Sensitive data returned by an access to password |
|
| main.go:59:18:59:25 | password | main.go:17:2:17:9 | SSA def(password) | main.go:59:18:59:25 | password | $@ flows to a logging call. | main.go:17:2:17:9 | SSA def(password) | Sensitive data returned by an access to password |
|
||||||
| main.go:62:12:62:19 | password | main.go:17:2:17:23 | SSA def(password) | main.go:62:12:62:19 | password | $@ flows to a logging call. | main.go:17:2:17:23 | SSA def(password) | Sensitive data returned by an access to password |
|
| main.go:62:12:62:19 | password | main.go:17:2:17:9 | SSA def(password) | main.go:62:12:62:19 | password | $@ flows to a logging call. | main.go:17:2:17:9 | SSA def(password) | Sensitive data returned by an access to password |
|
||||||
| main.go:65:13:65:20 | password | main.go:17:2:17:23 | SSA def(password) | main.go:65:13:65:20 | password | $@ flows to a logging call. | main.go:17:2:17:23 | SSA def(password) | Sensitive data returned by an access to password |
|
| main.go:65:13:65:20 | password | main.go:17:2:17:9 | SSA def(password) | main.go:65:13:65:20 | password | $@ flows to a logging call. | main.go:17:2:17:9 | SSA def(password) | Sensitive data returned by an access to password |
|
||||||
| main.go:68:11:68:18 | password | main.go:17:2:17:23 | SSA def(password) | main.go:68:11:68:18 | password | $@ flows to a logging call. | main.go:17:2:17:23 | SSA def(password) | Sensitive data returned by an access to password |
|
| main.go:68:11:68:18 | password | main.go:17:2:17:9 | SSA def(password) | main.go:68:11:68:18 | password | $@ flows to a logging call. | main.go:17:2:17:9 | SSA def(password) | Sensitive data returned by an access to password |
|
||||||
| main.go:71:18:71:25 | password | main.go:17:2:17:23 | SSA def(password) | main.go:71:18:71:25 | password | $@ flows to a logging call. | main.go:17:2:17:23 | SSA def(password) | Sensitive data returned by an access to password |
|
| main.go:71:18:71:25 | password | main.go:17:2:17:9 | SSA def(password) | main.go:71:18:71:25 | password | $@ flows to a logging call. | main.go:17:2:17:9 | SSA def(password) | Sensitive data returned by an access to password |
|
||||||
| main.go:74:12:74:19 | password | main.go:17:2:17:23 | SSA def(password) | main.go:74:12:74:19 | password | $@ flows to a logging call. | main.go:17:2:17:23 | SSA def(password) | Sensitive data returned by an access to password |
|
| main.go:74:12:74:19 | password | main.go:17:2:17:9 | SSA def(password) | main.go:74:12:74:19 | password | $@ flows to a logging call. | main.go:17:2:17:9 | SSA def(password) | Sensitive data returned by an access to password |
|
||||||
| main.go:77:13:77:20 | password | main.go:17:2:17:23 | SSA def(password) | main.go:77:13:77:20 | password | $@ flows to a logging call. | main.go:17:2:17:23 | SSA def(password) | Sensitive data returned by an access to password |
|
| main.go:77:13:77:20 | password | main.go:17:2:17:9 | SSA def(password) | main.go:77:13:77:20 | password | $@ flows to a logging call. | main.go:17:2:17:9 | SSA def(password) | Sensitive data returned by an access to password |
|
||||||
| main.go:79:14:79:21 | password | main.go:17:2:17:23 | SSA def(password) | main.go:79:14:79:21 | password | $@ flows to a logging call. | main.go:17:2:17:23 | SSA def(password) | Sensitive data returned by an access to password |
|
| main.go:79:14:79:21 | password | main.go:17:2:17:9 | SSA def(password) | main.go:79:14:79:21 | password | $@ flows to a logging call. | main.go:17:2:17:9 | SSA def(password) | Sensitive data returned by an access to password |
|
||||||
| main.go:82:12:82:19 | password | main.go:17:2:17:23 | SSA def(password) | main.go:82:12:82:19 | password | $@ flows to a logging call. | main.go:17:2:17:23 | SSA def(password) | Sensitive data returned by an access to password |
|
| main.go:82:12:82:19 | password | main.go:17:2:17:9 | SSA def(password) | main.go:82:12:82:19 | password | $@ flows to a logging call. | main.go:17:2:17:9 | SSA def(password) | Sensitive data returned by an access to password |
|
||||||
| main.go:83:17:83:24 | password | main.go:17:2:17:23 | SSA def(password) | main.go:83:17:83:24 | password | $@ flows to a logging call. | main.go:17:2:17:23 | SSA def(password) | Sensitive data returned by an access to password |
|
| main.go:83:17:83:24 | password | main.go:17:2:17:9 | SSA def(password) | main.go:83:17:83:24 | password | $@ flows to a logging call. | main.go:17:2:17:9 | SSA def(password) | Sensitive data returned by an access to password |
|
||||||
| main.go:87:29:87:34 | fields | main.go:17:2:17:23 | SSA def(password) | main.go:87:29:87:34 | fields | $@ flows to a logging call. | main.go:17:2:17:23 | SSA def(password) | Sensitive data returned by an access to password |
|
| main.go:87:29:87:34 | fields | main.go:17:2:17:9 | SSA def(password) | main.go:87:29:87:34 | fields | $@ flows to a logging call. | main.go:17:2:17:9 | SSA def(password) | Sensitive data returned by an access to password |
|
||||||
| main.go:90:35:90:42 | password | main.go:17:2:17:23 | SSA def(password) | main.go:90:35:90:42 | password | $@ flows to a logging call. | main.go:17:2:17:23 | SSA def(password) | Sensitive data returned by an access to password |
|
| main.go:90:35:90:42 | password | main.go:17:2:17:9 | SSA def(password) | main.go:90:35:90:42 | password | $@ flows to a logging call. | main.go:17:2:17:9 | SSA def(password) | Sensitive data returned by an access to password |
|
||||||
| overrides.go:13:14:13:23 | call to String | overrides.go:8:2:8:40 | SSA def(password) | overrides.go:13:14:13:23 | call to String | $@ flows to a logging call. | overrides.go:8:2:8:40 | SSA def(password) | Sensitive data returned by an access to password |
|
| overrides.go:13:14:13:23 | call to String | overrides.go:8:2:8:9 | SSA def(password) | overrides.go:13:14:13:23 | call to String | $@ flows to a logging call. | overrides.go:8:2:8:9 | SSA def(password) | Sensitive data returned by an access to password |
|
||||||
| passwords.go:9:14:9:14 | x | passwords.go:21:2:21:23 | SSA def(password) | passwords.go:9:14:9:14 | x | $@ flows to a logging call. | passwords.go:21:2:21:23 | SSA def(password) | Sensitive data returned by an access to password |
|
| passwords.go:9:14:9:14 | x | passwords.go:21:2:21:9 | SSA def(password) | passwords.go:9:14:9:14 | x | $@ flows to a logging call. | passwords.go:21:2:21:9 | SSA def(password) | Sensitive data returned by an access to password |
|
||||||
| passwords.go:25:14:25:21 | password | passwords.go:21:2:21:23 | SSA def(password) | passwords.go:25:14:25:21 | password | $@ flows to a logging call. | passwords.go:21:2:21:23 | SSA def(password) | Sensitive data returned by an access to password |
|
| passwords.go:25:14:25:21 | password | passwords.go:21:2:21:9 | SSA def(password) | passwords.go:25:14:25:21 | password | $@ flows to a logging call. | passwords.go:21:2:21:9 | SSA def(password) | Sensitive data returned by an access to password |
|
||||||
| passwords.go:26:14:26:23 | selection of password | passwords.go:26:14:26:23 | selection of password | passwords.go:26:14:26:23 | selection of password | $@ flows to a logging call. | passwords.go:26:14:26:23 | selection of password | Sensitive data returned by an access to password |
|
| passwords.go:26:14:26:23 | selection of password | passwords.go:26:14:26:23 | selection of password | passwords.go:26:14:26:23 | selection of password | $@ flows to a logging call. | passwords.go:26:14:26:23 | selection of password | Sensitive data returned by an access to password |
|
||||||
| passwords.go:27:14:27:26 | call to getPassword | passwords.go:27:14:27:26 | call to getPassword | passwords.go:27:14:27:26 | call to getPassword | $@ flows to a logging call. | passwords.go:27:14:27:26 | call to getPassword | Sensitive data returned by a call to getPassword |
|
| passwords.go:27:14:27:26 | call to getPassword | passwords.go:27:14:27:26 | call to getPassword | passwords.go:27:14:27:26 | call to getPassword | $@ flows to a logging call. | passwords.go:27:14:27:26 | call to getPassword | Sensitive data returned by a call to getPassword |
|
||||||
| passwords.go:28:14:28:28 | call to getPassword | passwords.go:28:14:28:28 | call to getPassword | passwords.go:28:14:28:28 | call to getPassword | $@ flows to a logging call. | passwords.go:28:14:28:28 | call to getPassword | Sensitive data returned by a call to getPassword |
|
| passwords.go:28:14:28:28 | call to getPassword | passwords.go:28:14:28:28 | call to getPassword | passwords.go:28:14:28:28 | call to getPassword | $@ flows to a logging call. | passwords.go:28:14:28:28 | call to getPassword | Sensitive data returned by a call to getPassword |
|
||||||
| passwords.go:33:13:33:20 | password | passwords.go:21:2:21:23 | SSA def(password) | passwords.go:33:13:33:20 | password | $@ flows to a logging call. | passwords.go:21:2:21:23 | SSA def(password) | Sensitive data returned by an access to password |
|
| passwords.go:33:13:33:20 | password | passwords.go:21:2:21:9 | SSA def(password) | passwords.go:33:13:33:20 | password | $@ flows to a logging call. | passwords.go:21:2:21:9 | SSA def(password) | Sensitive data returned by an access to password |
|
||||||
| passwords.go:36:14:36:35 | ...+... | passwords.go:21:2:21:23 | SSA def(password) | passwords.go:36:14:36:35 | ...+... | $@ flows to a logging call. | passwords.go:21:2:21:23 | SSA def(password) | Sensitive data returned by an access to password |
|
| passwords.go:36:14:36:35 | ...+... | passwords.go:21:2:21:9 | SSA def(password) | passwords.go:36:14:36:35 | ...+... | $@ flows to a logging call. | passwords.go:21:2:21:9 | SSA def(password) | Sensitive data returned by an access to password |
|
||||||
| passwords.go:41:14:41:17 | obj1 | passwords.go:39:3:39:13 | key-value pair | passwords.go:41:14:41:17 | obj1 | $@ flows to a logging call. | passwords.go:39:3:39:13 | key-value pair | Sensitive data returned by an access to password |
|
|
||||||
| passwords.go:41:14:41:17 | obj1 | passwords.go:39:13:39:13 | x | passwords.go:41:14:41:17 | obj1 | $@ flows to a logging call. | passwords.go:39:13:39:13 | x | Sensitive data returned by an access to password |
|
| passwords.go:41:14:41:17 | obj1 | passwords.go:39:13:39:13 | x | passwords.go:41:14:41:17 | obj1 | $@ flows to a logging call. | passwords.go:39:13:39:13 | x | Sensitive data returned by an access to password |
|
||||||
| passwords.go:46:14:46:17 | obj2 | passwords.go:21:2:21:23 | SSA def(password) | passwords.go:46:14:46:17 | obj2 | $@ flows to a logging call. | passwords.go:21:2:21:23 | SSA def(password) | Sensitive data returned by an access to password |
|
| passwords.go:46:14:46:17 | obj2 | passwords.go:21:2:21:9 | SSA def(password) | passwords.go:46:14:46:17 | obj2 | $@ flows to a logging call. | passwords.go:21:2:21:9 | SSA def(password) | Sensitive data returned by an access to password |
|
||||||
| passwords.go:53:14:53:27 | fixed_password | passwords.go:52:2:52:44 | SSA def(fixed_password) | passwords.go:53:14:53:27 | fixed_password | $@ flows to a logging call. | passwords.go:52:2:52:44 | SSA def(fixed_password) | Sensitive data returned by an access to fixed_password |
|
| passwords.go:53:14:53:27 | fixed_password | passwords.go:52:2:52:15 | SSA def(fixed_password) | passwords.go:53:14:53:27 | fixed_password | $@ flows to a logging call. | passwords.go:52:2:52:15 | SSA def(fixed_password) | Sensitive data returned by an access to fixed_password |
|
||||||
| passwords.go:65:14:65:44 | struct literal | passwords.go:65:25:65:43 | key-value pair | passwords.go:65:14:65:44 | struct literal | $@ flows to a logging call. | passwords.go:65:25:65:43 | key-value pair | Sensitive data returned by an access to password |
|
|
||||||
| passwords.go:91:14:91:26 | utilityObject | passwords.go:89:3:89:36 | key-value pair | passwords.go:91:14:91:26 | utilityObject | $@ flows to a logging call. | passwords.go:89:3:89:36 | key-value pair | Sensitive data returned by an access to passwordSet |
|
|
||||||
| passwords.go:91:14:91:26 | utilityObject | passwords.go:89:16:89:36 | call to make | passwords.go:91:14:91:26 | utilityObject | $@ flows to a logging call. | passwords.go:89:16:89:36 | call to make | Sensitive data returned by an access to passwordSet |
|
| passwords.go:91:14:91:26 | utilityObject | passwords.go:89:16:89:36 | call to make | passwords.go:91:14:91:26 | utilityObject | $@ flows to a logging call. | passwords.go:89:16:89:36 | call to make | Sensitive data returned by an access to passwordSet |
|
||||||
| passwords.go:94:23:94:28 | secret | passwords.go:21:2:21:23 | SSA def(password) | passwords.go:94:23:94:28 | secret | $@ flows to a logging call. | passwords.go:21:2:21:23 | SSA def(password) | Sensitive data returned by an access to password |
|
| passwords.go:94:23:94:28 | secret | passwords.go:21:2:21:9 | SSA def(password) | passwords.go:94:23:94:28 | secret | $@ flows to a logging call. | passwords.go:21:2:21:9 | SSA def(password) | Sensitive data returned by an access to password |
|
||||||
| passwords.go:104:15:104:40 | ...+... | passwords.go:21:2:21:23 | SSA def(password) | passwords.go:104:15:104:40 | ...+... | $@ flows to a logging call. | passwords.go:21:2:21:23 | SSA def(password) | Sensitive data returned by an access to password |
|
| passwords.go:104:15:104:40 | ...+... | passwords.go:21:2:21:9 | SSA def(password) | passwords.go:104:15:104:40 | ...+... | $@ flows to a logging call. | passwords.go:21:2:21:9 | SSA def(password) | Sensitive data returned by an access to password |
|
||||||
| passwords.go:110:16:110:41 | ...+... | passwords.go:21:2:21:23 | SSA def(password) | passwords.go:110:16:110:41 | ...+... | $@ flows to a logging call. | passwords.go:21:2:21:23 | SSA def(password) | Sensitive data returned by an access to password |
|
| passwords.go:110:16:110:41 | ...+... | passwords.go:21:2:21:9 | SSA def(password) | passwords.go:110:16:110:41 | ...+... | $@ flows to a logging call. | passwords.go:21:2:21:9 | SSA def(password) | Sensitive data returned by an access to password |
|
||||||
| passwords.go:115:15:115:40 | ...+... | passwords.go:21:2:21:23 | SSA def(password) | passwords.go:115:15:115:40 | ...+... | $@ flows to a logging call. | passwords.go:21:2:21:23 | SSA def(password) | Sensitive data returned by an access to password |
|
| passwords.go:115:15:115:40 | ...+... | passwords.go:21:2:21:9 | SSA def(password) | passwords.go:115:15:115:40 | ...+... | $@ flows to a logging call. | passwords.go:21:2:21:9 | SSA def(password) | Sensitive data returned by an access to password |
|
||||||
| passwords.go:119:14:119:45 | ...+... | passwords.go:118:6:118:50 | SSA def(password1) | passwords.go:119:14:119:45 | ...+... | $@ flows to a logging call. | passwords.go:118:6:118:50 | SSA def(password1) | Sensitive data returned by an access to password1 |
|
| passwords.go:119:14:119:45 | ...+... | passwords.go:118:6:118:14 | SSA def(password1) | passwords.go:119:14:119:45 | ...+... | $@ flows to a logging call. | passwords.go:118:6:118:14 | SSA def(password1) | Sensitive data returned by an access to password1 |
|
||||||
| passwords.go:129:14:129:19 | config | passwords.go:21:2:21:23 | SSA def(password) | passwords.go:129:14:129:19 | config | $@ flows to a logging call. | passwords.go:21:2:21:23 | SSA def(password) | Sensitive data returned by an access to password |
|
| passwords.go:129:14:129:19 | config | passwords.go:21:2:21:9 | SSA def(password) | passwords.go:129:14:129:19 | config | $@ flows to a logging call. | passwords.go:21:2:21:9 | SSA def(password) | Sensitive data returned by an access to password |
|
||||||
| passwords.go:129:14:129:19 | config | passwords.go:123:3:123:14 | key-value pair | passwords.go:129:14:129:19 | config | $@ flows to a logging call. | passwords.go:123:3:123:14 | key-value pair | Sensitive data returned by an access to password |
|
|
||||||
| passwords.go:129:14:129:19 | config | passwords.go:123:13:123:14 | x3 | passwords.go:129:14:129:19 | config | $@ flows to a logging call. | passwords.go:123:13:123:14 | x3 | Sensitive data returned by an access to password |
|
| passwords.go:129:14:129:19 | config | passwords.go:123:13:123:14 | x3 | passwords.go:129:14:129:19 | config | $@ flows to a logging call. | passwords.go:123:13:123:14 | x3 | Sensitive data returned by an access to password |
|
||||||
| passwords.go:129:14:129:19 | config | passwords.go:126:13:126:25 | call to getPassword | passwords.go:129:14:129:19 | config | $@ flows to a logging call. | passwords.go:126:13:126:25 | call to getPassword | Sensitive data returned by a call to getPassword |
|
| passwords.go:129:14:129:19 | config | passwords.go:126:13:126:25 | call to getPassword | passwords.go:129:14:129:19 | config | $@ flows to a logging call. | passwords.go:126:13:126:25 | call to getPassword | Sensitive data returned by a call to getPassword |
|
||||||
| passwords.go:130:14:130:21 | selection of x | passwords.go:21:2:21:23 | SSA def(password) | passwords.go:130:14:130:21 | selection of x | $@ flows to a logging call. | passwords.go:21:2:21:23 | SSA def(password) | Sensitive data returned by an access to password |
|
| passwords.go:130:14:130:21 | selection of x | passwords.go:21:2:21:9 | SSA def(password) | passwords.go:130:14:130:21 | selection of x | $@ flows to a logging call. | passwords.go:21:2:21:9 | SSA def(password) | Sensitive data returned by an access to password |
|
||||||
| passwords.go:131:14:131:21 | selection of y | passwords.go:126:13:126:25 | call to getPassword | passwords.go:131:14:131:21 | selection of y | $@ flows to a logging call. | passwords.go:126:13:126:25 | call to getPassword | Sensitive data returned by a call to getPassword |
|
| passwords.go:131:14:131:21 | selection of y | passwords.go:126:13:126:25 | call to getPassword | passwords.go:131:14:131:21 | selection of y | $@ flows to a logging call. | passwords.go:126:13:126:25 | call to getPassword | Sensitive data returned by a call to getPassword |
|
||||||
| protobuf.go:14:14:14:35 | call to GetDescription | protobuf.go:9:2:9:23 | SSA def(password) | protobuf.go:14:14:14:35 | call to GetDescription | $@ flows to a logging call. | protobuf.go:9:2:9:23 | SSA def(password) | Sensitive data returned by an access to password |
|
| protobuf.go:14:14:14:35 | call to GetDescription | protobuf.go:9:2:9:9 | SSA def(password) | protobuf.go:14:14:14:35 | call to GetDescription | $@ flows to a logging call. | protobuf.go:9:2:9:9 | SSA def(password) | Sensitive data returned by an access to password |
|
||||||
| server1.go:19:15:19:19 | user3 | server1.go:17:4:17:63 | key-value pair | server1.go:19:15:19:19 | user3 | $@ flows to a logging call. | server1.go:17:4:17:63 | key-value pair | Sensitive data returned by an access to password |
|
|
||||||
edges
|
edges
|
||||||
| klog.go:21:3:26:3 | extract:1 range statement | klog.go:22:27:22:33 | headers | provenance | |
|
| klog.go:21:3:26:3 | range statement[1] | klog.go:22:27:22:33 | headers | provenance | |
|
||||||
| klog.go:21:30:21:37 | selection of Header | klog.go:21:3:26:3 | extract:1 range statement | provenance | Src:MaD:11 Config |
|
| klog.go:21:30:21:37 | selection of Header | klog.go:21:3:26:3 | range statement[1] | provenance | Src:MaD:11 Config |
|
||||||
| klog.go:22:4:25:4 | extract:1 range statement | klog.go:23:15:23:20 | header | provenance | |
|
| klog.go:22:4:25:4 | range statement[1] | klog.go:23:15:23:20 | header | provenance | |
|
||||||
| klog.go:22:27:22:33 | headers | klog.go:22:4:25:4 | extract:1 range statement | provenance | Config |
|
| klog.go:22:27:22:33 | headers | klog.go:22:4:25:4 | range statement[1] | provenance | Config |
|
||||||
| klog.go:29:13:29:20 | selection of Header | klog.go:29:13:29:41 | call to Get | provenance | Src:MaD:11 Config |
|
| klog.go:29:13:29:20 | selection of Header | klog.go:29:13:29:41 | call to Get | provenance | Src:MaD:11 Config |
|
||||||
| main.go:17:2:17:23 | SSA def(password) | main.go:19:12:19:19 | password | provenance | |
|
| main.go:17:2:17:9 | SSA def(password) | main.go:19:12:19:19 | password | provenance | |
|
||||||
| main.go:17:2:17:23 | SSA def(password) | main.go:20:19:20:26 | password | provenance | |
|
| main.go:17:2:17:9 | SSA def(password) | main.go:20:19:20:26 | password | provenance | |
|
||||||
| main.go:17:2:17:23 | SSA def(password) | main.go:21:13:21:20 | password | provenance | Sink:MaD:6 |
|
| main.go:17:2:17:9 | SSA def(password) | main.go:21:13:21:20 | password | provenance | Sink:MaD:6 |
|
||||||
| main.go:17:2:17:23 | SSA def(password) | main.go:22:14:22:21 | password | provenance | |
|
| main.go:17:2:17:9 | SSA def(password) | main.go:22:14:22:21 | password | provenance | |
|
||||||
| main.go:17:2:17:23 | SSA def(password) | main.go:24:13:24:20 | password | provenance | |
|
| main.go:17:2:17:9 | SSA def(password) | main.go:24:13:24:20 | password | provenance | |
|
||||||
| main.go:17:2:17:23 | SSA def(password) | main.go:27:20:27:27 | password | provenance | |
|
| main.go:17:2:17:9 | SSA def(password) | main.go:27:20:27:27 | password | provenance | |
|
||||||
| main.go:17:2:17:23 | SSA def(password) | main.go:30:14:30:21 | password | provenance | Sink:MaD:3 |
|
| main.go:17:2:17:9 | SSA def(password) | main.go:30:14:30:21 | password | provenance | Sink:MaD:3 |
|
||||||
| main.go:17:2:17:23 | SSA def(password) | main.go:33:15:33:22 | password | provenance | |
|
| main.go:17:2:17:9 | SSA def(password) | main.go:33:15:33:22 | password | provenance | |
|
||||||
| main.go:17:2:17:23 | SSA def(password) | main.go:36:13:36:20 | password | provenance | |
|
| main.go:17:2:17:9 | SSA def(password) | main.go:36:13:36:20 | password | provenance | |
|
||||||
| main.go:17:2:17:23 | SSA def(password) | main.go:39:20:39:27 | password | provenance | |
|
| main.go:17:2:17:9 | SSA def(password) | main.go:39:20:39:27 | password | provenance | |
|
||||||
| main.go:17:2:17:23 | SSA def(password) | main.go:42:14:42:21 | password | provenance | Sink:MaD:5 |
|
| main.go:17:2:17:9 | SSA def(password) | main.go:42:14:42:21 | password | provenance | Sink:MaD:5 |
|
||||||
| main.go:17:2:17:23 | SSA def(password) | main.go:45:15:45:22 | password | provenance | |
|
| main.go:17:2:17:9 | SSA def(password) | main.go:45:15:45:22 | password | provenance | |
|
||||||
| main.go:17:2:17:23 | SSA def(password) | main.go:47:16:47:23 | password | provenance | Sink:MaD:4 |
|
| main.go:17:2:17:9 | SSA def(password) | main.go:47:16:47:23 | password | provenance | Sink:MaD:4 |
|
||||||
| main.go:17:2:17:23 | SSA def(password) | main.go:51:10:51:17 | password | provenance | |
|
| main.go:17:2:17:9 | SSA def(password) | main.go:51:10:51:17 | password | provenance | |
|
||||||
| main.go:17:2:17:23 | SSA def(password) | main.go:51:10:51:17 | password | provenance | |
|
| main.go:17:2:17:9 | SSA def(password) | main.go:51:10:51:17 | password | provenance | |
|
||||||
| main.go:51:10:51:17 | password | main.go:52:17:52:24 | password | provenance | |
|
| main.go:51:10:51:17 | password | main.go:52:17:52:24 | password | provenance | |
|
||||||
| main.go:51:10:51:17 | password | main.go:52:17:52:24 | password | provenance | |
|
| main.go:51:10:51:17 | password | main.go:52:17:52:24 | password | provenance | |
|
||||||
| main.go:52:17:52:24 | password | main.go:53:11:53:18 | password | provenance | |
|
| main.go:52:17:52:24 | password | main.go:53:11:53:18 | password | provenance | |
|
||||||
@@ -102,18 +97,17 @@ edges
|
|||||||
| main.go:86:2:86:7 | fields [postupdate] | main.go:87:29:87:34 | fields | provenance | Sink:MaD:2 |
|
| main.go:86:2:86:7 | fields [postupdate] | main.go:87:29:87:34 | fields | provenance | Sink:MaD:2 |
|
||||||
| main.go:86:19:86:26 | password | main.go:86:2:86:7 | fields [postupdate] | provenance | Config |
|
| main.go:86:19:86:26 | password | main.go:86:2:86:7 | fields [postupdate] | provenance | Config |
|
||||||
| main.go:86:19:86:26 | password | main.go:90:35:90:42 | password | provenance | Sink:MaD:1 |
|
| main.go:86:19:86:26 | password | main.go:90:35:90:42 | password | provenance | Sink:MaD:1 |
|
||||||
| overrides.go:8:2:8:40 | SSA def(password) | overrides.go:9:9:9:16 | password | provenance | |
|
| overrides.go:8:2:8:9 | SSA def(password) | overrides.go:9:9:9:16 | password | provenance | |
|
||||||
| overrides.go:9:9:9:16 | password | overrides.go:13:14:13:23 | call to String | provenance | |
|
| overrides.go:9:9:9:16 | password | overrides.go:13:14:13:23 | call to String | provenance | |
|
||||||
| passwords.go:8:22:10:1 | SSA def(x) | passwords.go:9:14:9:14 | x | provenance | |
|
| passwords.go:8:12:8:12 | SSA def(x) | passwords.go:9:14:9:14 | x | provenance | |
|
||||||
| passwords.go:21:2:21:23 | SSA def(password) | passwords.go:25:14:25:21 | password | provenance | |
|
| passwords.go:21:2:21:9 | SSA def(password) | passwords.go:25:14:25:21 | password | provenance | |
|
||||||
| passwords.go:21:2:21:23 | SSA def(password) | passwords.go:30:8:30:15 | password | provenance | |
|
| passwords.go:21:2:21:9 | SSA def(password) | passwords.go:30:8:30:15 | password | provenance | |
|
||||||
| passwords.go:21:2:21:23 | SSA def(password) | passwords.go:33:13:33:20 | password | provenance | |
|
| passwords.go:21:2:21:9 | SSA def(password) | passwords.go:33:13:33:20 | password | provenance | |
|
||||||
| passwords.go:21:2:21:23 | SSA def(password) | passwords.go:36:28:36:35 | password | provenance | |
|
| passwords.go:21:2:21:9 | SSA def(password) | passwords.go:36:28:36:35 | password | provenance | |
|
||||||
| passwords.go:30:8:30:15 | password | passwords.go:8:22:10:1 | SSA def(x) | provenance | |
|
| passwords.go:30:8:30:15 | password | passwords.go:8:12:8:12 | SSA def(x) | provenance | |
|
||||||
| passwords.go:36:28:36:35 | password | passwords.go:36:14:36:35 | ...+... | provenance | Config |
|
| passwords.go:36:28:36:35 | password | passwords.go:36:14:36:35 | ...+... | provenance | Config |
|
||||||
| passwords.go:36:28:36:35 | password | passwords.go:44:6:44:13 | password | provenance | |
|
| passwords.go:36:28:36:35 | password | passwords.go:44:6:44:13 | password | provenance | |
|
||||||
| passwords.go:38:10:40:2 | struct literal | passwords.go:41:14:41:17 | obj1 | provenance | |
|
| passwords.go:38:10:40:2 | struct literal | passwords.go:41:14:41:17 | obj1 | provenance | |
|
||||||
| passwords.go:39:3:39:13 | key-value pair | passwords.go:38:10:40:2 | struct literal | provenance | Config |
|
|
||||||
| passwords.go:39:13:39:13 | x | passwords.go:38:10:40:2 | struct literal | provenance | Config |
|
| passwords.go:39:13:39:13 | x | passwords.go:38:10:40:2 | struct literal | provenance | Config |
|
||||||
| passwords.go:43:10:45:2 | struct literal | passwords.go:46:14:46:17 | obj2 | provenance | |
|
| passwords.go:43:10:45:2 | struct literal | passwords.go:46:14:46:17 | obj2 | provenance | |
|
||||||
| passwords.go:44:6:44:13 | password | passwords.go:43:10:45:2 | struct literal | provenance | Config |
|
| passwords.go:44:6:44:13 | password | passwords.go:43:10:45:2 | struct literal | provenance | Config |
|
||||||
@@ -123,10 +117,8 @@ edges
|
|||||||
| passwords.go:50:11:50:18 | password | passwords.go:110:34:110:41 | password | provenance | |
|
| passwords.go:50:11:50:18 | password | passwords.go:110:34:110:41 | password | provenance | |
|
||||||
| passwords.go:50:11:50:18 | password | passwords.go:115:33:115:40 | password | provenance | |
|
| passwords.go:50:11:50:18 | password | passwords.go:115:33:115:40 | password | provenance | |
|
||||||
| passwords.go:50:11:50:18 | password | passwords.go:125:13:125:20 | password | provenance | |
|
| passwords.go:50:11:50:18 | password | passwords.go:125:13:125:20 | password | provenance | |
|
||||||
| passwords.go:52:2:52:44 | SSA def(fixed_password) | passwords.go:53:14:53:27 | fixed_password | provenance | |
|
| passwords.go:52:2:52:15 | SSA def(fixed_password) | passwords.go:53:14:53:27 | fixed_password | provenance | |
|
||||||
| passwords.go:65:25:65:43 | key-value pair | passwords.go:65:14:65:44 | struct literal | provenance | Config |
|
|
||||||
| passwords.go:88:19:90:2 | struct literal | passwords.go:91:14:91:26 | utilityObject | provenance | |
|
| passwords.go:88:19:90:2 | struct literal | passwords.go:91:14:91:26 | utilityObject | provenance | |
|
||||||
| passwords.go:89:3:89:36 | key-value pair | passwords.go:88:19:90:2 | struct literal | provenance | Config |
|
|
||||||
| passwords.go:89:16:89:36 | call to make | passwords.go:88:19:90:2 | struct literal | provenance | Config |
|
| passwords.go:89:16:89:36 | call to make | passwords.go:88:19:90:2 | struct literal | provenance | Config |
|
||||||
| passwords.go:104:33:104:40 | password | passwords.go:104:15:104:40 | ...+... | provenance | Config |
|
| passwords.go:104:33:104:40 | password | passwords.go:104:15:104:40 | ...+... | provenance | Config |
|
||||||
| passwords.go:104:33:104:40 | password | passwords.go:110:34:110:41 | password | provenance | |
|
| passwords.go:104:33:104:40 | password | passwords.go:110:34:110:41 | password | provenance | |
|
||||||
@@ -137,13 +129,12 @@ edges
|
|||||||
| passwords.go:110:34:110:41 | password | passwords.go:125:13:125:20 | password | provenance | |
|
| passwords.go:110:34:110:41 | password | passwords.go:125:13:125:20 | password | provenance | |
|
||||||
| passwords.go:115:33:115:40 | password | passwords.go:115:15:115:40 | ...+... | provenance | Config |
|
| passwords.go:115:33:115:40 | password | passwords.go:115:15:115:40 | ...+... | provenance | Config |
|
||||||
| passwords.go:115:33:115:40 | password | passwords.go:125:13:125:20 | password | provenance | |
|
| passwords.go:115:33:115:40 | password | passwords.go:125:13:125:20 | password | provenance | |
|
||||||
| passwords.go:118:6:118:50 | SSA def(password1) | passwords.go:119:28:119:36 | password1 | provenance | |
|
| passwords.go:118:6:118:14 | SSA def(password1) | passwords.go:119:28:119:36 | password1 | provenance | |
|
||||||
| passwords.go:119:28:119:36 | password1 | passwords.go:119:28:119:45 | call to String | provenance | Config |
|
| passwords.go:119:28:119:36 | password1 | passwords.go:119:28:119:45 | call to String | provenance | Config |
|
||||||
| passwords.go:119:28:119:45 | call to String | passwords.go:119:14:119:45 | ...+... | provenance | Config |
|
| passwords.go:119:28:119:45 | call to String | passwords.go:119:14:119:45 | ...+... | provenance | Config |
|
||||||
| passwords.go:122:12:127:2 | struct literal | passwords.go:129:14:129:19 | config | provenance | |
|
| passwords.go:122:12:127:2 | struct literal | passwords.go:129:14:129:19 | config | provenance | |
|
||||||
| passwords.go:122:12:127:2 | struct literal [x] | passwords.go:130:14:130:19 | config [x] | provenance | |
|
| passwords.go:122:12:127:2 | struct literal [x] | passwords.go:130:14:130:19 | config [x] | provenance | |
|
||||||
| passwords.go:122:12:127:2 | struct literal [y] | passwords.go:131:14:131:19 | config [y] | provenance | |
|
| passwords.go:122:12:127:2 | struct literal [y] | passwords.go:131:14:131:19 | config [y] | provenance | |
|
||||||
| passwords.go:123:3:123:14 | key-value pair | passwords.go:122:12:127:2 | struct literal | provenance | Config |
|
|
||||||
| passwords.go:123:13:123:14 | x3 | passwords.go:122:12:127:2 | struct literal | provenance | Config |
|
| passwords.go:123:13:123:14 | x3 | passwords.go:122:12:127:2 | struct literal | provenance | Config |
|
||||||
| passwords.go:125:13:125:20 | password | passwords.go:122:12:127:2 | struct literal | provenance | Config |
|
| passwords.go:125:13:125:20 | password | passwords.go:122:12:127:2 | struct literal | provenance | Config |
|
||||||
| passwords.go:125:13:125:20 | password | passwords.go:122:12:127:2 | struct literal [x] | provenance | |
|
| passwords.go:125:13:125:20 | password | passwords.go:122:12:127:2 | struct literal [x] | provenance | |
|
||||||
@@ -151,17 +142,15 @@ edges
|
|||||||
| passwords.go:126:13:126:25 | call to getPassword | passwords.go:122:12:127:2 | struct literal [y] | provenance | |
|
| passwords.go:126:13:126:25 | call to getPassword | passwords.go:122:12:127:2 | struct literal [y] | provenance | |
|
||||||
| passwords.go:130:14:130:19 | config [x] | passwords.go:130:14:130:21 | selection of x | provenance | |
|
| passwords.go:130:14:130:19 | config [x] | passwords.go:130:14:130:21 | selection of x | provenance | |
|
||||||
| passwords.go:131:14:131:19 | config [y] | passwords.go:131:14:131:21 | selection of y | provenance | |
|
| passwords.go:131:14:131:19 | config [y] | passwords.go:131:14:131:21 | selection of y | provenance | |
|
||||||
| protobuf.go:9:2:9:23 | SSA def(password) | protobuf.go:12:22:12:29 | password | provenance | |
|
| protobuf.go:9:2:9:9 | SSA def(password) | protobuf.go:12:22:12:29 | password | provenance | |
|
||||||
| protobuf.go:12:2:12:6 | implicit-deref query [postupdate] [Description] | protobuf.go:12:2:12:6 | query [postupdate] [pointer, Description] | provenance | |
|
| protobuf.go:12:2:12:6 | implicit dereference [postupdate] [Description] | protobuf.go:12:2:12:6 | query [postupdate] [pointer, Description] | provenance | |
|
||||||
| protobuf.go:12:2:12:6 | query [postupdate] [pointer, Description] | protobuf.go:14:14:14:18 | query [pointer, Description] | provenance | |
|
| protobuf.go:12:2:12:6 | query [postupdate] [pointer, Description] | protobuf.go:14:14:14:18 | query [pointer, Description] | provenance | |
|
||||||
| protobuf.go:12:22:12:29 | password | protobuf.go:12:2:12:6 | implicit-deref query [postupdate] [Description] | provenance | |
|
| protobuf.go:12:22:12:29 | password | protobuf.go:12:2:12:6 | implicit dereference [postupdate] [Description] | provenance | |
|
||||||
| protobuf.go:14:14:14:18 | query [pointer, Description] | protobuf.go:14:14:14:35 | call to GetDescription | provenance | |
|
| protobuf.go:14:14:14:18 | query [pointer, Description] | protobuf.go:14:14:14:35 | call to GetDescription | provenance | |
|
||||||
| protobuf.go:14:14:14:18 | query [pointer, Description] | protos/query/query.pb.go:117:41:122:1 | SSA def(x) [pointer, Description] | provenance | |
|
| protobuf.go:14:14:14:18 | query [pointer, Description] | protos/query/query.pb.go:117:7:117:7 | SSA def(x) [pointer, Description] | provenance | |
|
||||||
| protos/query/query.pb.go:117:41:122:1 | SSA def(x) [pointer, Description] | protos/query/query.pb.go:119:10:119:10 | x [pointer, Description] | provenance | |
|
| protos/query/query.pb.go:117:7:117:7 | SSA def(x) [pointer, Description] | protos/query/query.pb.go:119:10:119:10 | x [pointer, Description] | provenance | |
|
||||||
| protos/query/query.pb.go:119:10:119:10 | implicit-deref x [Description] | protos/query/query.pb.go:119:10:119:22 | selection of Description | provenance | |
|
| protos/query/query.pb.go:119:10:119:10 | implicit dereference [Description] | protos/query/query.pb.go:119:10:119:22 | selection of Description | provenance | |
|
||||||
| protos/query/query.pb.go:119:10:119:10 | x [pointer, Description] | protos/query/query.pb.go:119:10:119:10 | implicit-deref x [Description] | provenance | |
|
| protos/query/query.pb.go:119:10:119:10 | x [pointer, Description] | protos/query/query.pb.go:119:10:119:10 | implicit dereference [Description] | provenance | |
|
||||||
| server1.go:16:15:18:3 | struct literal | server1.go:19:15:19:19 | user3 | provenance | |
|
|
||||||
| server1.go:17:4:17:63 | key-value pair | server1.go:16:15:18:3 | struct literal | provenance | Config |
|
|
||||||
models
|
models
|
||||||
| 1 | Sink: group:logrus; ; false; WithField; ; ; Argument[0..1]; log-injection; manual |
|
| 1 | Sink: group:logrus; ; false; WithField; ; ; Argument[0..1]; log-injection; manual |
|
||||||
| 2 | Sink: group:logrus; ; false; WithFields; ; ; Argument[0]; log-injection; manual |
|
| 2 | Sink: group:logrus; ; false; WithFields; ; ; Argument[0]; log-injection; manual |
|
||||||
@@ -175,14 +164,14 @@ models
|
|||||||
| 10 | Sink: log; Logger; true; Printf; ; ; Argument[0..1]; log-injection; manual |
|
| 10 | Sink: log; Logger; true; Printf; ; ; Argument[0..1]; log-injection; manual |
|
||||||
| 11 | Source: net/http; Request; true; Header; ; ; ; remote; manual |
|
| 11 | Source: net/http; Request; true; Header; ; ; ; remote; manual |
|
||||||
nodes
|
nodes
|
||||||
| klog.go:21:3:26:3 | extract:1 range statement | semmle.label | extract:1 range statement |
|
| klog.go:21:3:26:3 | range statement[1] | semmle.label | range statement[1] |
|
||||||
| klog.go:21:30:21:37 | selection of Header | semmle.label | selection of Header |
|
| klog.go:21:30:21:37 | selection of Header | semmle.label | selection of Header |
|
||||||
| klog.go:22:4:25:4 | extract:1 range statement | semmle.label | extract:1 range statement |
|
| klog.go:22:4:25:4 | range statement[1] | semmle.label | range statement[1] |
|
||||||
| klog.go:22:27:22:33 | headers | semmle.label | headers |
|
| klog.go:22:27:22:33 | headers | semmle.label | headers |
|
||||||
| klog.go:23:15:23:20 | header | semmle.label | header |
|
| klog.go:23:15:23:20 | header | semmle.label | header |
|
||||||
| klog.go:29:13:29:20 | selection of Header | semmle.label | selection of Header |
|
| klog.go:29:13:29:20 | selection of Header | semmle.label | selection of Header |
|
||||||
| klog.go:29:13:29:41 | call to Get | semmle.label | call to Get |
|
| klog.go:29:13:29:41 | call to Get | semmle.label | call to Get |
|
||||||
| main.go:17:2:17:23 | SSA def(password) | semmle.label | SSA def(password) |
|
| main.go:17:2:17:9 | SSA def(password) | semmle.label | SSA def(password) |
|
||||||
| main.go:19:12:19:19 | password | semmle.label | password |
|
| main.go:19:12:19:19 | password | semmle.label | password |
|
||||||
| main.go:20:19:20:26 | password | semmle.label | password |
|
| main.go:20:19:20:26 | password | semmle.label | password |
|
||||||
| main.go:21:13:21:20 | password | semmle.label | password |
|
| main.go:21:13:21:20 | password | semmle.label | password |
|
||||||
@@ -220,12 +209,12 @@ nodes
|
|||||||
| main.go:86:19:86:26 | password | semmle.label | password |
|
| main.go:86:19:86:26 | password | semmle.label | password |
|
||||||
| main.go:87:29:87:34 | fields | semmle.label | fields |
|
| main.go:87:29:87:34 | fields | semmle.label | fields |
|
||||||
| main.go:90:35:90:42 | password | semmle.label | password |
|
| main.go:90:35:90:42 | password | semmle.label | password |
|
||||||
| overrides.go:8:2:8:40 | SSA def(password) | semmle.label | SSA def(password) |
|
| overrides.go:8:2:8:9 | SSA def(password) | semmle.label | SSA def(password) |
|
||||||
| overrides.go:9:9:9:16 | password | semmle.label | password |
|
| overrides.go:9:9:9:16 | password | semmle.label | password |
|
||||||
| overrides.go:13:14:13:23 | call to String | semmle.label | call to String |
|
| overrides.go:13:14:13:23 | call to String | semmle.label | call to String |
|
||||||
| passwords.go:8:22:10:1 | SSA def(x) | semmle.label | SSA def(x) |
|
| passwords.go:8:12:8:12 | SSA def(x) | semmle.label | SSA def(x) |
|
||||||
| passwords.go:9:14:9:14 | x | semmle.label | x |
|
| passwords.go:9:14:9:14 | x | semmle.label | x |
|
||||||
| passwords.go:21:2:21:23 | SSA def(password) | semmle.label | SSA def(password) |
|
| passwords.go:21:2:21:9 | SSA def(password) | semmle.label | SSA def(password) |
|
||||||
| passwords.go:25:14:25:21 | password | semmle.label | password |
|
| passwords.go:25:14:25:21 | password | semmle.label | password |
|
||||||
| passwords.go:26:14:26:23 | selection of password | semmle.label | selection of password |
|
| passwords.go:26:14:26:23 | selection of password | semmle.label | selection of password |
|
||||||
| passwords.go:27:14:27:26 | call to getPassword | semmle.label | call to getPassword |
|
| passwords.go:27:14:27:26 | call to getPassword | semmle.label | call to getPassword |
|
||||||
@@ -235,19 +224,15 @@ nodes
|
|||||||
| passwords.go:36:14:36:35 | ...+... | semmle.label | ...+... |
|
| passwords.go:36:14:36:35 | ...+... | semmle.label | ...+... |
|
||||||
| passwords.go:36:28:36:35 | password | semmle.label | password |
|
| passwords.go:36:28:36:35 | password | semmle.label | password |
|
||||||
| passwords.go:38:10:40:2 | struct literal | semmle.label | struct literal |
|
| passwords.go:38:10:40:2 | struct literal | semmle.label | struct literal |
|
||||||
| passwords.go:39:3:39:13 | key-value pair | semmle.label | key-value pair |
|
|
||||||
| passwords.go:39:13:39:13 | x | semmle.label | x |
|
| passwords.go:39:13:39:13 | x | semmle.label | x |
|
||||||
| passwords.go:41:14:41:17 | obj1 | semmle.label | obj1 |
|
| passwords.go:41:14:41:17 | obj1 | semmle.label | obj1 |
|
||||||
| passwords.go:43:10:45:2 | struct literal | semmle.label | struct literal |
|
| passwords.go:43:10:45:2 | struct literal | semmle.label | struct literal |
|
||||||
| passwords.go:44:6:44:13 | password | semmle.label | password |
|
| passwords.go:44:6:44:13 | password | semmle.label | password |
|
||||||
| passwords.go:46:14:46:17 | obj2 | semmle.label | obj2 |
|
| passwords.go:46:14:46:17 | obj2 | semmle.label | obj2 |
|
||||||
| passwords.go:50:11:50:18 | password | semmle.label | password |
|
| passwords.go:50:11:50:18 | password | semmle.label | password |
|
||||||
| passwords.go:52:2:52:44 | SSA def(fixed_password) | semmle.label | SSA def(fixed_password) |
|
| passwords.go:52:2:52:15 | SSA def(fixed_password) | semmle.label | SSA def(fixed_password) |
|
||||||
| passwords.go:53:14:53:27 | fixed_password | semmle.label | fixed_password |
|
| passwords.go:53:14:53:27 | fixed_password | semmle.label | fixed_password |
|
||||||
| passwords.go:65:14:65:44 | struct literal | semmle.label | struct literal |
|
|
||||||
| passwords.go:65:25:65:43 | key-value pair | semmle.label | key-value pair |
|
|
||||||
| passwords.go:88:19:90:2 | struct literal | semmle.label | struct literal |
|
| passwords.go:88:19:90:2 | struct literal | semmle.label | struct literal |
|
||||||
| passwords.go:89:3:89:36 | key-value pair | semmle.label | key-value pair |
|
|
||||||
| passwords.go:89:16:89:36 | call to make | semmle.label | call to make |
|
| passwords.go:89:16:89:36 | call to make | semmle.label | call to make |
|
||||||
| passwords.go:91:14:91:26 | utilityObject | semmle.label | utilityObject |
|
| passwords.go:91:14:91:26 | utilityObject | semmle.label | utilityObject |
|
||||||
| passwords.go:94:23:94:28 | secret | semmle.label | secret |
|
| passwords.go:94:23:94:28 | secret | semmle.label | secret |
|
||||||
@@ -257,14 +242,13 @@ nodes
|
|||||||
| passwords.go:110:34:110:41 | password | semmle.label | password |
|
| passwords.go:110:34:110:41 | password | semmle.label | password |
|
||||||
| passwords.go:115:15:115:40 | ...+... | semmle.label | ...+... |
|
| passwords.go:115:15:115:40 | ...+... | semmle.label | ...+... |
|
||||||
| passwords.go:115:33:115:40 | password | semmle.label | password |
|
| passwords.go:115:33:115:40 | password | semmle.label | password |
|
||||||
| passwords.go:118:6:118:50 | SSA def(password1) | semmle.label | SSA def(password1) |
|
| passwords.go:118:6:118:14 | SSA def(password1) | semmle.label | SSA def(password1) |
|
||||||
| passwords.go:119:14:119:45 | ...+... | semmle.label | ...+... |
|
| passwords.go:119:14:119:45 | ...+... | semmle.label | ...+... |
|
||||||
| passwords.go:119:28:119:36 | password1 | semmle.label | password1 |
|
| passwords.go:119:28:119:36 | password1 | semmle.label | password1 |
|
||||||
| passwords.go:119:28:119:45 | call to String | semmle.label | call to String |
|
| passwords.go:119:28:119:45 | call to String | semmle.label | call to String |
|
||||||
| passwords.go:122:12:127:2 | struct literal | semmle.label | struct literal |
|
| passwords.go:122:12:127:2 | struct literal | semmle.label | struct literal |
|
||||||
| passwords.go:122:12:127:2 | struct literal [x] | semmle.label | struct literal [x] |
|
| passwords.go:122:12:127:2 | struct literal [x] | semmle.label | struct literal [x] |
|
||||||
| passwords.go:122:12:127:2 | struct literal [y] | semmle.label | struct literal [y] |
|
| passwords.go:122:12:127:2 | struct literal [y] | semmle.label | struct literal [y] |
|
||||||
| passwords.go:123:3:123:14 | key-value pair | semmle.label | key-value pair |
|
|
||||||
| passwords.go:123:13:123:14 | x3 | semmle.label | x3 |
|
| passwords.go:123:13:123:14 | x3 | semmle.label | x3 |
|
||||||
| passwords.go:125:13:125:20 | password | semmle.label | password |
|
| passwords.go:125:13:125:20 | password | semmle.label | password |
|
||||||
| passwords.go:126:13:126:25 | call to getPassword | semmle.label | call to getPassword |
|
| passwords.go:126:13:126:25 | call to getPassword | semmle.label | call to getPassword |
|
||||||
@@ -273,23 +257,15 @@ nodes
|
|||||||
| passwords.go:130:14:130:21 | selection of x | semmle.label | selection of x |
|
| passwords.go:130:14:130:21 | selection of x | semmle.label | selection of x |
|
||||||
| passwords.go:131:14:131:19 | config [y] | semmle.label | config [y] |
|
| passwords.go:131:14:131:19 | config [y] | semmle.label | config [y] |
|
||||||
| passwords.go:131:14:131:21 | selection of y | semmle.label | selection of y |
|
| passwords.go:131:14:131:21 | selection of y | semmle.label | selection of y |
|
||||||
| protobuf.go:9:2:9:23 | SSA def(password) | semmle.label | SSA def(password) |
|
| protobuf.go:9:2:9:9 | SSA def(password) | semmle.label | SSA def(password) |
|
||||||
| protobuf.go:12:2:12:6 | implicit-deref query [postupdate] [Description] | semmle.label | implicit-deref query [postupdate] [Description] |
|
| protobuf.go:12:2:12:6 | implicit dereference [postupdate] [Description] | semmle.label | implicit dereference [postupdate] [Description] |
|
||||||
| protobuf.go:12:2:12:6 | query [postupdate] [pointer, Description] | semmle.label | query [postupdate] [pointer, Description] |
|
| protobuf.go:12:2:12:6 | query [postupdate] [pointer, Description] | semmle.label | query [postupdate] [pointer, Description] |
|
||||||
| protobuf.go:12:22:12:29 | password | semmle.label | password |
|
| protobuf.go:12:22:12:29 | password | semmle.label | password |
|
||||||
| protobuf.go:14:14:14:18 | query [pointer, Description] | semmle.label | query [pointer, Description] |
|
| protobuf.go:14:14:14:18 | query [pointer, Description] | semmle.label | query [pointer, Description] |
|
||||||
| protobuf.go:14:14:14:35 | call to GetDescription | semmle.label | call to GetDescription |
|
| protobuf.go:14:14:14:35 | call to GetDescription | semmle.label | call to GetDescription |
|
||||||
| protos/query/query.pb.go:117:41:122:1 | SSA def(x) [pointer, Description] | semmle.label | SSA def(x) [pointer, Description] |
|
| protos/query/query.pb.go:117:7:117:7 | SSA def(x) [pointer, Description] | semmle.label | SSA def(x) [pointer, Description] |
|
||||||
| protos/query/query.pb.go:119:10:119:10 | implicit-deref x [Description] | semmle.label | implicit-deref x [Description] |
|
| protos/query/query.pb.go:119:10:119:10 | implicit dereference [Description] | semmle.label | implicit dereference [Description] |
|
||||||
| protos/query/query.pb.go:119:10:119:10 | x [pointer, Description] | semmle.label | x [pointer, Description] |
|
| protos/query/query.pb.go:119:10:119:10 | x [pointer, Description] | semmle.label | x [pointer, Description] |
|
||||||
| protos/query/query.pb.go:119:10:119:22 | selection of Description | semmle.label | selection of Description |
|
| protos/query/query.pb.go:119:10:119:22 | selection of Description | semmle.label | selection of Description |
|
||||||
| server1.go:16:15:18:3 | struct literal | semmle.label | struct literal |
|
|
||||||
| server1.go:17:4:17:63 | key-value pair | semmle.label | key-value pair |
|
|
||||||
| server1.go:19:15:19:19 | user3 | semmle.label | user3 |
|
|
||||||
subpaths
|
subpaths
|
||||||
| protobuf.go:14:14:14:18 | query [pointer, Description] | protos/query/query.pb.go:117:41:122:1 | SSA def(x) [pointer, Description] | protos/query/query.pb.go:119:10:119:22 | selection of Description | protobuf.go:14:14:14:35 | call to GetDescription |
|
| protobuf.go:14:14:14:18 | query [pointer, Description] | protos/query/query.pb.go:117:7:117:7 | SSA def(x) [pointer, Description] | protos/query/query.pb.go:119:10:119:22 | selection of Description | protobuf.go:14:14:14:35 | call to GetDescription |
|
||||||
testFailures
|
|
||||||
| passwords.go:65:14:65:44 | struct literal | Unexpected result: Alert |
|
|
||||||
| passwords.go:65:25:65:43 | key-value pair | Unexpected result: Alert |
|
|
||||||
| server1.go:17:4:17:63 | key-value pair | Unexpected result: Source |
|
|
||||||
| server1.go:19:15:19:19 | user3 | Unexpected result: Alert |
|
|
||||||
|
|||||||
@@ -8,18 +8,18 @@ edges
|
|||||||
| InsecureHostKeyCallbackExample.go:31:14:34:4 | type conversion | InsecureHostKeyCallbackExample.go:39:20:39:27 | callback | provenance | |
|
| InsecureHostKeyCallbackExample.go:31:14:34:4 | type conversion | InsecureHostKeyCallbackExample.go:39:20:39:27 | callback | provenance | |
|
||||||
| InsecureHostKeyCallbackExample.go:32:3:34:3 | function literal | InsecureHostKeyCallbackExample.go:31:14:34:4 | type conversion | provenance | |
|
| InsecureHostKeyCallbackExample.go:32:3:34:3 | function literal | InsecureHostKeyCallbackExample.go:31:14:34:4 | type conversion | provenance | |
|
||||||
| InsecureHostKeyCallbackExample.go:45:3:47:3 | function literal | InsecureHostKeyCallbackExample.go:52:20:52:48 | type conversion | provenance | |
|
| InsecureHostKeyCallbackExample.go:45:3:47:3 | function literal | InsecureHostKeyCallbackExample.go:52:20:52:48 | type conversion | provenance | |
|
||||||
| InsecureHostKeyCallbackExample.go:58:69:64:1 | SSA def(callback) | InsecureHostKeyCallbackExample.go:62:20:62:27 | callback | provenance | |
|
| InsecureHostKeyCallbackExample.go:58:39:58:46 | SSA def(callback) | InsecureHostKeyCallbackExample.go:62:20:62:27 | callback | provenance | |
|
||||||
| InsecureHostKeyCallbackExample.go:68:78:80:1 | SSA def(callback) | InsecureHostKeyCallbackExample.go:78:28:78:35 | callback | provenance | |
|
| InsecureHostKeyCallbackExample.go:68:48:68:55 | SSA def(callback) | InsecureHostKeyCallbackExample.go:78:28:78:35 | callback | provenance | |
|
||||||
| InsecureHostKeyCallbackExample.go:94:3:94:43 | extract:0 ... := ... | InsecureHostKeyCallbackExample.go:95:28:95:35 | callback | provenance | |
|
| InsecureHostKeyCallbackExample.go:94:3:94:43 | ... := ...[0] | InsecureHostKeyCallbackExample.go:95:28:95:35 | callback | provenance | |
|
||||||
| InsecureHostKeyCallbackExample.go:102:22:105:4 | type conversion | InsecureHostKeyCallbackExample.go:107:35:107:50 | insecureCallback | provenance | |
|
| InsecureHostKeyCallbackExample.go:102:22:105:4 | type conversion | InsecureHostKeyCallbackExample.go:107:35:107:50 | insecureCallback | provenance | |
|
||||||
| InsecureHostKeyCallbackExample.go:103:3:105:3 | function literal | InsecureHostKeyCallbackExample.go:102:22:105:4 | type conversion | provenance | |
|
| InsecureHostKeyCallbackExample.go:103:3:105:3 | function literal | InsecureHostKeyCallbackExample.go:102:22:105:4 | type conversion | provenance | |
|
||||||
| InsecureHostKeyCallbackExample.go:107:35:107:50 | insecureCallback | InsecureHostKeyCallbackExample.go:58:69:64:1 | SSA def(callback) | provenance | |
|
| InsecureHostKeyCallbackExample.go:107:35:107:50 | insecureCallback | InsecureHostKeyCallbackExample.go:58:39:58:46 | SSA def(callback) | provenance | |
|
||||||
| InsecureHostKeyCallbackExample.go:109:31:115:4 | type conversion | InsecureHostKeyCallbackExample.go:117:35:117:59 | potentiallySecureCallback | provenance | |
|
| InsecureHostKeyCallbackExample.go:109:31:115:4 | type conversion | InsecureHostKeyCallbackExample.go:117:35:117:59 | potentiallySecureCallback | provenance | |
|
||||||
| InsecureHostKeyCallbackExample.go:109:31:115:4 | type conversion | InsecureHostKeyCallbackExample.go:120:44:120:68 | potentiallySecureCallback | provenance | |
|
| InsecureHostKeyCallbackExample.go:109:31:115:4 | type conversion | InsecureHostKeyCallbackExample.go:120:44:120:68 | potentiallySecureCallback | provenance | |
|
||||||
| InsecureHostKeyCallbackExample.go:110:3:115:3 | function literal | InsecureHostKeyCallbackExample.go:109:31:115:4 | type conversion | provenance | |
|
| InsecureHostKeyCallbackExample.go:110:3:115:3 | function literal | InsecureHostKeyCallbackExample.go:109:31:115:4 | type conversion | provenance | |
|
||||||
| InsecureHostKeyCallbackExample.go:117:35:117:59 | potentiallySecureCallback | InsecureHostKeyCallbackExample.go:58:69:64:1 | SSA def(callback) | provenance | |
|
| InsecureHostKeyCallbackExample.go:117:35:117:59 | potentiallySecureCallback | InsecureHostKeyCallbackExample.go:58:39:58:46 | SSA def(callback) | provenance | |
|
||||||
| InsecureHostKeyCallbackExample.go:118:35:118:61 | call to InsecureIgnoreHostKey | InsecureHostKeyCallbackExample.go:58:69:64:1 | SSA def(callback) | provenance | |
|
| InsecureHostKeyCallbackExample.go:118:35:118:61 | call to InsecureIgnoreHostKey | InsecureHostKeyCallbackExample.go:58:39:58:46 | SSA def(callback) | provenance | |
|
||||||
| InsecureHostKeyCallbackExample.go:120:44:120:68 | potentiallySecureCallback | InsecureHostKeyCallbackExample.go:68:78:80:1 | SSA def(callback) | provenance | |
|
| InsecureHostKeyCallbackExample.go:120:44:120:68 | potentiallySecureCallback | InsecureHostKeyCallbackExample.go:68:48:68:55 | SSA def(callback) | provenance | |
|
||||||
nodes
|
nodes
|
||||||
| InsecureHostKeyCallbackExample.go:15:20:18:5 | type conversion | semmle.label | type conversion |
|
| InsecureHostKeyCallbackExample.go:15:20:18:5 | type conversion | semmle.label | type conversion |
|
||||||
| InsecureHostKeyCallbackExample.go:16:4:18:4 | function literal | semmle.label | function literal |
|
| InsecureHostKeyCallbackExample.go:16:4:18:4 | function literal | semmle.label | function literal |
|
||||||
@@ -29,13 +29,13 @@ nodes
|
|||||||
| InsecureHostKeyCallbackExample.go:39:20:39:27 | callback | semmle.label | callback |
|
| InsecureHostKeyCallbackExample.go:39:20:39:27 | callback | semmle.label | callback |
|
||||||
| InsecureHostKeyCallbackExample.go:45:3:47:3 | function literal | semmle.label | function literal |
|
| InsecureHostKeyCallbackExample.go:45:3:47:3 | function literal | semmle.label | function literal |
|
||||||
| InsecureHostKeyCallbackExample.go:52:20:52:48 | type conversion | semmle.label | type conversion |
|
| InsecureHostKeyCallbackExample.go:52:20:52:48 | type conversion | semmle.label | type conversion |
|
||||||
| InsecureHostKeyCallbackExample.go:58:69:64:1 | SSA def(callback) | semmle.label | SSA def(callback) |
|
| InsecureHostKeyCallbackExample.go:58:39:58:46 | SSA def(callback) | semmle.label | SSA def(callback) |
|
||||||
| InsecureHostKeyCallbackExample.go:62:20:62:27 | callback | semmle.label | callback |
|
| InsecureHostKeyCallbackExample.go:62:20:62:27 | callback | semmle.label | callback |
|
||||||
| InsecureHostKeyCallbackExample.go:68:78:80:1 | SSA def(callback) | semmle.label | SSA def(callback) |
|
| InsecureHostKeyCallbackExample.go:68:48:68:55 | SSA def(callback) | semmle.label | SSA def(callback) |
|
||||||
| InsecureHostKeyCallbackExample.go:76:28:76:54 | call to InsecureIgnoreHostKey | semmle.label | call to InsecureIgnoreHostKey |
|
| InsecureHostKeyCallbackExample.go:76:28:76:54 | call to InsecureIgnoreHostKey | semmle.label | call to InsecureIgnoreHostKey |
|
||||||
| InsecureHostKeyCallbackExample.go:78:28:78:35 | callback | semmle.label | callback |
|
| InsecureHostKeyCallbackExample.go:78:28:78:35 | callback | semmle.label | callback |
|
||||||
| InsecureHostKeyCallbackExample.go:92:28:92:54 | call to InsecureIgnoreHostKey | semmle.label | call to InsecureIgnoreHostKey |
|
| InsecureHostKeyCallbackExample.go:92:28:92:54 | call to InsecureIgnoreHostKey | semmle.label | call to InsecureIgnoreHostKey |
|
||||||
| InsecureHostKeyCallbackExample.go:94:3:94:43 | extract:0 ... := ... | semmle.label | extract:0 ... := ... |
|
| InsecureHostKeyCallbackExample.go:94:3:94:43 | ... := ...[0] | semmle.label | ... := ...[0] |
|
||||||
| InsecureHostKeyCallbackExample.go:95:28:95:35 | callback | semmle.label | callback |
|
| InsecureHostKeyCallbackExample.go:95:28:95:35 | callback | semmle.label | callback |
|
||||||
| InsecureHostKeyCallbackExample.go:102:22:105:4 | type conversion | semmle.label | type conversion |
|
| InsecureHostKeyCallbackExample.go:102:22:105:4 | type conversion | semmle.label | type conversion |
|
||||||
| InsecureHostKeyCallbackExample.go:103:3:105:3 | function literal | semmle.label | function literal |
|
| InsecureHostKeyCallbackExample.go:103:3:105:3 | function literal | semmle.label | function literal |
|
||||||
|
|||||||
@@ -1,14 +1,7 @@
|
|||||||
#select
|
|
||||||
| InsufficientKeySize.go:9:31:9:34 | 1024 | InsufficientKeySize.go:9:31:9:34 | 1024 | InsufficientKeySize.go:9:31:9:34 | 1024 | The size of this RSA key should be at least 2048 bits. |
|
|
||||||
| InsufficientKeySize.go:14:31:14:34 | size | InsufficientKeySize.go:13:10:13:13 | 1024 | InsufficientKeySize.go:14:31:14:34 | size | The size of this RSA key should be at least 2048 bits. |
|
|
||||||
| InsufficientKeySize.go:26:31:26:34 | size | InsufficientKeySize.go:18:7:18:10 | 1024 | InsufficientKeySize.go:26:31:26:34 | size | The size of this RSA key should be at least 2048 bits. |
|
|
||||||
| InsufficientKeySize.go:32:32:32:38 | keyBits | InsufficientKeySize.go:30:13:30:16 | 1024 | InsufficientKeySize.go:32:32:32:38 | keyBits | The size of this RSA key should be at least 2048 bits. |
|
|
||||||
| InsufficientKeySize.go:47:32:47:38 | keyBits | InsufficientKeySize.go:44:13:44:16 | 1024 | InsufficientKeySize.go:47:32:47:38 | keyBits | The size of this RSA key should be at least 2048 bits. |
|
|
||||||
| InsufficientKeySize.go:67:31:67:37 | keyBits | InsufficientKeySize.go:61:21:61:24 | 1024 | InsufficientKeySize.go:67:31:67:37 | keyBits | The size of this RSA key should be at least 2048 bits. |
|
|
||||||
edges
|
edges
|
||||||
| InsufficientKeySize.go:13:10:13:13 | 1024 | InsufficientKeySize.go:14:31:14:34 | size | provenance | |
|
| InsufficientKeySize.go:13:10:13:13 | 1024 | InsufficientKeySize.go:14:31:14:34 | size | provenance | |
|
||||||
| InsufficientKeySize.go:18:7:18:10 | 1024 | InsufficientKeySize.go:25:21:27:1 | SSA def(size) | provenance | |
|
| InsufficientKeySize.go:18:7:18:10 | 1024 | InsufficientKeySize.go:25:11:25:14 | SSA def(size) | provenance | |
|
||||||
| InsufficientKeySize.go:25:21:27:1 | SSA def(size) | InsufficientKeySize.go:26:31:26:34 | size | provenance | |
|
| InsufficientKeySize.go:25:11:25:14 | SSA def(size) | InsufficientKeySize.go:26:31:26:34 | size | provenance | |
|
||||||
| InsufficientKeySize.go:30:13:30:16 | 1024 | InsufficientKeySize.go:32:32:32:38 | keyBits | provenance | |
|
| InsufficientKeySize.go:30:13:30:16 | 1024 | InsufficientKeySize.go:32:32:32:38 | keyBits | provenance | |
|
||||||
| InsufficientKeySize.go:44:13:44:16 | 1024 | InsufficientKeySize.go:47:32:47:38 | keyBits | provenance | |
|
| InsufficientKeySize.go:44:13:44:16 | 1024 | InsufficientKeySize.go:47:32:47:38 | keyBits | provenance | |
|
||||||
| InsufficientKeySize.go:61:21:61:24 | 1024 | InsufficientKeySize.go:67:31:67:37 | keyBits | provenance | |
|
| InsufficientKeySize.go:61:21:61:24 | 1024 | InsufficientKeySize.go:67:31:67:37 | keyBits | provenance | |
|
||||||
@@ -17,7 +10,7 @@ nodes
|
|||||||
| InsufficientKeySize.go:13:10:13:13 | 1024 | semmle.label | 1024 |
|
| InsufficientKeySize.go:13:10:13:13 | 1024 | semmle.label | 1024 |
|
||||||
| InsufficientKeySize.go:14:31:14:34 | size | semmle.label | size |
|
| InsufficientKeySize.go:14:31:14:34 | size | semmle.label | size |
|
||||||
| InsufficientKeySize.go:18:7:18:10 | 1024 | semmle.label | 1024 |
|
| InsufficientKeySize.go:18:7:18:10 | 1024 | semmle.label | 1024 |
|
||||||
| InsufficientKeySize.go:25:21:27:1 | SSA def(size) | semmle.label | SSA def(size) |
|
| InsufficientKeySize.go:25:11:25:14 | SSA def(size) | semmle.label | SSA def(size) |
|
||||||
| InsufficientKeySize.go:26:31:26:34 | size | semmle.label | size |
|
| InsufficientKeySize.go:26:31:26:34 | size | semmle.label | size |
|
||||||
| InsufficientKeySize.go:30:13:30:16 | 1024 | semmle.label | 1024 |
|
| InsufficientKeySize.go:30:13:30:16 | 1024 | semmle.label | 1024 |
|
||||||
| InsufficientKeySize.go:32:32:32:38 | keyBits | semmle.label | keyBits |
|
| InsufficientKeySize.go:32:32:32:38 | keyBits | semmle.label | keyBits |
|
||||||
@@ -26,3 +19,10 @@ nodes
|
|||||||
| InsufficientKeySize.go:61:21:61:24 | 1024 | semmle.label | 1024 |
|
| InsufficientKeySize.go:61:21:61:24 | 1024 | semmle.label | 1024 |
|
||||||
| InsufficientKeySize.go:67:31:67:37 | keyBits | semmle.label | keyBits |
|
| InsufficientKeySize.go:67:31:67:37 | keyBits | semmle.label | keyBits |
|
||||||
subpaths
|
subpaths
|
||||||
|
#select
|
||||||
|
| InsufficientKeySize.go:9:31:9:34 | 1024 | InsufficientKeySize.go:9:31:9:34 | 1024 | InsufficientKeySize.go:9:31:9:34 | 1024 | The size of this RSA key should be at least 2048 bits. |
|
||||||
|
| InsufficientKeySize.go:14:31:14:34 | size | InsufficientKeySize.go:13:10:13:13 | 1024 | InsufficientKeySize.go:14:31:14:34 | size | The size of this RSA key should be at least 2048 bits. |
|
||||||
|
| InsufficientKeySize.go:26:31:26:34 | size | InsufficientKeySize.go:18:7:18:10 | 1024 | InsufficientKeySize.go:26:31:26:34 | size | The size of this RSA key should be at least 2048 bits. |
|
||||||
|
| InsufficientKeySize.go:32:32:32:38 | keyBits | InsufficientKeySize.go:30:13:30:16 | 1024 | InsufficientKeySize.go:32:32:32:38 | keyBits | The size of this RSA key should be at least 2048 bits. |
|
||||||
|
| InsufficientKeySize.go:47:32:47:38 | keyBits | InsufficientKeySize.go:44:13:44:16 | 1024 | InsufficientKeySize.go:47:32:47:38 | keyBits | The size of this RSA key should be at least 2048 bits. |
|
||||||
|
| InsufficientKeySize.go:67:31:67:37 | keyBits | InsufficientKeySize.go:61:21:61:24 | 1024 | InsufficientKeySize.go:67:31:67:37 | keyBits | The size of this RSA key should be at least 2048 bits. |
|
||||||
|
|||||||
@@ -1,29 +1,29 @@
|
|||||||
| encryption.go:30:2:30:36 | call to Encrypt | $@ is broken or weak, and should not be used. | encryption.go:28:2:28:31 | extract:0 ... := ... | The cryptographic algorithm DES |
|
| encryption.go:30:2:30:36 | call to Encrypt | $@ is broken or weak, and should not be used. | encryption.go:28:2:28:31 | ... := ...[0] | The cryptographic algorithm DES |
|
||||||
| encryption.go:34:2:34:42 | call to Seal | $@ is broken or weak, and should not be used. | encryption.go:28:2:28:31 | extract:0 ... := ... | The cryptographic algorithm DES |
|
| encryption.go:34:2:34:42 | call to Seal | $@ is broken or weak, and should not be used. | encryption.go:28:2:28:31 | ... := ...[0] | The cryptographic algorithm DES |
|
||||||
| encryption.go:38:2:38:42 | call to Seal | $@ is broken or weak, and should not be used. | encryption.go:28:2:28:31 | extract:0 ... := ... | The cryptographic algorithm DES |
|
| encryption.go:38:2:38:42 | call to Seal | $@ is broken or weak, and should not be used. | encryption.go:28:2:28:31 | ... := ...[0] | The cryptographic algorithm DES |
|
||||||
| encryption.go:42:2:42:42 | call to Seal | $@ is broken or weak, and should not be used. | encryption.go:28:2:28:31 | extract:0 ... := ... | The cryptographic algorithm DES |
|
| encryption.go:42:2:42:42 | call to Seal | $@ is broken or weak, and should not be used. | encryption.go:28:2:28:31 | ... := ...[0] | The cryptographic algorithm DES |
|
||||||
| encryption.go:46:2:46:42 | call to Seal | $@ is broken or weak, and should not be used. | encryption.go:28:2:28:31 | extract:0 ... := ... | The cryptographic algorithm DES |
|
| encryption.go:46:2:46:42 | call to Seal | $@ is broken or weak, and should not be used. | encryption.go:28:2:28:31 | ... := ...[0] | The cryptographic algorithm DES |
|
||||||
| encryption.go:50:2:50:47 | call to CryptBlocks | $@ is broken or weak, and should not be used. | encryption.go:28:2:28:31 | extract:0 ... := ... | The cryptographic algorithm DES |
|
| encryption.go:50:2:50:47 | call to CryptBlocks | $@ is broken or weak, and should not be used. | encryption.go:28:2:28:31 | ... := ...[0] | The cryptographic algorithm DES |
|
||||||
| encryption.go:54:2:54:45 | call to XORKeyStream | $@ is broken or weak, and should not be used. | encryption.go:28:2:28:31 | extract:0 ... := ... | The cryptographic algorithm DES |
|
| encryption.go:54:2:54:45 | call to XORKeyStream | $@ is broken or weak, and should not be used. | encryption.go:28:2:28:31 | ... := ...[0] | The cryptographic algorithm DES |
|
||||||
| encryption.go:56:22:56:91 | struct literal | $@ is broken or weak, and should not be used. | encryption.go:28:2:28:31 | extract:0 ... := ... | The cryptographic algorithm DES |
|
| encryption.go:56:22:56:91 | struct literal | $@ is broken or weak, and should not be used. | encryption.go:28:2:28:31 | ... := ...[0] | The cryptographic algorithm DES |
|
||||||
| encryption.go:59:21:59:68 | &... [postupdate] | $@ is broken or weak, and should not be used. | encryption.go:28:2:28:31 | extract:0 ... := ... | The cryptographic algorithm DES |
|
| encryption.go:59:21:59:68 | &... [postupdate] | $@ is broken or weak, and should not be used. | encryption.go:28:2:28:31 | ... := ...[0] | The cryptographic algorithm DES |
|
||||||
| encryption.go:59:22:59:68 | struct literal | $@ is broken or weak, and should not be used. | encryption.go:28:2:28:31 | extract:0 ... := ... | The cryptographic algorithm DES |
|
| encryption.go:59:22:59:68 | struct literal | $@ is broken or weak, and should not be used. | encryption.go:28:2:28:31 | ... := ...[0] | The cryptographic algorithm DES |
|
||||||
| encryption.go:59:22:59:68 | struct literal [postupdate] | $@ is broken or weak, and should not be used. | encryption.go:28:2:28:31 | extract:0 ... := ... | The cryptographic algorithm DES |
|
| encryption.go:59:22:59:68 | struct literal [postupdate] | $@ is broken or weak, and should not be used. | encryption.go:28:2:28:31 | ... := ...[0] | The cryptographic algorithm DES |
|
||||||
| encryption.go:60:10:60:24 | ctrStreamWriter [postupdate] | $@ is broken or weak, and should not be used. | encryption.go:28:2:28:31 | extract:0 ... := ... | The cryptographic algorithm DES |
|
| encryption.go:60:10:60:24 | ctrStreamWriter [postupdate] | $@ is broken or weak, and should not be used. | encryption.go:28:2:28:31 | ... := ...[0] | The cryptographic algorithm DES |
|
||||||
| encryption.go:65:2:65:45 | call to XORKeyStream | $@ is broken or weak, and should not be used. | encryption.go:28:2:28:31 | extract:0 ... := ... | The cryptographic algorithm DES |
|
| encryption.go:65:2:65:45 | call to XORKeyStream | $@ is broken or weak, and should not be used. | encryption.go:28:2:28:31 | ... := ...[0] | The cryptographic algorithm DES |
|
||||||
| encryption.go:69:2:69:45 | call to XORKeyStream | $@ is broken or weak, and should not be used. | encryption.go:28:2:28:31 | extract:0 ... := ... | The cryptographic algorithm DES |
|
| encryption.go:69:2:69:45 | call to XORKeyStream | $@ is broken or weak, and should not be used. | encryption.go:28:2:28:31 | ... := ...[0] | The cryptographic algorithm DES |
|
||||||
| encryption.go:76:2:76:32 | call to Encrypt | $@ is broken or weak, and should not be used. | encryption.go:74:2:74:40 | extract:0 ... := ... | The cryptographic algorithm TRIPLEDES |
|
| encryption.go:76:2:76:32 | call to Encrypt | $@ is broken or weak, and should not be used. | encryption.go:74:2:74:40 | ... := ...[0] | The cryptographic algorithm TRIPLEDES |
|
||||||
| encryption.go:80:2:80:38 | call to Seal | $@ is broken or weak, and should not be used. | encryption.go:74:2:74:40 | extract:0 ... := ... | The cryptographic algorithm TRIPLEDES |
|
| encryption.go:80:2:80:38 | call to Seal | $@ is broken or weak, and should not be used. | encryption.go:74:2:74:40 | ... := ...[0] | The cryptographic algorithm TRIPLEDES |
|
||||||
| encryption.go:84:2:84:38 | call to Seal | $@ is broken or weak, and should not be used. | encryption.go:74:2:74:40 | extract:0 ... := ... | The cryptographic algorithm TRIPLEDES |
|
| encryption.go:84:2:84:38 | call to Seal | $@ is broken or weak, and should not be used. | encryption.go:74:2:74:40 | ... := ...[0] | The cryptographic algorithm TRIPLEDES |
|
||||||
| encryption.go:88:2:88:42 | call to Seal | $@ is broken or weak, and should not be used. | encryption.go:74:2:74:40 | extract:0 ... := ... | The cryptographic algorithm TRIPLEDES |
|
| encryption.go:88:2:88:42 | call to Seal | $@ is broken or weak, and should not be used. | encryption.go:74:2:74:40 | ... := ...[0] | The cryptographic algorithm TRIPLEDES |
|
||||||
| encryption.go:92:2:92:42 | call to Seal | $@ is broken or weak, and should not be used. | encryption.go:74:2:74:40 | extract:0 ... := ... | The cryptographic algorithm TRIPLEDES |
|
| encryption.go:92:2:92:42 | call to Seal | $@ is broken or weak, and should not be used. | encryption.go:74:2:74:40 | ... := ...[0] | The cryptographic algorithm TRIPLEDES |
|
||||||
| encryption.go:96:2:96:43 | call to CryptBlocks | $@ is broken or weak, and should not be used. | encryption.go:74:2:74:40 | extract:0 ... := ... | The cryptographic algorithm TRIPLEDES |
|
| encryption.go:96:2:96:43 | call to CryptBlocks | $@ is broken or weak, and should not be used. | encryption.go:74:2:74:40 | ... := ...[0] | The cryptographic algorithm TRIPLEDES |
|
||||||
| encryption.go:100:2:100:41 | call to XORKeyStream | $@ is broken or weak, and should not be used. | encryption.go:74:2:74:40 | extract:0 ... := ... | The cryptographic algorithm TRIPLEDES |
|
| encryption.go:100:2:100:41 | call to XORKeyStream | $@ is broken or weak, and should not be used. | encryption.go:74:2:74:40 | ... := ...[0] | The cryptographic algorithm TRIPLEDES |
|
||||||
| encryption.go:102:22:102:87 | struct literal | $@ is broken or weak, and should not be used. | encryption.go:74:2:74:40 | extract:0 ... := ... | The cryptographic algorithm TRIPLEDES |
|
| encryption.go:102:22:102:87 | struct literal | $@ is broken or weak, and should not be used. | encryption.go:74:2:74:40 | ... := ...[0] | The cryptographic algorithm TRIPLEDES |
|
||||||
| encryption.go:105:21:105:68 | &... [postupdate] | $@ is broken or weak, and should not be used. | encryption.go:74:2:74:40 | extract:0 ... := ... | The cryptographic algorithm TRIPLEDES |
|
| encryption.go:105:21:105:68 | &... [postupdate] | $@ is broken or weak, and should not be used. | encryption.go:74:2:74:40 | ... := ...[0] | The cryptographic algorithm TRIPLEDES |
|
||||||
| encryption.go:105:22:105:68 | struct literal | $@ is broken or weak, and should not be used. | encryption.go:74:2:74:40 | extract:0 ... := ... | The cryptographic algorithm TRIPLEDES |
|
| encryption.go:105:22:105:68 | struct literal | $@ is broken or weak, and should not be used. | encryption.go:74:2:74:40 | ... := ...[0] | The cryptographic algorithm TRIPLEDES |
|
||||||
| encryption.go:105:22:105:68 | struct literal [postupdate] | $@ is broken or weak, and should not be used. | encryption.go:74:2:74:40 | extract:0 ... := ... | The cryptographic algorithm TRIPLEDES |
|
| encryption.go:105:22:105:68 | struct literal [postupdate] | $@ is broken or weak, and should not be used. | encryption.go:74:2:74:40 | ... := ...[0] | The cryptographic algorithm TRIPLEDES |
|
||||||
| encryption.go:106:10:106:24 | ctrStreamWriter [postupdate] | $@ is broken or weak, and should not be used. | encryption.go:74:2:74:40 | extract:0 ... := ... | The cryptographic algorithm TRIPLEDES |
|
| encryption.go:106:10:106:24 | ctrStreamWriter [postupdate] | $@ is broken or weak, and should not be used. | encryption.go:74:2:74:40 | ... := ...[0] | The cryptographic algorithm TRIPLEDES |
|
||||||
| encryption.go:111:2:111:45 | call to XORKeyStream | $@ is broken or weak, and should not be used. | encryption.go:74:2:74:40 | extract:0 ... := ... | The cryptographic algorithm TRIPLEDES |
|
| encryption.go:111:2:111:45 | call to XORKeyStream | $@ is broken or weak, and should not be used. | encryption.go:74:2:74:40 | ... := ...[0] | The cryptographic algorithm TRIPLEDES |
|
||||||
| encryption.go:115:2:115:45 | call to XORKeyStream | $@ is broken or weak, and should not be used. | encryption.go:74:2:74:40 | extract:0 ... := ... | The cryptographic algorithm TRIPLEDES |
|
| encryption.go:115:2:115:45 | call to XORKeyStream | $@ is broken or weak, and should not be used. | encryption.go:74:2:74:40 | ... := ...[0] | The cryptographic algorithm TRIPLEDES |
|
||||||
| encryption.go:166:2:166:33 | call to XORKeyStream | $@ is broken or weak, and should not be used. | encryption.go:166:2:166:33 | call to XORKeyStream | The cryptographic algorithm RC4 |
|
| encryption.go:166:2:166:33 | call to XORKeyStream | $@ is broken or weak, and should not be used. | encryption.go:166:2:166:33 | call to XORKeyStream | The cryptographic algorithm RC4 |
|
||||||
|
|||||||
@@ -5,15 +5,15 @@ edges
|
|||||||
| go-jose.v3.go:25:16:25:20 | selection of URL | go-jose.v3.go:25:16:25:28 | call to Query | provenance | Src:MaD:3 MaD:5 |
|
| go-jose.v3.go:25:16:25:20 | selection of URL | go-jose.v3.go:25:16:25:28 | call to Query | provenance | Src:MaD:3 MaD:5 |
|
||||||
| go-jose.v3.go:25:16:25:28 | call to Query | go-jose.v3.go:25:16:25:47 | call to Get | provenance | MaD:6 |
|
| go-jose.v3.go:25:16:25:28 | call to Query | go-jose.v3.go:25:16:25:47 | call to Get | provenance | MaD:6 |
|
||||||
| go-jose.v3.go:25:16:25:47 | call to Get | go-jose.v3.go:26:15:26:25 | signedToken | provenance | |
|
| go-jose.v3.go:25:16:25:47 | call to Get | go-jose.v3.go:26:15:26:25 | signedToken | provenance | |
|
||||||
| go-jose.v3.go:26:15:26:25 | signedToken | go-jose.v3.go:29:39:37:1 | SSA def(signedToken) | provenance | |
|
| go-jose.v3.go:26:15:26:25 | signedToken | go-jose.v3.go:29:19:29:29 | SSA def(signedToken) | provenance | |
|
||||||
| go-jose.v3.go:29:39:37:1 | SSA def(signedToken) | go-jose.v3.go:31:37:31:47 | signedToken | provenance | |
|
| go-jose.v3.go:29:19:29:29 | SSA def(signedToken) | go-jose.v3.go:31:37:31:47 | signedToken | provenance | |
|
||||||
| go-jose.v3.go:31:2:31:48 | extract:0 ... := ... | go-jose.v3.go:33:12:33:23 | DecodedToken | provenance | Sink:MaD:2 |
|
| go-jose.v3.go:31:2:31:48 | ... := ...[0] | go-jose.v3.go:33:12:33:23 | DecodedToken | provenance | Sink:MaD:2 |
|
||||||
| go-jose.v3.go:31:37:31:47 | signedToken | go-jose.v3.go:31:2:31:48 | extract:0 ... := ... | provenance | MaD:4 |
|
| go-jose.v3.go:31:37:31:47 | signedToken | go-jose.v3.go:31:2:31:48 | ... := ...[0] | provenance | MaD:4 |
|
||||||
| golang-jwt-v5.go:28:16:28:20 | selection of URL | golang-jwt-v5.go:28:16:28:28 | call to Query | provenance | Src:MaD:3 MaD:5 |
|
| golang-jwt-v5.go:28:16:28:20 | selection of URL | golang-jwt-v5.go:28:16:28:28 | call to Query | provenance | Src:MaD:3 MaD:5 |
|
||||||
| golang-jwt-v5.go:28:16:28:28 | call to Query | golang-jwt-v5.go:28:16:28:47 | call to Get | provenance | MaD:6 |
|
| golang-jwt-v5.go:28:16:28:28 | call to Query | golang-jwt-v5.go:28:16:28:47 | call to Get | provenance | MaD:6 |
|
||||||
| golang-jwt-v5.go:28:16:28:47 | call to Get | golang-jwt-v5.go:29:25:29:35 | signedToken | provenance | |
|
| golang-jwt-v5.go:28:16:28:47 | call to Get | golang-jwt-v5.go:29:25:29:35 | signedToken | provenance | |
|
||||||
| golang-jwt-v5.go:29:25:29:35 | signedToken | golang-jwt-v5.go:32:49:40:1 | SSA def(signedToken) | provenance | |
|
| golang-jwt-v5.go:29:25:29:35 | signedToken | golang-jwt-v5.go:32:29:32:39 | SSA def(signedToken) | provenance | |
|
||||||
| golang-jwt-v5.go:32:49:40:1 | SSA def(signedToken) | golang-jwt-v5.go:34:58:34:68 | signedToken | provenance | Sink:MaD:1 |
|
| golang-jwt-v5.go:32:29:32:39 | SSA def(signedToken) | golang-jwt-v5.go:34:58:34:68 | signedToken | provenance | Sink:MaD:1 |
|
||||||
models
|
models
|
||||||
| 1 | Sink: github.com/golang-jwt/jwt; Parser; true; ParseUnverified; ; ; Argument[0]; jwt; manual |
|
| 1 | Sink: github.com/golang-jwt/jwt; Parser; true; ParseUnverified; ; ; Argument[0]; jwt; manual |
|
||||||
| 2 | Sink: group:go-jose/jwt; JSONWebToken; true; UnsafeClaimsWithoutVerification; ; ; Argument[receiver]; jwt; manual |
|
| 2 | Sink: group:go-jose/jwt; JSONWebToken; true; UnsafeClaimsWithoutVerification; ; ; Argument[receiver]; jwt; manual |
|
||||||
@@ -26,14 +26,14 @@ nodes
|
|||||||
| go-jose.v3.go:25:16:25:28 | call to Query | semmle.label | call to Query |
|
| go-jose.v3.go:25:16:25:28 | call to Query | semmle.label | call to Query |
|
||||||
| go-jose.v3.go:25:16:25:47 | call to Get | semmle.label | call to Get |
|
| go-jose.v3.go:25:16:25:47 | call to Get | semmle.label | call to Get |
|
||||||
| go-jose.v3.go:26:15:26:25 | signedToken | semmle.label | signedToken |
|
| go-jose.v3.go:26:15:26:25 | signedToken | semmle.label | signedToken |
|
||||||
| go-jose.v3.go:29:39:37:1 | SSA def(signedToken) | semmle.label | SSA def(signedToken) |
|
| go-jose.v3.go:29:19:29:29 | SSA def(signedToken) | semmle.label | SSA def(signedToken) |
|
||||||
| go-jose.v3.go:31:2:31:48 | extract:0 ... := ... | semmle.label | extract:0 ... := ... |
|
| go-jose.v3.go:31:2:31:48 | ... := ...[0] | semmle.label | ... := ...[0] |
|
||||||
| go-jose.v3.go:31:37:31:47 | signedToken | semmle.label | signedToken |
|
| go-jose.v3.go:31:37:31:47 | signedToken | semmle.label | signedToken |
|
||||||
| go-jose.v3.go:33:12:33:23 | DecodedToken | semmle.label | DecodedToken |
|
| go-jose.v3.go:33:12:33:23 | DecodedToken | semmle.label | DecodedToken |
|
||||||
| golang-jwt-v5.go:28:16:28:20 | selection of URL | semmle.label | selection of URL |
|
| golang-jwt-v5.go:28:16:28:20 | selection of URL | semmle.label | selection of URL |
|
||||||
| golang-jwt-v5.go:28:16:28:28 | call to Query | semmle.label | call to Query |
|
| golang-jwt-v5.go:28:16:28:28 | call to Query | semmle.label | call to Query |
|
||||||
| golang-jwt-v5.go:28:16:28:47 | call to Get | semmle.label | call to Get |
|
| golang-jwt-v5.go:28:16:28:47 | call to Get | semmle.label | call to Get |
|
||||||
| golang-jwt-v5.go:29:25:29:35 | signedToken | semmle.label | signedToken |
|
| golang-jwt-v5.go:29:25:29:35 | signedToken | semmle.label | signedToken |
|
||||||
| golang-jwt-v5.go:32:49:40:1 | SSA def(signedToken) | semmle.label | SSA def(signedToken) |
|
| golang-jwt-v5.go:32:29:32:39 | SSA def(signedToken) | semmle.label | SSA def(signedToken) |
|
||||||
| golang-jwt-v5.go:34:58:34:68 | signedToken | semmle.label | signedToken |
|
| golang-jwt-v5.go:34:58:34:68 | signedToken | semmle.label | signedToken |
|
||||||
subpaths
|
subpaths
|
||||||
|
|||||||
@@ -1,76 +1,63 @@
|
|||||||
#select
|
#select
|
||||||
| BadRedirectCheck.go:4:23:4:37 | ...==... | BadRedirectCheck.go:3:39:8:1 | arg:0 block statement | main.go:11:25:11:45 | call to sanitizeUrl | This is a check that $@, which flows into a $@, has a leading slash, but not that it does not have '/' or '\\' in its second position. | BadRedirectCheck.go:3:39:8:1 | arg:0 block statement | this value | main.go:11:25:11:45 | call to sanitizeUrl | redirect |
|
| BadRedirectCheck.go:4:23:4:37 | ...==... | BadRedirectCheck.go:3:18:3:22 | argument corresponding to redir | main.go:11:25:11:45 | call to sanitizeUrl | This is a check that $@, which flows into a $@, has a leading slash, but not that it does not have '/' or '\\' in its second position. | BadRedirectCheck.go:3:18:3:22 | argument corresponding to redir | this value | main.go:11:25:11:45 | call to sanitizeUrl | redirect |
|
||||||
| BadRedirectCheck.go:4:23:4:37 | ...==... | main.go:10:78:12:1 | arg:0 block statement | main.go:11:25:11:45 | call to sanitizeUrl | This is a check that $@, which flows into a $@, has a leading slash, but not that it does not have '/' or '\\' in its second position. | main.go:10:78:12:1 | arg:0 block statement | this value | main.go:11:25:11:45 | call to sanitizeUrl | redirect |
|
| BadRedirectCheck.go:4:23:4:37 | ...==... | main.go:10:18:10:25 | argument corresponding to redirect | main.go:11:25:11:45 | call to sanitizeUrl | This is a check that $@, which flows into a $@, has a leading slash, but not that it does not have '/' or '\\' in its second position. | main.go:10:18:10:25 | argument corresponding to redirect | this value | main.go:11:25:11:45 | call to sanitizeUrl | redirect |
|
||||||
| cves.go:11:26:11:38 | ...==... | cves.go:14:78:18:1 | arg:0 block statement | cves.go:16:26:16:28 | url | This is a check that $@, which flows into a $@, has a leading slash, but not that it does not have '/' or '\\' in its second position. | cves.go:14:78:18:1 | arg:0 block statement | this value | cves.go:16:26:16:28 | url | redirect |
|
| cves.go:11:26:11:38 | ...==... | cves.go:14:23:14:25 | argument corresponding to url | cves.go:16:26:16:28 | url | This is a check that $@, which flows into a $@, has a leading slash, but not that it does not have '/' or '\\' in its second position. | cves.go:14:23:14:25 | argument corresponding to url | this value | cves.go:16:26:16:28 | url | redirect |
|
||||||
| cves.go:34:6:34:37 | call to HasPrefix | cves.go:33:14:33:34 | call to Get | cves.go:37:25:37:32 | redirect | This is a check that $@, which flows into a $@, has a leading slash, but not that it does not have '/' or '\\' in its second position. | cves.go:33:14:33:34 | call to Get | this value | cves.go:37:25:37:32 | redirect | redirect |
|
| cves.go:34:6:34:37 | call to HasPrefix | cves.go:33:14:33:34 | call to Get | cves.go:37:25:37:32 | redirect | This is a check that $@, which flows into a $@, has a leading slash, but not that it does not have '/' or '\\' in its second position. | cves.go:33:14:33:34 | call to Get | this value | cves.go:37:25:37:32 | redirect | redirect |
|
||||||
| cves.go:42:6:42:37 | call to HasPrefix | cves.go:41:14:41:34 | call to Get | cves.go:45:25:45:32 | redirect | This is a check that $@, which flows into a $@, has a leading slash, but not that it does not have '/' or '\\' in its second position. | cves.go:41:14:41:34 | call to Get | this value | cves.go:45:25:45:32 | redirect | redirect |
|
| cves.go:42:6:42:37 | call to HasPrefix | cves.go:41:14:41:34 | call to Get | cves.go:45:25:45:32 | redirect | This is a check that $@, which flows into a $@, has a leading slash, but not that it does not have '/' or '\\' in its second position. | cves.go:41:14:41:34 | call to Get | this value | cves.go:45:25:45:32 | redirect | redirect |
|
||||||
| main.go:25:7:25:38 | call to HasPrefix | main.go:32:79:36:1 | arg:0 block statement | main.go:34:26:34:28 | url | This is a check that $@, which flows into a $@, has a leading slash, but not that it does not have '/' or '\\' in its second position. | main.go:32:79:36:1 | arg:0 block statement | this value | main.go:34:26:34:28 | url | redirect |
|
| main.go:25:7:25:38 | call to HasPrefix | main.go:32:24:32:26 | argument corresponding to url | main.go:34:26:34:28 | url | This is a check that $@, which flows into a $@, has a leading slash, but not that it does not have '/' or '\\' in its second position. | main.go:32:24:32:26 | argument corresponding to url | this value | main.go:34:26:34:28 | url | redirect |
|
||||||
| main.go:69:5:69:22 | ...!=... | main.go:68:41:74:1 | arg:0 block statement | main.go:77:25:77:39 | call to getTarget1 | This is a check that $@, which flows into a $@, has a leading slash, but not that it does not have '/' or '\\' in its second position. | main.go:68:41:74:1 | arg:0 block statement | this value | main.go:77:25:77:39 | call to getTarget1 | redirect |
|
| main.go:69:5:69:22 | ...!=... | main.go:68:17:68:24 | argument corresponding to redirect | main.go:77:25:77:39 | call to getTarget1 | This is a check that $@, which flows into a $@, has a leading slash, but not that it does not have '/' or '\\' in its second position. | main.go:68:17:68:24 | argument corresponding to redirect | this value | main.go:77:25:77:39 | call to getTarget1 | redirect |
|
||||||
| main.go:69:5:69:22 | ...!=... | main.go:76:74:78:1 | arg:0 block statement | main.go:77:25:77:39 | call to getTarget1 | This is a check that $@, which flows into a $@, has a leading slash, but not that it does not have '/' or '\\' in its second position. | main.go:76:74:78:1 | arg:0 block statement | this value | main.go:77:25:77:39 | call to getTarget1 | redirect |
|
| main.go:69:5:69:22 | ...!=... | main.go:76:19:76:21 | argument corresponding to url | main.go:77:25:77:39 | call to getTarget1 | This is a check that $@, which flows into a $@, has a leading slash, but not that it does not have '/' or '\\' in its second position. | main.go:76:19:76:21 | argument corresponding to url | this value | main.go:77:25:77:39 | call to getTarget1 | redirect |
|
||||||
| main.go:83:5:83:20 | ...!=... | main.go:87:9:87:14 | selection of Path | main.go:91:25:91:39 | call to getTarget2 | This is a check that $@, which flows into a $@, has a leading slash, but not that it does not have '/' or '\\' in its second position. | main.go:87:9:87:14 | selection of Path | this value | main.go:91:25:91:39 | call to getTarget2 | redirect |
|
| main.go:83:5:83:20 | ...!=... | main.go:87:9:87:14 | selection of Path | main.go:91:25:91:39 | call to getTarget2 | This is a check that $@, which flows into a $@, has a leading slash, but not that it does not have '/' or '\\' in its second position. | main.go:87:9:87:14 | selection of Path | this value | main.go:91:25:91:39 | call to getTarget2 | redirect |
|
||||||
edges
|
edges
|
||||||
| BadRedirectCheck.go:3:39:8:1 | SSA def(redir) | BadRedirectCheck.go:5:10:5:14 | redir | provenance | |
|
| BadRedirectCheck.go:3:18:3:22 | SSA def(redir) | BadRedirectCheck.go:5:10:5:14 | redir | provenance | |
|
||||||
| BadRedirectCheck.go:3:39:8:1 | arg:0 block statement | BadRedirectCheck.go:5:10:5:14 | redir | provenance | |
|
| BadRedirectCheck.go:3:18:3:22 | argument corresponding to redir | BadRedirectCheck.go:5:10:5:14 | redir | provenance | |
|
||||||
| BadRedirectCheck.go:5:10:5:14 | redir | main.go:11:25:11:45 | call to sanitizeUrl | provenance | Sink:MaD:1 |
|
| BadRedirectCheck.go:5:10:5:14 | redir | main.go:11:25:11:45 | call to sanitizeUrl | provenance | Sink:MaD:1 |
|
||||||
| cves.go:14:78:18:1 | arg:0 block statement | cves.go:16:26:16:28 | url | provenance | Sink:MaD:1 |
|
| cves.go:14:23:14:25 | argument corresponding to url | cves.go:16:26:16:28 | url | provenance | Sink:MaD:1 |
|
||||||
| cves.go:33:14:33:34 | call to Get | cves.go:37:25:37:32 | redirect | provenance | Sink:MaD:1 |
|
| cves.go:33:14:33:34 | call to Get | cves.go:37:25:37:32 | redirect | provenance | Sink:MaD:1 |
|
||||||
| cves.go:41:14:41:34 | call to Get | cves.go:45:25:45:32 | redirect | provenance | Sink:MaD:1 |
|
| cves.go:41:14:41:34 | call to Get | cves.go:45:25:45:32 | redirect | provenance | Sink:MaD:1 |
|
||||||
| main.go:10:78:12:1 | arg:0 block statement | main.go:11:37:11:44 | redirect | provenance | |
|
| main.go:10:18:10:25 | argument corresponding to redirect | main.go:11:37:11:44 | redirect | provenance | |
|
||||||
| main.go:11:37:11:44 | redirect | BadRedirectCheck.go:3:39:8:1 | SSA def(redir) | provenance | |
|
| main.go:11:37:11:44 | redirect | BadRedirectCheck.go:3:18:3:22 | SSA def(redir) | provenance | |
|
||||||
| main.go:11:37:11:44 | redirect | main.go:11:25:11:45 | call to sanitizeUrl | provenance | Sink:MaD:1 |
|
| main.go:11:37:11:44 | redirect | main.go:11:25:11:45 | call to sanitizeUrl | provenance | Sink:MaD:1 |
|
||||||
| main.go:32:79:36:1 | arg:0 block statement | main.go:34:26:34:28 | url | provenance | Sink:MaD:1 |
|
| main.go:32:24:32:26 | argument corresponding to url | main.go:34:26:34:28 | url | provenance | Sink:MaD:1 |
|
||||||
| main.go:68:41:74:1 | SSA def(redirect) | main.go:73:20:73:27 | redirect | provenance | |
|
| main.go:68:17:68:24 | SSA def(redirect) | main.go:73:20:73:27 | redirect | provenance | |
|
||||||
| main.go:68:41:74:1 | arg:0 block statement | main.go:73:20:73:27 | redirect | provenance | |
|
| main.go:68:17:68:24 | argument corresponding to redirect | main.go:73:20:73:27 | redirect | provenance | |
|
||||||
| main.go:73:9:73:28 | call to Clean | main.go:77:25:77:39 | call to getTarget1 | provenance | Sink:MaD:1 |
|
| main.go:73:9:73:28 | call to Clean | main.go:77:25:77:39 | call to getTarget1 | provenance | Sink:MaD:1 |
|
||||||
| main.go:73:20:73:27 | redirect | main.go:73:9:73:28 | call to Clean | provenance | MaD:2 |
|
| main.go:73:20:73:27 | redirect | main.go:73:9:73:28 | call to Clean | provenance | MaD:2 |
|
||||||
| main.go:73:20:73:27 | redirect | main.go:73:9:73:28 | call to Clean | provenance | MaD:2 |
|
| main.go:73:20:73:27 | redirect | main.go:73:9:73:28 | call to Clean | provenance | MaD:2 |
|
||||||
| main.go:76:74:78:1 | arg:0 block statement | main.go:77:36:77:38 | url | provenance | |
|
| main.go:76:19:76:21 | argument corresponding to url | main.go:77:36:77:38 | url | provenance | |
|
||||||
| main.go:77:36:77:38 | url | main.go:68:41:74:1 | SSA def(redirect) | provenance | |
|
| main.go:77:36:77:38 | url | main.go:68:17:68:24 | SSA def(redirect) | provenance | |
|
||||||
| main.go:77:36:77:38 | url | main.go:77:25:77:39 | call to getTarget1 | provenance | MaD:2 Sink:MaD:1 |
|
| main.go:77:36:77:38 | url | main.go:77:25:77:39 | call to getTarget1 | provenance | MaD:2 Sink:MaD:1 |
|
||||||
| main.go:87:9:87:14 | selection of Path | main.go:91:25:91:39 | call to getTarget2 | provenance | Sink:MaD:1 |
|
| main.go:87:9:87:14 | selection of Path | main.go:91:25:91:39 | call to getTarget2 | provenance | Sink:MaD:1 |
|
||||||
models
|
models
|
||||||
| 1 | Sink: net/http; ; false; Redirect; ; ; Argument[2]; url-redirection[0]; manual |
|
| 1 | Sink: net/http; ; false; Redirect; ; ; Argument[2]; url-redirection[0]; manual |
|
||||||
| 2 | Summary: path; ; false; Clean; ; ; Argument[0]; ReturnValue; taint; manual |
|
| 2 | Summary: path; ; false; Clean; ; ; Argument[0]; ReturnValue; taint; manual |
|
||||||
nodes
|
nodes
|
||||||
| BadRedirectCheck.go:3:39:8:1 | SSA def(redir) | semmle.label | SSA def(redir) |
|
| BadRedirectCheck.go:3:18:3:22 | SSA def(redir) | semmle.label | SSA def(redir) |
|
||||||
| BadRedirectCheck.go:3:39:8:1 | arg:0 block statement | semmle.label | arg:0 block statement |
|
| BadRedirectCheck.go:3:18:3:22 | argument corresponding to redir | semmle.label | argument corresponding to redir |
|
||||||
| BadRedirectCheck.go:5:10:5:14 | redir | semmle.label | redir |
|
| BadRedirectCheck.go:5:10:5:14 | redir | semmle.label | redir |
|
||||||
| BadRedirectCheck.go:5:10:5:14 | redir | semmle.label | redir |
|
| BadRedirectCheck.go:5:10:5:14 | redir | semmle.label | redir |
|
||||||
| cves.go:14:78:18:1 | arg:0 block statement | semmle.label | arg:0 block statement |
|
| cves.go:14:23:14:25 | argument corresponding to url | semmle.label | argument corresponding to url |
|
||||||
| cves.go:16:26:16:28 | url | semmle.label | url |
|
| cves.go:16:26:16:28 | url | semmle.label | url |
|
||||||
| cves.go:33:14:33:34 | call to Get | semmle.label | call to Get |
|
| cves.go:33:14:33:34 | call to Get | semmle.label | call to Get |
|
||||||
| cves.go:37:25:37:32 | redirect | semmle.label | redirect |
|
| cves.go:37:25:37:32 | redirect | semmle.label | redirect |
|
||||||
| cves.go:41:14:41:34 | call to Get | semmle.label | call to Get |
|
| cves.go:41:14:41:34 | call to Get | semmle.label | call to Get |
|
||||||
| cves.go:45:25:45:32 | redirect | semmle.label | redirect |
|
| cves.go:45:25:45:32 | redirect | semmle.label | redirect |
|
||||||
| main.go:10:78:12:1 | arg:0 block statement | semmle.label | arg:0 block statement |
|
| main.go:10:18:10:25 | argument corresponding to redirect | semmle.label | argument corresponding to redirect |
|
||||||
| main.go:11:25:11:45 | call to sanitizeUrl | semmle.label | call to sanitizeUrl |
|
| main.go:11:25:11:45 | call to sanitizeUrl | semmle.label | call to sanitizeUrl |
|
||||||
| main.go:11:37:11:44 | redirect | semmle.label | redirect |
|
| main.go:11:37:11:44 | redirect | semmle.label | redirect |
|
||||||
| main.go:32:79:36:1 | arg:0 block statement | semmle.label | arg:0 block statement |
|
| main.go:32:24:32:26 | argument corresponding to url | semmle.label | argument corresponding to url |
|
||||||
| main.go:34:26:34:28 | url | semmle.label | url |
|
| main.go:34:26:34:28 | url | semmle.label | url |
|
||||||
| main.go:68:41:74:1 | SSA def(redirect) | semmle.label | SSA def(redirect) |
|
| main.go:68:17:68:24 | SSA def(redirect) | semmle.label | SSA def(redirect) |
|
||||||
| main.go:68:41:74:1 | arg:0 block statement | semmle.label | arg:0 block statement |
|
| main.go:68:17:68:24 | argument corresponding to redirect | semmle.label | argument corresponding to redirect |
|
||||||
| main.go:73:9:73:28 | call to Clean | semmle.label | call to Clean |
|
| main.go:73:9:73:28 | call to Clean | semmle.label | call to Clean |
|
||||||
| main.go:73:9:73:28 | call to Clean | semmle.label | call to Clean |
|
| main.go:73:9:73:28 | call to Clean | semmle.label | call to Clean |
|
||||||
| main.go:73:20:73:27 | redirect | semmle.label | redirect |
|
| main.go:73:20:73:27 | redirect | semmle.label | redirect |
|
||||||
| main.go:73:20:73:27 | redirect | semmle.label | redirect |
|
| main.go:73:20:73:27 | redirect | semmle.label | redirect |
|
||||||
| main.go:76:74:78:1 | arg:0 block statement | semmle.label | arg:0 block statement |
|
| main.go:76:19:76:21 | argument corresponding to url | semmle.label | argument corresponding to url |
|
||||||
| main.go:77:25:77:39 | call to getTarget1 | semmle.label | call to getTarget1 |
|
| main.go:77:25:77:39 | call to getTarget1 | semmle.label | call to getTarget1 |
|
||||||
| main.go:77:36:77:38 | url | semmle.label | url |
|
| main.go:77:36:77:38 | url | semmle.label | url |
|
||||||
| main.go:87:9:87:14 | selection of Path | semmle.label | selection of Path |
|
| main.go:87:9:87:14 | selection of Path | semmle.label | selection of Path |
|
||||||
| main.go:91:25:91:39 | call to getTarget2 | semmle.label | call to getTarget2 |
|
| main.go:91:25:91:39 | call to getTarget2 | semmle.label | call to getTarget2 |
|
||||||
subpaths
|
subpaths
|
||||||
| main.go:11:37:11:44 | redirect | BadRedirectCheck.go:3:39:8:1 | SSA def(redir) | BadRedirectCheck.go:5:10:5:14 | redir | main.go:11:25:11:45 | call to sanitizeUrl |
|
| main.go:11:37:11:44 | redirect | BadRedirectCheck.go:3:18:3:22 | SSA def(redir) | BadRedirectCheck.go:5:10:5:14 | redir | main.go:11:25:11:45 | call to sanitizeUrl |
|
||||||
| main.go:77:36:77:38 | url | main.go:68:41:74:1 | SSA def(redirect) | main.go:73:9:73:28 | call to Clean | main.go:77:25:77:39 | call to getTarget1 |
|
| main.go:77:36:77:38 | url | main.go:68:17:68:24 | SSA def(redirect) | main.go:73:9:73:28 | call to Clean | main.go:77:25:77:39 | call to getTarget1 |
|
||||||
testFailures
|
|
||||||
| BadRedirectCheck.go:3:39:8:1 | arg:0 block statement | Unexpected result: Source |
|
|
||||||
| BadRedirectCheck.go:3:41:3:51 | comment | Missing result: Source |
|
|
||||||
| cves.go:14:78:18:1 | arg:0 block statement | Unexpected result: Source |
|
|
||||||
| cves.go:14:80:14:90 | comment | Missing result: Source |
|
|
||||||
| main.go:10:78:12:1 | arg:0 block statement | Unexpected result: Source |
|
|
||||||
| main.go:10:80:10:90 | comment | Missing result: Source |
|
|
||||||
| main.go:32:79:36:1 | arg:0 block statement | Unexpected result: Source |
|
|
||||||
| main.go:32:81:32:91 | comment | Missing result: Source |
|
|
||||||
| main.go:68:41:74:1 | arg:0 block statement | Unexpected result: Source |
|
|
||||||
| main.go:68:43:68:53 | comment | Missing result: Source |
|
|
||||||
| main.go:76:74:78:1 | arg:0 block statement | Unexpected result: Source |
|
|
||||||
| main.go:76:76:76:86 | comment | Missing result: Source |
|
|
||||||
|
|||||||
@@ -30,16 +30,16 @@ edges
|
|||||||
| stdlib.go:71:23:71:37 | ...+... | stdlib.go:71:23:71:40 | ...+... | provenance | Config Sink:MaD:1 |
|
| stdlib.go:71:23:71:37 | ...+... | stdlib.go:71:23:71:40 | ...+... | provenance | Config Sink:MaD:1 |
|
||||||
| stdlib.go:93:13:93:18 | selection of Form | stdlib.go:93:13:93:32 | call to Get | provenance | Src:MaD:2 Config |
|
| stdlib.go:93:13:93:18 | selection of Form | stdlib.go:93:13:93:32 | call to Get | provenance | Src:MaD:2 Config |
|
||||||
| stdlib.go:93:13:93:32 | call to Get | stdlib.go:94:3:94:8 | target | provenance | |
|
| stdlib.go:93:13:93:32 | call to Get | stdlib.go:94:3:94:8 | target | provenance | |
|
||||||
| stdlib.go:94:3:94:8 | target | stdlib.go:94:3:94:25 | compound-rhs ... += ... | provenance | Config |
|
| stdlib.go:94:3:94:8 | target | stdlib.go:94:3:94:25 | ... += ... | provenance | Config |
|
||||||
| stdlib.go:94:3:94:25 | compound-rhs ... += ... | stdlib.go:96:23:96:28 | target | provenance | Sink:MaD:1 |
|
| stdlib.go:94:3:94:25 | ... += ... | stdlib.go:96:23:96:28 | target | provenance | Sink:MaD:1 |
|
||||||
| stdlib.go:116:4:116:4 | implicit-deref r [postupdate] [URL] | stdlib.go:116:4:116:4 | r [postupdate] [pointer, URL] | provenance | |
|
| stdlib.go:116:4:116:4 | implicit dereference [postupdate] [URL] | stdlib.go:116:4:116:4 | r [postupdate] [pointer, URL] | provenance | |
|
||||||
| stdlib.go:116:4:116:4 | r [postupdate] [pointer, URL] | stdlib.go:117:24:117:24 | r [pointer, URL] | provenance | |
|
| stdlib.go:116:4:116:4 | r [postupdate] [pointer, URL] | stdlib.go:117:24:117:24 | r [pointer, URL] | provenance | |
|
||||||
| stdlib.go:116:4:116:8 | implicit-deref selection of URL | stdlib.go:116:4:116:8 | selection of URL [postupdate] | provenance | Config |
|
| stdlib.go:116:4:116:8 | implicit dereference | stdlib.go:116:4:116:8 | selection of URL [postupdate] | provenance | Config |
|
||||||
| stdlib.go:116:4:116:8 | selection of URL | stdlib.go:116:4:116:8 | implicit-deref selection of URL | provenance | Src:MaD:4 Config |
|
| stdlib.go:116:4:116:8 | selection of URL | stdlib.go:116:4:116:8 | implicit dereference | provenance | Src:MaD:4 Config |
|
||||||
| stdlib.go:116:4:116:8 | selection of URL [postupdate] | stdlib.go:116:4:116:4 | implicit-deref r [postupdate] [URL] | provenance | |
|
| stdlib.go:116:4:116:8 | selection of URL [postupdate] | stdlib.go:116:4:116:4 | implicit dereference [postupdate] [URL] | provenance | |
|
||||||
| stdlib.go:116:4:116:8 | selection of URL [postupdate] | stdlib.go:116:4:116:8 | implicit-deref selection of URL | provenance | Config |
|
| stdlib.go:116:4:116:8 | selection of URL [postupdate] | stdlib.go:116:4:116:8 | implicit dereference | provenance | Config |
|
||||||
| stdlib.go:117:24:117:24 | implicit-deref r [URL] | stdlib.go:117:24:117:28 | selection of URL | provenance | |
|
| stdlib.go:117:24:117:24 | implicit dereference [URL] | stdlib.go:117:24:117:28 | selection of URL | provenance | |
|
||||||
| stdlib.go:117:24:117:24 | r [pointer, URL] | stdlib.go:117:24:117:24 | implicit-deref r [URL] | provenance | |
|
| stdlib.go:117:24:117:24 | r [pointer, URL] | stdlib.go:117:24:117:24 | implicit dereference [URL] | provenance | |
|
||||||
| stdlib.go:117:24:117:28 | selection of URL | stdlib.go:117:24:117:37 | call to String | provenance | Src:MaD:4 Config Sink:MaD:1 |
|
| stdlib.go:117:24:117:28 | selection of URL | stdlib.go:117:24:117:37 | call to String | provenance | Src:MaD:4 Config Sink:MaD:1 |
|
||||||
| stdlib.go:150:13:150:18 | selection of Form | stdlib.go:150:13:150:32 | call to Get | provenance | Src:MaD:2 Config |
|
| stdlib.go:150:13:150:18 | selection of Form | stdlib.go:150:13:150:32 | call to Get | provenance | Src:MaD:2 Config |
|
||||||
| stdlib.go:150:13:150:32 | call to Get | stdlib.go:156:23:156:28 | target | provenance | Sink:MaD:1 |
|
| stdlib.go:150:13:150:32 | call to Get | stdlib.go:156:23:156:28 | target | provenance | Sink:MaD:1 |
|
||||||
@@ -51,42 +51,42 @@ edges
|
|||||||
| stdlib.go:177:35:177:39 | selection of URL | stdlib.go:177:35:177:52 | call to RequestURI | provenance | Src:MaD:4 Config |
|
| stdlib.go:177:35:177:39 | selection of URL | stdlib.go:177:35:177:52 | call to RequestURI | provenance | Src:MaD:4 Config |
|
||||||
| stdlib.go:177:35:177:52 | call to RequestURI | stdlib.go:177:24:177:52 | ...+... | provenance | Config Sink:MaD:1 |
|
| stdlib.go:177:35:177:52 | call to RequestURI | stdlib.go:177:24:177:52 | ...+... | provenance | Config Sink:MaD:1 |
|
||||||
| stdlib.go:186:13:186:33 | call to FormValue | stdlib.go:188:23:188:28 | target | provenance | Src:MaD:3 Sink:MaD:1 |
|
| stdlib.go:186:13:186:33 | call to FormValue | stdlib.go:188:23:188:28 | target | provenance | Src:MaD:3 Sink:MaD:1 |
|
||||||
| stdlib.go:194:3:194:57 | extract:0 ... := ... | stdlib.go:196:23:196:28 | target | provenance | |
|
| stdlib.go:194:3:194:57 | ... := ...[0] | stdlib.go:196:23:196:28 | target | provenance | |
|
||||||
| stdlib.go:194:36:194:56 | call to FormValue | stdlib.go:194:3:194:57 | extract:0 ... := ... | provenance | Src:MaD:3 Config |
|
| stdlib.go:194:36:194:56 | call to FormValue | stdlib.go:194:3:194:57 | ... := ...[0] | provenance | Src:MaD:3 Config |
|
||||||
| stdlib.go:196:23:196:28 | implicit-deref target | stdlib.go:196:23:196:28 | target [postupdate] | provenance | Config |
|
| stdlib.go:196:23:196:28 | implicit dereference | stdlib.go:196:23:196:28 | target [postupdate] | provenance | Config |
|
||||||
| stdlib.go:196:23:196:28 | implicit-deref target | stdlib.go:196:23:196:33 | selection of Path | provenance | Config Sink:MaD:1 |
|
| stdlib.go:196:23:196:28 | implicit dereference | stdlib.go:196:23:196:33 | selection of Path | provenance | Config Sink:MaD:1 |
|
||||||
| stdlib.go:196:23:196:28 | target | stdlib.go:196:23:196:28 | implicit-deref target | provenance | Config |
|
| stdlib.go:196:23:196:28 | target | stdlib.go:196:23:196:28 | implicit dereference | provenance | Config |
|
||||||
| stdlib.go:196:23:196:28 | target | stdlib.go:196:23:196:33 | selection of Path | provenance | Config Sink:MaD:1 |
|
| stdlib.go:196:23:196:28 | target | stdlib.go:196:23:196:33 | selection of Path | provenance | Config Sink:MaD:1 |
|
||||||
| stdlib.go:196:23:196:28 | target | stdlib.go:198:23:198:28 | target | provenance | |
|
| stdlib.go:196:23:196:28 | target | stdlib.go:198:23:198:28 | target | provenance | |
|
||||||
| stdlib.go:196:23:196:28 | target [postupdate] | stdlib.go:196:23:196:28 | implicit-deref target | provenance | Config |
|
| stdlib.go:196:23:196:28 | target [postupdate] | stdlib.go:196:23:196:28 | implicit dereference | provenance | Config |
|
||||||
| stdlib.go:196:23:196:28 | target [postupdate] | stdlib.go:198:23:198:28 | target | provenance | |
|
| stdlib.go:196:23:196:28 | target [postupdate] | stdlib.go:198:23:198:28 | target | provenance | |
|
||||||
| stdlib.go:198:23:198:28 | target | stdlib.go:198:23:198:42 | call to EscapedPath | provenance | Config Sink:MaD:1 |
|
| stdlib.go:198:23:198:28 | target | stdlib.go:198:23:198:42 | call to EscapedPath | provenance | Config Sink:MaD:1 |
|
||||||
| stdlib.go:210:3:210:3 | implicit-deref u [postupdate] | stdlib.go:210:3:210:3 | u [postupdate] | provenance | Config |
|
| stdlib.go:210:3:210:3 | implicit dereference [postupdate] | stdlib.go:210:3:210:3 | u [postupdate] | provenance | Config |
|
||||||
| stdlib.go:210:3:210:3 | implicit-deref u [postupdate] | stdlib.go:210:3:210:3 | u [postupdate] [pointer] | provenance | |
|
| stdlib.go:210:3:210:3 | implicit dereference [postupdate] | stdlib.go:210:3:210:3 | u [postupdate] [pointer] | provenance | |
|
||||||
| stdlib.go:210:3:210:3 | u [postupdate] | stdlib.go:212:23:212:23 | u | provenance | |
|
| stdlib.go:210:3:210:3 | u [postupdate] | stdlib.go:212:23:212:23 | u | provenance | |
|
||||||
| stdlib.go:210:3:210:3 | u [postupdate] [pointer] | stdlib.go:212:23:212:23 | u [pointer] | provenance | |
|
| stdlib.go:210:3:210:3 | u [postupdate] [pointer] | stdlib.go:212:23:212:23 | u [pointer] | provenance | |
|
||||||
| stdlib.go:210:12:210:30 | call to FormValue | stdlib.go:210:3:210:3 | implicit-deref u [postupdate] | provenance | Src:MaD:3 Config |
|
| stdlib.go:210:12:210:30 | call to FormValue | stdlib.go:210:3:210:3 | implicit dereference [postupdate] | provenance | Src:MaD:3 Config |
|
||||||
| stdlib.go:210:12:210:30 | call to FormValue | stdlib.go:210:3:210:3 | u [postupdate] | provenance | Src:MaD:3 Config |
|
| stdlib.go:210:12:210:30 | call to FormValue | stdlib.go:210:3:210:3 | u [postupdate] | provenance | Src:MaD:3 Config |
|
||||||
| stdlib.go:212:23:212:23 | implicit-deref u | stdlib.go:212:23:212:23 | u [postupdate] | provenance | Config |
|
| stdlib.go:212:23:212:23 | implicit dereference | stdlib.go:212:23:212:23 | u [postupdate] | provenance | Config |
|
||||||
| stdlib.go:212:23:212:23 | implicit-deref u | stdlib.go:212:23:212:28 | selection of Path | provenance | Config Sink:MaD:1 |
|
| stdlib.go:212:23:212:23 | implicit dereference | stdlib.go:212:23:212:28 | selection of Path | provenance | Config Sink:MaD:1 |
|
||||||
| stdlib.go:212:23:212:23 | u | stdlib.go:212:23:212:23 | implicit-deref u | provenance | Config |
|
| stdlib.go:212:23:212:23 | u | stdlib.go:212:23:212:23 | implicit dereference | provenance | Config |
|
||||||
| stdlib.go:212:23:212:23 | u | stdlib.go:212:23:212:28 | selection of Path | provenance | Config Sink:MaD:1 |
|
| stdlib.go:212:23:212:23 | u | stdlib.go:212:23:212:28 | selection of Path | provenance | Config Sink:MaD:1 |
|
||||||
| stdlib.go:212:23:212:23 | u | stdlib.go:214:23:214:23 | u | provenance | |
|
| stdlib.go:212:23:212:23 | u | stdlib.go:214:23:214:23 | u | provenance | |
|
||||||
| stdlib.go:212:23:212:23 | u [pointer] | stdlib.go:212:23:212:23 | implicit-deref u | provenance | |
|
| stdlib.go:212:23:212:23 | u [pointer] | stdlib.go:212:23:212:23 | implicit dereference | provenance | |
|
||||||
| stdlib.go:212:23:212:23 | u [postupdate] | stdlib.go:212:23:212:23 | implicit-deref u | provenance | Config |
|
| stdlib.go:212:23:212:23 | u [postupdate] | stdlib.go:212:23:212:23 | implicit dereference | provenance | Config |
|
||||||
| stdlib.go:212:23:212:23 | u [postupdate] | stdlib.go:214:23:214:23 | u | provenance | |
|
| stdlib.go:212:23:212:23 | u [postupdate] | stdlib.go:214:23:214:23 | u | provenance | |
|
||||||
| stdlib.go:214:23:214:23 | u | stdlib.go:214:23:214:32 | call to String | provenance | Config Sink:MaD:1 |
|
| stdlib.go:214:23:214:23 | u | stdlib.go:214:23:214:32 | call to String | provenance | Config Sink:MaD:1 |
|
||||||
| stdlib.go:257:3:257:3 | implicit-deref u [postupdate] | stdlib.go:257:3:257:3 | u [postupdate] | provenance | Config |
|
| stdlib.go:257:3:257:3 | implicit dereference [postupdate] | stdlib.go:257:3:257:3 | u [postupdate] | provenance | Config |
|
||||||
| stdlib.go:257:3:257:3 | implicit-deref u [postupdate] | stdlib.go:257:3:257:3 | u [postupdate] [pointer] | provenance | |
|
| stdlib.go:257:3:257:3 | implicit dereference [postupdate] | stdlib.go:257:3:257:3 | u [postupdate] [pointer] | provenance | |
|
||||||
| stdlib.go:257:3:257:3 | u [postupdate] | stdlib.go:260:3:260:3 | u | provenance | |
|
| stdlib.go:257:3:257:3 | u [postupdate] | stdlib.go:260:3:260:3 | u | provenance | |
|
||||||
| stdlib.go:257:3:257:3 | u [postupdate] [pointer] | stdlib.go:260:3:260:3 | u [pointer] | provenance | |
|
| stdlib.go:257:3:257:3 | u [postupdate] [pointer] | stdlib.go:260:3:260:3 | u [pointer] | provenance | |
|
||||||
| stdlib.go:257:12:257:30 | call to FormValue | stdlib.go:257:3:257:3 | implicit-deref u [postupdate] | provenance | Src:MaD:3 Config |
|
| stdlib.go:257:12:257:30 | call to FormValue | stdlib.go:257:3:257:3 | implicit dereference [postupdate] | provenance | Src:MaD:3 Config |
|
||||||
| stdlib.go:257:12:257:30 | call to FormValue | stdlib.go:257:3:257:3 | u [postupdate] | provenance | Src:MaD:3 Config |
|
| stdlib.go:257:12:257:30 | call to FormValue | stdlib.go:257:3:257:3 | u [postupdate] | provenance | Src:MaD:3 Config |
|
||||||
| stdlib.go:260:3:260:3 | implicit-deref u | stdlib.go:260:3:260:3 | u [postupdate] | provenance | Config |
|
| stdlib.go:260:3:260:3 | implicit dereference | stdlib.go:260:3:260:3 | u [postupdate] | provenance | Config |
|
||||||
| stdlib.go:260:3:260:3 | u | stdlib.go:260:3:260:3 | implicit-deref u | provenance | Config |
|
| stdlib.go:260:3:260:3 | u | stdlib.go:260:3:260:3 | implicit dereference | provenance | Config |
|
||||||
| stdlib.go:260:3:260:3 | u | stdlib.go:261:23:261:23 | u | provenance | |
|
| stdlib.go:260:3:260:3 | u | stdlib.go:261:23:261:23 | u | provenance | |
|
||||||
| stdlib.go:260:3:260:3 | u [pointer] | stdlib.go:260:3:260:3 | implicit-deref u | provenance | |
|
| stdlib.go:260:3:260:3 | u [pointer] | stdlib.go:260:3:260:3 | implicit dereference | provenance | |
|
||||||
| stdlib.go:260:3:260:3 | u [postupdate] | stdlib.go:260:3:260:3 | implicit-deref u | provenance | Config |
|
| stdlib.go:260:3:260:3 | u [postupdate] | stdlib.go:260:3:260:3 | implicit dereference | provenance | Config |
|
||||||
| stdlib.go:260:3:260:3 | u [postupdate] | stdlib.go:261:23:261:23 | u | provenance | |
|
| stdlib.go:260:3:260:3 | u [postupdate] | stdlib.go:261:23:261:23 | u | provenance | |
|
||||||
| stdlib.go:261:23:261:23 | u | stdlib.go:261:23:261:32 | call to String | provenance | Config Sink:MaD:1 |
|
| stdlib.go:261:23:261:23 | u | stdlib.go:261:23:261:32 | call to String | provenance | Config Sink:MaD:1 |
|
||||||
models
|
models
|
||||||
@@ -118,14 +118,14 @@ nodes
|
|||||||
| stdlib.go:93:13:93:18 | selection of Form | semmle.label | selection of Form |
|
| stdlib.go:93:13:93:18 | selection of Form | semmle.label | selection of Form |
|
||||||
| stdlib.go:93:13:93:32 | call to Get | semmle.label | call to Get |
|
| stdlib.go:93:13:93:32 | call to Get | semmle.label | call to Get |
|
||||||
| stdlib.go:94:3:94:8 | target | semmle.label | target |
|
| stdlib.go:94:3:94:8 | target | semmle.label | target |
|
||||||
| stdlib.go:94:3:94:25 | compound-rhs ... += ... | semmle.label | compound-rhs ... += ... |
|
| stdlib.go:94:3:94:25 | ... += ... | semmle.label | ... += ... |
|
||||||
| stdlib.go:96:23:96:28 | target | semmle.label | target |
|
| stdlib.go:96:23:96:28 | target | semmle.label | target |
|
||||||
| stdlib.go:116:4:116:4 | implicit-deref r [postupdate] [URL] | semmle.label | implicit-deref r [postupdate] [URL] |
|
| stdlib.go:116:4:116:4 | implicit dereference [postupdate] [URL] | semmle.label | implicit dereference [postupdate] [URL] |
|
||||||
| stdlib.go:116:4:116:4 | r [postupdate] [pointer, URL] | semmle.label | r [postupdate] [pointer, URL] |
|
| stdlib.go:116:4:116:4 | r [postupdate] [pointer, URL] | semmle.label | r [postupdate] [pointer, URL] |
|
||||||
| stdlib.go:116:4:116:8 | implicit-deref selection of URL | semmle.label | implicit-deref selection of URL |
|
| stdlib.go:116:4:116:8 | implicit dereference | semmle.label | implicit dereference |
|
||||||
| stdlib.go:116:4:116:8 | selection of URL | semmle.label | selection of URL |
|
| stdlib.go:116:4:116:8 | selection of URL | semmle.label | selection of URL |
|
||||||
| stdlib.go:116:4:116:8 | selection of URL [postupdate] | semmle.label | selection of URL [postupdate] |
|
| stdlib.go:116:4:116:8 | selection of URL [postupdate] | semmle.label | selection of URL [postupdate] |
|
||||||
| stdlib.go:117:24:117:24 | implicit-deref r [URL] | semmle.label | implicit-deref r [URL] |
|
| stdlib.go:117:24:117:24 | implicit dereference [URL] | semmle.label | implicit dereference [URL] |
|
||||||
| stdlib.go:117:24:117:24 | r [pointer, URL] | semmle.label | r [pointer, URL] |
|
| stdlib.go:117:24:117:24 | r [pointer, URL] | semmle.label | r [pointer, URL] |
|
||||||
| stdlib.go:117:24:117:28 | selection of URL | semmle.label | selection of URL |
|
| stdlib.go:117:24:117:28 | selection of URL | semmle.label | selection of URL |
|
||||||
| stdlib.go:117:24:117:37 | call to String | semmle.label | call to String |
|
| stdlib.go:117:24:117:37 | call to String | semmle.label | call to String |
|
||||||
@@ -142,30 +142,30 @@ nodes
|
|||||||
| stdlib.go:177:35:177:52 | call to RequestURI | semmle.label | call to RequestURI |
|
| stdlib.go:177:35:177:52 | call to RequestURI | semmle.label | call to RequestURI |
|
||||||
| stdlib.go:186:13:186:33 | call to FormValue | semmle.label | call to FormValue |
|
| stdlib.go:186:13:186:33 | call to FormValue | semmle.label | call to FormValue |
|
||||||
| stdlib.go:188:23:188:28 | target | semmle.label | target |
|
| stdlib.go:188:23:188:28 | target | semmle.label | target |
|
||||||
| stdlib.go:194:3:194:57 | extract:0 ... := ... | semmle.label | extract:0 ... := ... |
|
| stdlib.go:194:3:194:57 | ... := ...[0] | semmle.label | ... := ...[0] |
|
||||||
| stdlib.go:194:36:194:56 | call to FormValue | semmle.label | call to FormValue |
|
| stdlib.go:194:36:194:56 | call to FormValue | semmle.label | call to FormValue |
|
||||||
| stdlib.go:196:23:196:28 | implicit-deref target | semmle.label | implicit-deref target |
|
| stdlib.go:196:23:196:28 | implicit dereference | semmle.label | implicit dereference |
|
||||||
| stdlib.go:196:23:196:28 | target | semmle.label | target |
|
| stdlib.go:196:23:196:28 | target | semmle.label | target |
|
||||||
| stdlib.go:196:23:196:28 | target [postupdate] | semmle.label | target [postupdate] |
|
| stdlib.go:196:23:196:28 | target [postupdate] | semmle.label | target [postupdate] |
|
||||||
| stdlib.go:196:23:196:33 | selection of Path | semmle.label | selection of Path |
|
| stdlib.go:196:23:196:33 | selection of Path | semmle.label | selection of Path |
|
||||||
| stdlib.go:198:23:198:28 | target | semmle.label | target |
|
| stdlib.go:198:23:198:28 | target | semmle.label | target |
|
||||||
| stdlib.go:198:23:198:42 | call to EscapedPath | semmle.label | call to EscapedPath |
|
| stdlib.go:198:23:198:42 | call to EscapedPath | semmle.label | call to EscapedPath |
|
||||||
| stdlib.go:210:3:210:3 | implicit-deref u [postupdate] | semmle.label | implicit-deref u [postupdate] |
|
| stdlib.go:210:3:210:3 | implicit dereference [postupdate] | semmle.label | implicit dereference [postupdate] |
|
||||||
| stdlib.go:210:3:210:3 | u [postupdate] | semmle.label | u [postupdate] |
|
| stdlib.go:210:3:210:3 | u [postupdate] | semmle.label | u [postupdate] |
|
||||||
| stdlib.go:210:3:210:3 | u [postupdate] [pointer] | semmle.label | u [postupdate] [pointer] |
|
| stdlib.go:210:3:210:3 | u [postupdate] [pointer] | semmle.label | u [postupdate] [pointer] |
|
||||||
| stdlib.go:210:12:210:30 | call to FormValue | semmle.label | call to FormValue |
|
| stdlib.go:210:12:210:30 | call to FormValue | semmle.label | call to FormValue |
|
||||||
| stdlib.go:212:23:212:23 | implicit-deref u | semmle.label | implicit-deref u |
|
| stdlib.go:212:23:212:23 | implicit dereference | semmle.label | implicit dereference |
|
||||||
| stdlib.go:212:23:212:23 | u | semmle.label | u |
|
| stdlib.go:212:23:212:23 | u | semmle.label | u |
|
||||||
| stdlib.go:212:23:212:23 | u [pointer] | semmle.label | u [pointer] |
|
| stdlib.go:212:23:212:23 | u [pointer] | semmle.label | u [pointer] |
|
||||||
| stdlib.go:212:23:212:23 | u [postupdate] | semmle.label | u [postupdate] |
|
| stdlib.go:212:23:212:23 | u [postupdate] | semmle.label | u [postupdate] |
|
||||||
| stdlib.go:212:23:212:28 | selection of Path | semmle.label | selection of Path |
|
| stdlib.go:212:23:212:28 | selection of Path | semmle.label | selection of Path |
|
||||||
| stdlib.go:214:23:214:23 | u | semmle.label | u |
|
| stdlib.go:214:23:214:23 | u | semmle.label | u |
|
||||||
| stdlib.go:214:23:214:32 | call to String | semmle.label | call to String |
|
| stdlib.go:214:23:214:32 | call to String | semmle.label | call to String |
|
||||||
| stdlib.go:257:3:257:3 | implicit-deref u [postupdate] | semmle.label | implicit-deref u [postupdate] |
|
| stdlib.go:257:3:257:3 | implicit dereference [postupdate] | semmle.label | implicit dereference [postupdate] |
|
||||||
| stdlib.go:257:3:257:3 | u [postupdate] | semmle.label | u [postupdate] |
|
| stdlib.go:257:3:257:3 | u [postupdate] | semmle.label | u [postupdate] |
|
||||||
| stdlib.go:257:3:257:3 | u [postupdate] [pointer] | semmle.label | u [postupdate] [pointer] |
|
| stdlib.go:257:3:257:3 | u [postupdate] [pointer] | semmle.label | u [postupdate] [pointer] |
|
||||||
| stdlib.go:257:12:257:30 | call to FormValue | semmle.label | call to FormValue |
|
| stdlib.go:257:12:257:30 | call to FormValue | semmle.label | call to FormValue |
|
||||||
| stdlib.go:260:3:260:3 | implicit-deref u | semmle.label | implicit-deref u |
|
| stdlib.go:260:3:260:3 | implicit dereference | semmle.label | implicit dereference |
|
||||||
| stdlib.go:260:3:260:3 | u | semmle.label | u |
|
| stdlib.go:260:3:260:3 | u | semmle.label | u |
|
||||||
| stdlib.go:260:3:260:3 | u [pointer] | semmle.label | u [pointer] |
|
| stdlib.go:260:3:260:3 | u [pointer] | semmle.label | u [pointer] |
|
||||||
| stdlib.go:260:3:260:3 | u [postupdate] | semmle.label | u [postupdate] |
|
| stdlib.go:260:3:260:3 | u [postupdate] | semmle.label | u [postupdate] |
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ edges
|
|||||||
| UncontrolledAllocationSizeBad.go:11:12:11:24 | call to Query | UncontrolledAllocationSizeBad.go:13:15:13:20 | source | provenance | |
|
| UncontrolledAllocationSizeBad.go:11:12:11:24 | call to Query | UncontrolledAllocationSizeBad.go:13:15:13:20 | source | provenance | |
|
||||||
| UncontrolledAllocationSizeBad.go:13:15:13:20 | source | UncontrolledAllocationSizeBad.go:13:15:13:29 | call to Get | provenance | MaD:3 |
|
| UncontrolledAllocationSizeBad.go:13:15:13:20 | source | UncontrolledAllocationSizeBad.go:13:15:13:29 | call to Get | provenance | MaD:3 |
|
||||||
| UncontrolledAllocationSizeBad.go:13:15:13:29 | call to Get | UncontrolledAllocationSizeBad.go:14:28:14:36 | sourceStr | provenance | |
|
| UncontrolledAllocationSizeBad.go:13:15:13:29 | call to Get | UncontrolledAllocationSizeBad.go:14:28:14:36 | sourceStr | provenance | |
|
||||||
| UncontrolledAllocationSizeBad.go:14:2:14:37 | extract:0 ... := ... | UncontrolledAllocationSizeBad.go:20:27:20:30 | sink | provenance | |
|
| UncontrolledAllocationSizeBad.go:14:2:14:37 | ... := ...[0] | UncontrolledAllocationSizeBad.go:20:27:20:30 | sink | provenance | |
|
||||||
| UncontrolledAllocationSizeBad.go:14:28:14:36 | sourceStr | UncontrolledAllocationSizeBad.go:14:2:14:37 | extract:0 ... := ... | provenance | Config |
|
| UncontrolledAllocationSizeBad.go:14:28:14:36 | sourceStr | UncontrolledAllocationSizeBad.go:14:2:14:37 | ... := ...[0] | provenance | Config |
|
||||||
models
|
models
|
||||||
| 1 | Source: net/http; Request; true; URL; ; ; ; remote; manual |
|
| 1 | Source: net/http; Request; true; URL; ; ; ; remote; manual |
|
||||||
| 2 | Summary: net/url; URL; true; Query; ; ; Argument[receiver]; ReturnValue; taint; manual |
|
| 2 | Summary: net/url; URL; true; Query; ; ; Argument[receiver]; ReturnValue; taint; manual |
|
||||||
@@ -16,7 +16,7 @@ nodes
|
|||||||
| UncontrolledAllocationSizeBad.go:11:12:11:24 | call to Query | semmle.label | call to Query |
|
| UncontrolledAllocationSizeBad.go:11:12:11:24 | call to Query | semmle.label | call to Query |
|
||||||
| UncontrolledAllocationSizeBad.go:13:15:13:20 | source | semmle.label | source |
|
| UncontrolledAllocationSizeBad.go:13:15:13:20 | source | semmle.label | source |
|
||||||
| UncontrolledAllocationSizeBad.go:13:15:13:29 | call to Get | semmle.label | call to Get |
|
| UncontrolledAllocationSizeBad.go:13:15:13:29 | call to Get | semmle.label | call to Get |
|
||||||
| UncontrolledAllocationSizeBad.go:14:2:14:37 | extract:0 ... := ... | semmle.label | extract:0 ... := ... |
|
| UncontrolledAllocationSizeBad.go:14:2:14:37 | ... := ...[0] | semmle.label | ... := ...[0] |
|
||||||
| UncontrolledAllocationSizeBad.go:14:28:14:36 | sourceStr | semmle.label | sourceStr |
|
| UncontrolledAllocationSizeBad.go:14:28:14:36 | sourceStr | semmle.label | sourceStr |
|
||||||
| UncontrolledAllocationSizeBad.go:20:27:20:30 | sink | semmle.label | sink |
|
| UncontrolledAllocationSizeBad.go:20:27:20:30 | sink | semmle.label | sink |
|
||||||
subpaths
|
subpaths
|
||||||
|
|||||||
@@ -37,9 +37,9 @@ edges
|
|||||||
| tst.go:11:13:11:35 | call to FormValue | tst.go:39:11:39:29 | ...+... | provenance | Src:MaD:1 |
|
| tst.go:11:13:11:35 | call to FormValue | tst.go:39:11:39:29 | ...+... | provenance | Src:MaD:1 |
|
||||||
| tst.go:11:13:11:35 | call to FormValue | tst.go:41:11:41:40 | ...+... | provenance | Src:MaD:1 |
|
| tst.go:11:13:11:35 | call to FormValue | tst.go:41:11:41:40 | ...+... | provenance | Src:MaD:1 |
|
||||||
| tst.go:11:13:11:35 | call to FormValue | tst.go:48:11:48:18 | tainted2 | provenance | Src:MaD:1 |
|
| tst.go:11:13:11:35 | call to FormValue | tst.go:48:11:48:18 | tainted2 | provenance | Src:MaD:1 |
|
||||||
| tst.go:48:2:48:2 | implicit-deref u [postupdate] | tst.go:48:2:48:2 | u [postupdate] | provenance | |
|
| tst.go:48:2:48:2 | implicit dereference [postupdate] | tst.go:48:2:48:2 | u [postupdate] | provenance | |
|
||||||
| tst.go:48:2:48:2 | u [postupdate] | tst.go:49:11:49:11 | u | provenance | |
|
| tst.go:48:2:48:2 | u [postupdate] | tst.go:49:11:49:11 | u | provenance | |
|
||||||
| tst.go:48:11:48:18 | tainted2 | tst.go:48:2:48:2 | implicit-deref u [postupdate] | provenance | Config |
|
| tst.go:48:11:48:18 | tainted2 | tst.go:48:2:48:2 | implicit dereference [postupdate] | provenance | Config |
|
||||||
| tst.go:48:11:48:18 | tainted2 | tst.go:48:2:48:2 | u [postupdate] | provenance | Config |
|
| tst.go:48:11:48:18 | tainted2 | tst.go:48:2:48:2 | u [postupdate] | provenance | Config |
|
||||||
| tst.go:49:11:49:11 | u | tst.go:49:11:49:20 | call to String | provenance | MaD:3 |
|
| tst.go:49:11:49:11 | u | tst.go:49:11:49:20 | call to String | provenance | MaD:3 |
|
||||||
| websocket.go:60:21:60:31 | call to Referer | websocket.go:65:27:65:40 | untrustedInput | provenance | Src:MaD:2 |
|
| websocket.go:60:21:60:31 | call to Referer | websocket.go:65:27:65:40 | untrustedInput | provenance | Src:MaD:2 |
|
||||||
@@ -71,7 +71,7 @@ nodes
|
|||||||
| tst.go:37:18:37:24 | tainted | semmle.label | tainted |
|
| tst.go:37:18:37:24 | tainted | semmle.label | tainted |
|
||||||
| tst.go:39:11:39:29 | ...+... | semmle.label | ...+... |
|
| tst.go:39:11:39:29 | ...+... | semmle.label | ...+... |
|
||||||
| tst.go:41:11:41:40 | ...+... | semmle.label | ...+... |
|
| tst.go:41:11:41:40 | ...+... | semmle.label | ...+... |
|
||||||
| tst.go:48:2:48:2 | implicit-deref u [postupdate] | semmle.label | implicit-deref u [postupdate] |
|
| tst.go:48:2:48:2 | implicit dereference [postupdate] | semmle.label | implicit dereference [postupdate] |
|
||||||
| tst.go:48:2:48:2 | u [postupdate] | semmle.label | u [postupdate] |
|
| tst.go:48:2:48:2 | u [postupdate] | semmle.label | u [postupdate] |
|
||||||
| tst.go:48:11:48:18 | tainted2 | semmle.label | tainted2 |
|
| tst.go:48:11:48:18 | tainted2 | semmle.label | tainted2 |
|
||||||
| tst.go:49:11:49:11 | u | semmle.label | u |
|
| tst.go:49:11:49:11 | u | semmle.label | u |
|
||||||
|
|||||||
2
python/ql/consistency-queries/CfgConsistency.ql
Normal file
2
python/ql/consistency-queries/CfgConsistency.ql
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
import semmle.python.controlflow.internal.AstNodeImpl
|
||||||
|
import ControlFlow::Consistency
|
||||||
@@ -9,6 +9,7 @@ private import semmle.python.dataflow.new.internal.DataFlowImplSpecific
|
|||||||
private import semmle.python.dataflow.new.internal.DataFlowDispatch
|
private import semmle.python.dataflow.new.internal.DataFlowDispatch
|
||||||
private import semmle.python.dataflow.new.internal.TaintTrackingImplSpecific
|
private import semmle.python.dataflow.new.internal.TaintTrackingImplSpecific
|
||||||
private import codeql.dataflow.internal.DataFlowImplConsistency
|
private import codeql.dataflow.internal.DataFlowImplConsistency
|
||||||
|
private import semmle.python.controlflow.internal.Cfg as Cfg
|
||||||
|
|
||||||
private module Input implements InputSig<Location, PythonDataFlow> {
|
private module Input implements InputSig<Location, PythonDataFlow> {
|
||||||
private import Private
|
private import Private
|
||||||
@@ -74,7 +75,7 @@ private module Input implements InputSig<Location, PythonDataFlow> {
|
|||||||
// resolve to multiple functions), but we only make _one_ ArgumentNode for each
|
// resolve to multiple functions), but we only make _one_ ArgumentNode for each
|
||||||
// argument in the CallNode, we end up violating this consistency check in those
|
// argument in the CallNode, we end up violating this consistency check in those
|
||||||
// cases. (see `getCallArg` in DataFlowDispatch.qll)
|
// cases. (see `getCallArg` in DataFlowDispatch.qll)
|
||||||
exists(DataFlowCall other, CallNode cfgCall | other != call |
|
exists(DataFlowCall other, Cfg::CallNode cfgCall | other != call |
|
||||||
call.getNode() = cfgCall and
|
call.getNode() = cfgCall and
|
||||||
other.getNode() = cfgCall and
|
other.getNode() = cfgCall and
|
||||||
isArgumentNode(arg, call, _) and
|
isArgumentNode(arg, call, _) and
|
||||||
@@ -90,16 +91,16 @@ private module Input implements InputSig<Location, PythonDataFlow> {
|
|||||||
// allow it instead.
|
// allow it instead.
|
||||||
(
|
(
|
||||||
call.getScope() = attr.getScope() and
|
call.getScope() = attr.getScope() and
|
||||||
any(CfgNode n | n.asCfgNode() = call.getNode().(CallNode).getFunction()).getALocalSource() =
|
any(CfgNode n | n.asCfgNode() = call.getNode().(Cfg::CallNode).getFunction())
|
||||||
attr
|
.getALocalSource() = attr
|
||||||
or
|
or
|
||||||
not exists(call.getScope().(Function).getDefinition()) and
|
not exists(call.getScope().(Function).getDefinition()) and
|
||||||
call.getScope().getScope+() = attr.getScope()
|
call.getScope().getScope+() = attr.getScope()
|
||||||
) and
|
) and
|
||||||
(
|
(
|
||||||
other.getScope() = attr.getScope() and
|
other.getScope() = attr.getScope() and
|
||||||
any(CfgNode n | n.asCfgNode() = other.getNode().(CallNode).getFunction()).getALocalSource() =
|
any(CfgNode n | n.asCfgNode() = other.getNode().(Cfg::CallNode).getFunction())
|
||||||
attr
|
.getALocalSource() = attr
|
||||||
or
|
or
|
||||||
not exists(other.getScope().(Function).getDefinition()) and
|
not exists(other.getScope().(Function).getDefinition()) and
|
||||||
other.getScope().getScope+() = attr.getScope()
|
other.getScope().getScope+() = attr.getScope()
|
||||||
|
|||||||
4
python/ql/lib/change-notes/2026-05-19-add-shared-cfg.md
Normal file
4
python/ql/lib/change-notes/2026-05-19-add-shared-cfg.md
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
---
|
||||||
|
category: minorAnalysis
|
||||||
|
---
|
||||||
|
* A new Python control flow graph implementation has been added under `semmle.python.controlflow.internal.Cfg` (backed by `AstNodeImpl.qll`), built on the shared `codeql.controlflow.ControlFlowGraph` library. It is not yet used by the dataflow library or any production query; the legacy CFG in `semmle/python/Flow.qll` remains the default. The new library is exposed for tests and for upcoming migrations.
|
||||||
4
python/ql/lib/change-notes/2026-05-19-add-shared-ssa.md
Normal file
4
python/ql/lib/change-notes/2026-05-19-add-shared-ssa.md
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
---
|
||||||
|
category: minorAnalysis
|
||||||
|
---
|
||||||
|
* A new SSA adapter has been added under `semmle.python.dataflow.new.internal.SsaImpl`, built on the shared `codeql.ssa.Ssa` library and the new shared CFG (`semmle.python.controlflow.internal.Cfg`). It is not yet used by the dataflow library or any production query; the legacy ESSA SSA in `semmle/python/essa/*` remains the default. The new SSA adapter is exposed for tests and for the upcoming dataflow migration.
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
---
|
||||||
|
category: breaking
|
||||||
|
---
|
||||||
|
* The deprecated `AstNode.getAFlowNode()` and `Function.getAReturnValueFlowNode()` predicates now return nodes from the new shared CFG (`Cfg::ControlFlowNode`) rather than from the legacy CFG (`ControlFlowNode`). Callers that still rely on these deprecated APIs and feed the result into legacy-CFG-aware predicates will no longer type-check; migrate to `n.getNode() = e` (or, for return values, the explicit `Return` pattern shown in the deprecation message) to get nodes from the dataflow library's current CFG.
|
||||||
45
python/ql/lib/printCfgNew.ql
Normal file
45
python/ql/lib/printCfgNew.ql
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
/**
|
||||||
|
* @name Print CFG (New)
|
||||||
|
* @description Produces a representation of a file's Control Flow Graph
|
||||||
|
* using the new shared control flow library.
|
||||||
|
* This query is used by the VS Code extension.
|
||||||
|
* @id python/print-cfg
|
||||||
|
* @kind graph
|
||||||
|
* @tags ide-contextual-queries/print-cfg
|
||||||
|
*/
|
||||||
|
|
||||||
|
private import python as Py
|
||||||
|
import semmle.python.controlflow.internal.AstNodeImpl
|
||||||
|
|
||||||
|
external string selectedSourceFile();
|
||||||
|
|
||||||
|
private predicate selectedSourceFileAlias = selectedSourceFile/0;
|
||||||
|
|
||||||
|
external int selectedSourceLine();
|
||||||
|
|
||||||
|
private predicate selectedSourceLineAlias = selectedSourceLine/0;
|
||||||
|
|
||||||
|
external int selectedSourceColumn();
|
||||||
|
|
||||||
|
private predicate selectedSourceColumnAlias = selectedSourceColumn/0;
|
||||||
|
|
||||||
|
module ViewCfgQueryInput implements ControlFlow::ViewCfgQueryInputSig<Py::File> {
|
||||||
|
predicate selectedSourceFile = selectedSourceFileAlias/0;
|
||||||
|
|
||||||
|
predicate selectedSourceLine = selectedSourceLineAlias/0;
|
||||||
|
|
||||||
|
predicate selectedSourceColumn = selectedSourceColumnAlias/0;
|
||||||
|
|
||||||
|
predicate cfgScopeSpan(
|
||||||
|
Ast::Callable callable, Py::File file, int startLine, int startColumn, int endLine,
|
||||||
|
int endColumn
|
||||||
|
) {
|
||||||
|
exists(Py::Scope scope |
|
||||||
|
scope = callable.asScope() and
|
||||||
|
file = scope.getLocation().getFile() and
|
||||||
|
scope.getLocation().hasLocationInfo(_, startLine, startColumn, endLine, endColumn)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
import ControlFlow::ViewCfgQuery<Py::File, ViewCfgQueryInput>
|
||||||
@@ -6,8 +6,9 @@
|
|||||||
* directed and labeled; they specify how the components represented by nodes relate to each other.
|
* directed and labeled; they specify how the components represented by nodes relate to each other.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Importing python under the `py` namespace to avoid importing `CallNode` from `Flow.qll` and thereby having a naming conflict with `API::CallNode`.
|
// Importing python under the `PY` namespace to avoid pulling in `CallNode` from `Flow.qll` (via `import python`) and thereby having a naming conflict with `API::CallNode`.
|
||||||
private import python as PY
|
private import python as PY
|
||||||
|
private import semmle.python.controlflow.internal.Cfg as Cfg
|
||||||
import semmle.python.dataflow.new.DataFlow
|
import semmle.python.dataflow.new.DataFlow
|
||||||
private import semmle.python.internal.CachedStages
|
private import semmle.python.internal.CachedStages
|
||||||
|
|
||||||
@@ -282,7 +283,7 @@ module API {
|
|||||||
index = this.getIndex() and
|
index = this.getIndex() and
|
||||||
(
|
(
|
||||||
// subscripting
|
// subscripting
|
||||||
exists(PY::SubscriptNode subscript |
|
exists(Cfg::SubscriptNode subscript |
|
||||||
subscript.getObject() = this.getAValueReachableFromSource().asCfgNode() and
|
subscript.getObject() = this.getAValueReachableFromSource().asCfgNode() and
|
||||||
subscript.getIndex() = index.asSink().asCfgNode()
|
subscript.getIndex() = index.asSink().asCfgNode()
|
||||||
|
|
|
|
||||||
@@ -290,7 +291,7 @@ module API {
|
|||||||
subscript = result.asSource().asCfgNode()
|
subscript = result.asSource().asCfgNode()
|
||||||
or
|
or
|
||||||
// writing
|
// writing
|
||||||
subscript.(PY::DefinitionNode).getValue() = result.asSink().asCfgNode()
|
subscript.(Cfg::DefinitionNode).getValue() = result.asSink().asCfgNode()
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
// dictionary literals
|
// dictionary literals
|
||||||
@@ -684,7 +685,7 @@ module API {
|
|||||||
* Ignores relative imports, such as `from ..foo.bar import baz`.
|
* Ignores relative imports, such as `from ..foo.bar import baz`.
|
||||||
*/
|
*/
|
||||||
private predicate imports(DataFlow::CfgNode imp, string name) {
|
private predicate imports(DataFlow::CfgNode imp, string name) {
|
||||||
exists(PY::ImportExprNode iexpr |
|
exists(Cfg::ImportExprNode iexpr |
|
||||||
imp.getNode() = iexpr and
|
imp.getNode() = iexpr and
|
||||||
not iexpr.getNode().isRelative() and
|
not iexpr.getNode().isRelative() and
|
||||||
name = iexpr.getNode().getImportedModuleName()
|
name = iexpr.getNode().getImportedModuleName()
|
||||||
@@ -775,7 +776,7 @@ module API {
|
|||||||
// list literals, from `x` to `[x]`
|
// list literals, from `x` to `[x]`
|
||||||
// TODO: once convenient, this should be done at a higher level than the AST,
|
// TODO: once convenient, this should be done at a higher level than the AST,
|
||||||
// at least at the CFG layer, to take splitting into account.
|
// at least at the CFG layer, to take splitting into account.
|
||||||
// Also consider `SequenceNode for generality.
|
// Also consider `Cfg::SequenceNode` for generality.
|
||||||
exists(PY::List list | list = pred.(DataFlow::ExprNode).getNode().getNode() |
|
exists(PY::List list | list = pred.(DataFlow::ExprNode).getNode().getNode() |
|
||||||
rhs.(DataFlow::ExprNode).getNode().getNode() = list.getAnElt() and
|
rhs.(DataFlow::ExprNode).getNode().getNode() = list.getAnElt() and
|
||||||
lbl = Label::subscript()
|
lbl = Label::subscript()
|
||||||
@@ -805,7 +806,7 @@ module API {
|
|||||||
subscript = trackUseNode(src).getSubscript(index)
|
subscript = trackUseNode(src).getSubscript(index)
|
||||||
|
|
|
|
||||||
// from `x` to a definition of `x[...]`
|
// from `x` to a definition of `x[...]`
|
||||||
rhs.asCfgNode() = subscript.asCfgNode().(PY::DefinitionNode).getValue() and
|
rhs.asCfgNode() = subscript.asCfgNode().(Cfg::DefinitionNode).getValue() and
|
||||||
lbl = Label::subscript()
|
lbl = Label::subscript()
|
||||||
or
|
or
|
||||||
// from `x` to `"key"` in `x["key"]`
|
// from `x` to `"key"` in `x["key"]`
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ module;
|
|||||||
|
|
||||||
import python
|
import python
|
||||||
private import semmle.python.internal.CachedStages
|
private import semmle.python.internal.CachedStages
|
||||||
|
private import semmle.python.controlflow.internal.Cfg as Cfg
|
||||||
|
|
||||||
/** A syntactic node (Class, Function, Module, Expr, Stmt or Comprehension) corresponding to a flow node */
|
/** A syntactic node (Class, Function, Module, Expr, Stmt or Comprehension) corresponding to a flow node */
|
||||||
abstract class AstNode extends AstNode_ {
|
abstract class AstNode extends AstNode_ {
|
||||||
@@ -19,17 +20,16 @@ abstract class AstNode extends AstNode_ {
|
|||||||
/**
|
/**
|
||||||
* DEPRECATED: use `ControlFlowNode.getNode()` from the other direction instead;
|
* DEPRECATED: use `ControlFlowNode.getNode()` from the other direction instead;
|
||||||
* that is, replace `e.getAFlowNode() = n` with `n.getNode() = e`. This API is
|
* that is, replace `e.getAFlowNode() = n` with `n.getNode() = e`. This API is
|
||||||
* being removed to untangle the AST and CFG hierarchies in preparation for
|
* being removed to untangle the AST and CFG hierarchies.
|
||||||
* migrating the dataflow library off the legacy CFG.
|
|
||||||
*
|
*
|
||||||
* Gets a flow node corresponding directly to this node.
|
* Gets a flow node corresponding directly to this node, from the new
|
||||||
* NOTE: For some statements and other purely syntactic elements,
|
* (shared) CFG. NOTE: For some statements and other purely syntactic
|
||||||
* there may not be a `ControlFlowNode`.
|
* elements, there may not be a `ControlFlowNode`.
|
||||||
*/
|
*/
|
||||||
cached
|
cached
|
||||||
deprecated ControlFlowNode getAFlowNode() {
|
deprecated Cfg::ControlFlowNode getAFlowNode() {
|
||||||
Stages::AST::ref() and
|
Stages::AST::ref() and
|
||||||
py_flow_bb_node(result, this, _, _)
|
result.getNode() = this
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Gets the location for this AST node */
|
/** Gets the location for this AST node */
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
private import python
|
private import python
|
||||||
|
private import semmle.python.controlflow.internal.Cfg as Cfg
|
||||||
private import semmle.python.dataflow.new.DataFlow
|
private import semmle.python.dataflow.new.DataFlow
|
||||||
private import semmle.python.dataflow.new.internal.DataFlowImplSpecific
|
private import semmle.python.dataflow.new.internal.DataFlowImplSpecific
|
||||||
private import semmle.python.dataflow.new.RemoteFlowSources
|
private import semmle.python.dataflow.new.RemoteFlowSources
|
||||||
@@ -214,7 +215,7 @@ module Path {
|
|||||||
SafeAccessCheck() { this = DataFlow::BarrierGuard<safeAccessCheck/3>::getABarrierNode() }
|
SafeAccessCheck() { this = DataFlow::BarrierGuard<safeAccessCheck/3>::getABarrierNode() }
|
||||||
}
|
}
|
||||||
|
|
||||||
private predicate safeAccessCheck(DataFlow::GuardNode g, ControlFlowNode node, boolean branch) {
|
private predicate safeAccessCheck(DataFlow::GuardNode g, Cfg::ControlFlowNode node, boolean branch) {
|
||||||
g.(SafeAccessCheck::Range).checks(node, branch)
|
g.(SafeAccessCheck::Range).checks(node, branch)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -223,7 +224,7 @@ module Path {
|
|||||||
/** A data-flow node that checks that a path is safe to access in some way, for example by having a controlled prefix. */
|
/** A data-flow node that checks that a path is safe to access in some way, for example by having a controlled prefix. */
|
||||||
abstract class Range extends DataFlow::GuardNode {
|
abstract class Range extends DataFlow::GuardNode {
|
||||||
/** Holds if this guard validates `node` upon evaluating to `branch`. */
|
/** Holds if this guard validates `node` upon evaluating to `branch`. */
|
||||||
abstract predicate checks(ControlFlowNode node, boolean branch);
|
abstract predicate checks(Cfg::ControlFlowNode node, boolean branch);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ module;
|
|||||||
|
|
||||||
private import python
|
private import python
|
||||||
private import semmle.python.internal.CachedStages
|
private import semmle.python.internal.CachedStages
|
||||||
|
private import semmle.python.controlflow.internal.Cfg as Cfg
|
||||||
|
|
||||||
/** An expression */
|
/** An expression */
|
||||||
class Expr extends Expr_, AstNode {
|
class Expr extends Expr_, AstNode {
|
||||||
@@ -70,7 +71,7 @@ class Attribute extends Attribute_ {
|
|||||||
/* syntax: Expr.name */
|
/* syntax: Expr.name */
|
||||||
override Expr getASubExpression() { result = this.getObject() }
|
override Expr getASubExpression() { result = this.getObject() }
|
||||||
|
|
||||||
deprecated override AttrNode getAFlowNode() { result = super.getAFlowNode() }
|
deprecated override Cfg::AttrNode getAFlowNode() { result = super.getAFlowNode() }
|
||||||
|
|
||||||
/** Gets the name of this attribute. That is the `name` in `obj.name` */
|
/** Gets the name of this attribute. That is the `name` in `obj.name` */
|
||||||
string getName() { result = Attribute_.super.getAttr() }
|
string getName() { result = Attribute_.super.getAttr() }
|
||||||
@@ -99,7 +100,7 @@ class Subscript extends Subscript_ {
|
|||||||
|
|
||||||
Expr getObject() { result = Subscript_.super.getValue() }
|
Expr getObject() { result = Subscript_.super.getValue() }
|
||||||
|
|
||||||
deprecated override SubscriptNode getAFlowNode() { result = super.getAFlowNode() }
|
deprecated override Cfg::SubscriptNode getAFlowNode() { result = super.getAFlowNode() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/** A call expression, such as `func(...)` */
|
/** A call expression, such as `func(...)` */
|
||||||
@@ -115,7 +116,7 @@ class Call extends Call_ {
|
|||||||
|
|
||||||
override string toString() { result = this.getFunc().toString() + "()" }
|
override string toString() { result = this.getFunc().toString() + "()" }
|
||||||
|
|
||||||
deprecated override CallNode getAFlowNode() { result = super.getAFlowNode() }
|
deprecated override Cfg::CallNode getAFlowNode() { result = super.getAFlowNode() }
|
||||||
|
|
||||||
/** Gets a tuple (*) argument of this call. */
|
/** Gets a tuple (*) argument of this call. */
|
||||||
Expr getStarargs() { result = this.getAPositionalArg().(Starred).getValue() }
|
Expr getStarargs() { result = this.getAPositionalArg().(Starred).getValue() }
|
||||||
@@ -203,7 +204,7 @@ class IfExp extends IfExp_ {
|
|||||||
result = this.getTest() or result = this.getBody() or result = this.getOrelse()
|
result = this.getTest() or result = this.getBody() or result = this.getOrelse()
|
||||||
}
|
}
|
||||||
|
|
||||||
deprecated override IfExprNode getAFlowNode() { result = super.getAFlowNode() }
|
deprecated override Cfg::IfExprNode getAFlowNode() { result = super.getAFlowNode() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/** A starred expression, such as the `*rest` in the assignment `first, *rest = seq` */
|
/** A starred expression, such as the `*rest` in the assignment `first, *rest = seq` */
|
||||||
@@ -413,7 +414,7 @@ class PlaceHolder extends PlaceHolder_ {
|
|||||||
|
|
||||||
override string toString() { result = "$" + this.getId() }
|
override string toString() { result = "$" + this.getId() }
|
||||||
|
|
||||||
deprecated override NameNode getAFlowNode() { result = super.getAFlowNode() }
|
deprecated override Cfg::NameNode getAFlowNode() { result = super.getAFlowNode() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/** A tuple expression such as `( 1, 3, 5, 7, 9 )` */
|
/** A tuple expression such as `( 1, 3, 5, 7, 9 )` */
|
||||||
@@ -480,7 +481,7 @@ class Name extends Name_ {
|
|||||||
|
|
||||||
override string toString() { result = this.getId() }
|
override string toString() { result = this.getId() }
|
||||||
|
|
||||||
deprecated override NameNode getAFlowNode() { result = super.getAFlowNode() }
|
deprecated override Cfg::NameNode getAFlowNode() { result = super.getAFlowNode() }
|
||||||
|
|
||||||
override predicate isArtificial() {
|
override predicate isArtificial() {
|
||||||
/* Artificial variable names in comprehensions all start with "." */
|
/* Artificial variable names in comprehensions all start with "." */
|
||||||
@@ -587,7 +588,7 @@ abstract class NameConstant extends Name, ImmutableLiteral {
|
|||||||
|
|
||||||
override predicate isConstant() { any() }
|
override predicate isConstant() { any() }
|
||||||
|
|
||||||
deprecated override NameConstantNode getAFlowNode() { result = Name.super.getAFlowNode() }
|
deprecated override Cfg::NameConstantNode getAFlowNode() { result = Name.super.getAFlowNode() }
|
||||||
|
|
||||||
override predicate isArtificial() { none() }
|
override predicate isArtificial() { none() }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
overlay[local]
|
overlay[local]
|
||||||
module;
|
module;
|
||||||
|
|
||||||
import python
|
import python as Py
|
||||||
private import semmle.python.internal.CachedStages
|
private import semmle.python.internal.CachedStages
|
||||||
private import codeql.controlflow.BasicBlock as BB
|
private import codeql.controlflow.BasicBlock as BB
|
||||||
|
|
||||||
@@ -17,7 +17,7 @@ private import codeql.controlflow.BasicBlock as BB
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
private predicate augstore(ControlFlowNode load, ControlFlowNode store) {
|
private predicate augstore(ControlFlowNode load, ControlFlowNode store) {
|
||||||
exists(Expr load_store | exists(AugAssign aa | aa.getTarget() = load_store) |
|
exists(Py::Expr load_store | exists(Py::AugAssign aa | aa.getTarget() = load_store) |
|
||||||
toAst(load) = load_store and
|
toAst(load) = load_store and
|
||||||
toAst(store) = load_store and
|
toAst(store) = load_store and
|
||||||
load.strictlyDominates(store)
|
load.strictlyDominates(store)
|
||||||
@@ -25,7 +25,7 @@ private predicate augstore(ControlFlowNode load, ControlFlowNode store) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** A non-dispatched getNode() to avoid negative recursion issues */
|
/** A non-dispatched getNode() to avoid negative recursion issues */
|
||||||
private AstNode toAst(ControlFlowNode n) { py_flow_bb_node(n, result, _, _) }
|
private Py::AstNode toAst(ControlFlowNode n) { py_flow_bb_node(n, result, _, _) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A control flow node. Control flow nodes have a many-to-one relation with syntactic nodes,
|
* A control flow node. Control flow nodes have a many-to-one relation with syntactic nodes,
|
||||||
@@ -35,19 +35,19 @@ private AstNode toAst(ControlFlowNode n) { py_flow_bb_node(n, result, _, _) }
|
|||||||
class ControlFlowNode extends @py_flow_node {
|
class ControlFlowNode extends @py_flow_node {
|
||||||
/** Whether this control flow node is a load (including those in augmented assignments) */
|
/** Whether this control flow node is a load (including those in augmented assignments) */
|
||||||
predicate isLoad() {
|
predicate isLoad() {
|
||||||
exists(Expr e | e = toAst(this) | py_expr_contexts(_, 3, e) and not augstore(_, this))
|
exists(Py::Expr e | e = toAst(this) | py_expr_contexts(_, 3, e) and not augstore(_, this))
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Whether this control flow node is a store (including those in augmented assignments) */
|
/** Whether this control flow node is a store (including those in augmented assignments) */
|
||||||
predicate isStore() {
|
predicate isStore() {
|
||||||
exists(Expr e | e = toAst(this) | py_expr_contexts(_, 5, e) or augstore(_, this))
|
exists(Py::Expr e | e = toAst(this) | py_expr_contexts(_, 5, e) or augstore(_, this))
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Whether this control flow node is a delete */
|
/** Whether this control flow node is a delete */
|
||||||
predicate isDelete() { exists(Expr e | e = toAst(this) | py_expr_contexts(_, 2, e)) }
|
predicate isDelete() { exists(Py::Expr e | e = toAst(this) | py_expr_contexts(_, 2, e)) }
|
||||||
|
|
||||||
/** Whether this control flow node is a parameter */
|
/** Whether this control flow node is a parameter */
|
||||||
predicate isParameter() { exists(Expr e | e = toAst(this) | py_expr_contexts(_, 4, e)) }
|
predicate isParameter() { exists(Py::Expr e | e = toAst(this) | py_expr_contexts(_, 4, e)) }
|
||||||
|
|
||||||
/** Whether this control flow node is a store in an augmented assignment */
|
/** Whether this control flow node is a store in an augmented assignment */
|
||||||
predicate isAugStore() { augstore(_, this) }
|
predicate isAugStore() { augstore(_, this) }
|
||||||
@@ -57,61 +57,61 @@ class ControlFlowNode extends @py_flow_node {
|
|||||||
|
|
||||||
/** Whether this flow node corresponds to a literal */
|
/** Whether this flow node corresponds to a literal */
|
||||||
predicate isLiteral() {
|
predicate isLiteral() {
|
||||||
toAst(this) instanceof Bytes
|
toAst(this) instanceof Py::Bytes
|
||||||
or
|
or
|
||||||
toAst(this) instanceof Dict
|
toAst(this) instanceof Py::Dict
|
||||||
or
|
or
|
||||||
toAst(this) instanceof DictComp
|
toAst(this) instanceof Py::DictComp
|
||||||
or
|
or
|
||||||
toAst(this) instanceof Set
|
toAst(this) instanceof Py::Set
|
||||||
or
|
or
|
||||||
toAst(this) instanceof SetComp
|
toAst(this) instanceof Py::SetComp
|
||||||
or
|
or
|
||||||
toAst(this) instanceof Ellipsis
|
toAst(this) instanceof Py::Ellipsis
|
||||||
or
|
or
|
||||||
toAst(this) instanceof GeneratorExp
|
toAst(this) instanceof Py::GeneratorExp
|
||||||
or
|
or
|
||||||
toAst(this) instanceof Lambda
|
toAst(this) instanceof Py::Lambda
|
||||||
or
|
or
|
||||||
toAst(this) instanceof ListComp
|
toAst(this) instanceof Py::ListComp
|
||||||
or
|
or
|
||||||
toAst(this) instanceof List
|
toAst(this) instanceof Py::List
|
||||||
or
|
or
|
||||||
toAst(this) instanceof Num
|
toAst(this) instanceof Py::Num
|
||||||
or
|
or
|
||||||
toAst(this) instanceof Tuple
|
toAst(this) instanceof Py::Tuple
|
||||||
or
|
or
|
||||||
toAst(this) instanceof Unicode
|
toAst(this) instanceof Py::Unicode
|
||||||
or
|
or
|
||||||
toAst(this) instanceof NameConstant
|
toAst(this) instanceof Py::NameConstant
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Whether this flow node corresponds to an attribute expression */
|
/** Whether this flow node corresponds to an attribute expression */
|
||||||
predicate isAttribute() { toAst(this) instanceof Attribute }
|
predicate isAttribute() { toAst(this) instanceof Py::Attribute }
|
||||||
|
|
||||||
/** Whether this flow node corresponds to an subscript expression */
|
/** Whether this flow node corresponds to an subscript expression */
|
||||||
predicate isSubscript() { toAst(this) instanceof Subscript }
|
predicate isSubscript() { toAst(this) instanceof Py::Subscript }
|
||||||
|
|
||||||
/** Whether this flow node corresponds to an import member */
|
/** Whether this flow node corresponds to an import member */
|
||||||
predicate isImportMember() { toAst(this) instanceof ImportMember }
|
predicate isImportMember() { toAst(this) instanceof Py::ImportMember }
|
||||||
|
|
||||||
/** Whether this flow node corresponds to a call */
|
/** Whether this flow node corresponds to a call */
|
||||||
predicate isCall() { toAst(this) instanceof Call }
|
predicate isCall() { toAst(this) instanceof Py::Call }
|
||||||
|
|
||||||
/** Whether this flow node is the first in a module */
|
/** Whether this flow node is the first in a module */
|
||||||
predicate isModuleEntry() { this.isEntryNode() and toAst(this) instanceof Module }
|
predicate isModuleEntry() { this.isEntryNode() and toAst(this) instanceof Py::Module }
|
||||||
|
|
||||||
/** Whether this flow node corresponds to an import */
|
/** Whether this flow node corresponds to an import */
|
||||||
predicate isImport() { toAst(this) instanceof ImportExpr }
|
predicate isImport() { toAst(this) instanceof Py::ImportExpr }
|
||||||
|
|
||||||
/** Whether this flow node corresponds to a conditional expression */
|
/** Whether this flow node corresponds to a conditional expression */
|
||||||
predicate isIfExp() { toAst(this) instanceof IfExp }
|
predicate isIfExp() { toAst(this) instanceof Py::IfExp }
|
||||||
|
|
||||||
/** Whether this flow node corresponds to a function definition expression */
|
/** Whether this flow node corresponds to a function definition expression */
|
||||||
predicate isFunction() { toAst(this) instanceof FunctionExpr }
|
predicate isFunction() { toAst(this) instanceof Py::FunctionExpr }
|
||||||
|
|
||||||
/** Whether this flow node corresponds to a class definition expression */
|
/** Whether this flow node corresponds to a class definition expression */
|
||||||
predicate isClass() { toAst(this) instanceof ClassExpr }
|
predicate isClass() { toAst(this) instanceof Py::ClassExpr }
|
||||||
|
|
||||||
/** Gets a predecessor of this flow node */
|
/** Gets a predecessor of this flow node */
|
||||||
ControlFlowNode getAPredecessor() { this = result.getASuccessor() }
|
ControlFlowNode getAPredecessor() { this = result.getASuccessor() }
|
||||||
@@ -123,25 +123,25 @@ class ControlFlowNode extends @py_flow_node {
|
|||||||
ControlFlowNode getImmediateDominator() { py_idoms(this, result) }
|
ControlFlowNode getImmediateDominator() { py_idoms(this, result) }
|
||||||
|
|
||||||
/** Gets the syntactic element corresponding to this flow node */
|
/** Gets the syntactic element corresponding to this flow node */
|
||||||
AstNode getNode() { py_flow_bb_node(this, result, _, _) }
|
Py::AstNode getNode() { py_flow_bb_node(this, result, _, _) }
|
||||||
|
|
||||||
/** Gets a textual representation of this element. */
|
/** Gets a textual representation of this element. */
|
||||||
cached
|
cached
|
||||||
string toString() {
|
string toString() {
|
||||||
Stages::AST::ref() and
|
Stages::AST::ref() and
|
||||||
// Since modules can have ambigous names, entry nodes can too, if we do not collate them.
|
// Since modules can have ambigous names, entry nodes can too, if we do not collate them.
|
||||||
exists(Scope s | s.getEntryNode() = this |
|
exists(Py::Scope s | s.getEntryNode() = this |
|
||||||
result = "Entry node for " + concat( | | s.toString(), ",")
|
result = "Entry node for " + concat( | | s.toString(), ",")
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
exists(Scope s | s.getANormalExit() = this | result = "Exit node for " + s.toString())
|
exists(Py::Scope s | s.getANormalExit() = this | result = "Exit node for " + s.toString())
|
||||||
or
|
or
|
||||||
not exists(Scope s | s.getEntryNode() = this or s.getANormalExit() = this) and
|
not exists(Py::Scope s | s.getEntryNode() = this or s.getANormalExit() = this) and
|
||||||
result = "ControlFlowNode for " + this.getNode().toString()
|
result = "ControlFlowNode for " + this.getNode().toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Gets the location of this ControlFlowNode */
|
/** Gets the location of this ControlFlowNode */
|
||||||
Location getLocation() { result = this.getNode().getLocation() }
|
Py::Location getLocation() { result = this.getNode().getLocation() }
|
||||||
|
|
||||||
/** Whether this flow node is the first in its scope */
|
/** Whether this flow node is the first in its scope */
|
||||||
predicate isEntryNode() { py_scope_flow(this, _, -1) }
|
predicate isEntryNode() { py_scope_flow(this, _, -1) }
|
||||||
@@ -151,9 +151,9 @@ class ControlFlowNode extends @py_flow_node {
|
|||||||
|
|
||||||
/** Gets the scope containing this flow node */
|
/** Gets the scope containing this flow node */
|
||||||
cached
|
cached
|
||||||
Scope getScope() {
|
Py::Scope getScope() {
|
||||||
Stages::AST::ref() and
|
Stages::AST::ref() and
|
||||||
if this.getNode() instanceof Scope
|
if this.getNode() instanceof Py::Scope
|
||||||
then
|
then
|
||||||
/* Entry or exit node */
|
/* Entry or exit node */
|
||||||
result = this.getNode()
|
result = this.getNode()
|
||||||
@@ -161,7 +161,7 @@ class ControlFlowNode extends @py_flow_node {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Gets the enclosing module */
|
/** Gets the enclosing module */
|
||||||
Module getEnclosingModule() { result = this.getScope().getEnclosingModule() }
|
Py::Module getEnclosingModule() { result = this.getScope().getEnclosingModule() }
|
||||||
|
|
||||||
/** Gets a successor for this node if the relevant condition is True. */
|
/** Gets a successor for this node if the relevant condition is True. */
|
||||||
ControlFlowNode getATrueSuccessor() {
|
ControlFlowNode getATrueSuccessor() {
|
||||||
@@ -188,7 +188,7 @@ class ControlFlowNode extends @py_flow_node {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Whether the scope may be exited as a result of this node raising an exception */
|
/** Whether the scope may be exited as a result of this node raising an exception */
|
||||||
predicate isExceptionalExit(Scope s) { py_scope_flow(this, s, 1) }
|
predicate isExceptionalExit(Py::Scope s) { py_scope_flow(this, s, 1) }
|
||||||
|
|
||||||
/** Whether this node is a normal (non-exceptional) exit */
|
/** Whether this node is a normal (non-exceptional) exit */
|
||||||
predicate isNormalExit() { py_scope_flow(this, _, 0) or py_scope_flow(this, _, 2) }
|
predicate isNormalExit() { py_scope_flow(this, _, 0) or py_scope_flow(this, _, 2) }
|
||||||
@@ -236,7 +236,7 @@ class ControlFlowNode extends @py_flow_node {
|
|||||||
/* join-ordering helper for `getAChild() */
|
/* join-ordering helper for `getAChild() */
|
||||||
pragma[noinline]
|
pragma[noinline]
|
||||||
private ControlFlowNode getExprChild(BasicBlock dom) {
|
private ControlFlowNode getExprChild(BasicBlock dom) {
|
||||||
this.getNode().(Expr).getAChildNode() = result.getNode() and
|
this.getNode().(Py::Expr).getAChildNode() = result.getNode() and
|
||||||
result.getBasicBlock().dominates(dom) and
|
result.getBasicBlock().dominates(dom) and
|
||||||
not this instanceof UnaryExprNode
|
not this instanceof UnaryExprNode
|
||||||
}
|
}
|
||||||
@@ -249,16 +249,16 @@ class ControlFlowNode extends @py_flow_node {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
private class AnyNode extends ControlFlowNode {
|
private class AnyNode extends ControlFlowNode {
|
||||||
override AstNode getNode() { result = super.getNode() }
|
override Py::AstNode getNode() { result = super.getNode() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/** A control flow node corresponding to a call expression, such as `func(...)` */
|
/** A control flow node corresponding to a call expression, such as `func(...)` */
|
||||||
class CallNode extends ControlFlowNode {
|
class CallNode extends ControlFlowNode {
|
||||||
CallNode() { toAst(this) instanceof Call }
|
CallNode() { toAst(this) instanceof Py::Call }
|
||||||
|
|
||||||
/** Gets the flow node corresponding to the function expression for the call corresponding to this flow node */
|
/** Gets the flow node corresponding to the function expression for the call corresponding to this flow node */
|
||||||
ControlFlowNode getFunction() {
|
ControlFlowNode getFunction() {
|
||||||
exists(Call c |
|
exists(Py::Call c |
|
||||||
this.getNode() = c and
|
this.getNode() = c and
|
||||||
c.getFunc() = result.getNode() and
|
c.getFunc() = result.getNode() and
|
||||||
result.getBasicBlock().dominates(this.getBasicBlock())
|
result.getBasicBlock().dominates(this.getBasicBlock())
|
||||||
@@ -267,7 +267,7 @@ class CallNode extends ControlFlowNode {
|
|||||||
|
|
||||||
/** Gets the flow node corresponding to the n'th positional argument of the call corresponding to this flow node */
|
/** Gets the flow node corresponding to the n'th positional argument of the call corresponding to this flow node */
|
||||||
ControlFlowNode getArg(int n) {
|
ControlFlowNode getArg(int n) {
|
||||||
exists(Call c |
|
exists(Py::Call c |
|
||||||
this.getNode() = c and
|
this.getNode() = c and
|
||||||
c.getArg(n) = result.getNode() and
|
c.getArg(n) = result.getNode() and
|
||||||
result.getBasicBlock().dominates(this.getBasicBlock())
|
result.getBasicBlock().dominates(this.getBasicBlock())
|
||||||
@@ -276,7 +276,7 @@ class CallNode extends ControlFlowNode {
|
|||||||
|
|
||||||
/** Gets the flow node corresponding to the named argument of the call corresponding to this flow node */
|
/** Gets the flow node corresponding to the named argument of the call corresponding to this flow node */
|
||||||
ControlFlowNode getArgByName(string name) {
|
ControlFlowNode getArgByName(string name) {
|
||||||
exists(Call c, Keyword k |
|
exists(Py::Call c, Py::Keyword k |
|
||||||
this.getNode() = c and
|
this.getNode() = c and
|
||||||
k = c.getANamedArg() and
|
k = c.getANamedArg() and
|
||||||
k.getValue() = result.getNode() and
|
k.getValue() = result.getNode() and
|
||||||
@@ -292,7 +292,7 @@ class CallNode extends ControlFlowNode {
|
|||||||
result = this.getArgByName(_)
|
result = this.getArgByName(_)
|
||||||
}
|
}
|
||||||
|
|
||||||
override Call getNode() { result = super.getNode() }
|
override Py::Call getNode() { result = super.getNode() }
|
||||||
|
|
||||||
predicate isDecoratorCall() {
|
predicate isDecoratorCall() {
|
||||||
this.isClassDecoratorCall()
|
this.isClassDecoratorCall()
|
||||||
@@ -301,11 +301,11 @@ class CallNode extends ControlFlowNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
predicate isClassDecoratorCall() {
|
predicate isClassDecoratorCall() {
|
||||||
exists(ClassExpr cls | this.getNode() = cls.getADecoratorCall())
|
exists(Py::ClassExpr cls | this.getNode() = cls.getADecoratorCall())
|
||||||
}
|
}
|
||||||
|
|
||||||
predicate isFunctionDecoratorCall() {
|
predicate isFunctionDecoratorCall() {
|
||||||
exists(FunctionExpr func | this.getNode() = func.getADecoratorCall())
|
exists(Py::FunctionExpr func | this.getNode() = func.getADecoratorCall())
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Gets the first tuple (*) argument of this call, if any. */
|
/** Gets the first tuple (*) argument of this call, if any. */
|
||||||
@@ -323,11 +323,11 @@ class CallNode extends ControlFlowNode {
|
|||||||
|
|
||||||
/** A control flow corresponding to an attribute expression, such as `value.attr` */
|
/** A control flow corresponding to an attribute expression, such as `value.attr` */
|
||||||
class AttrNode extends ControlFlowNode {
|
class AttrNode extends ControlFlowNode {
|
||||||
AttrNode() { toAst(this) instanceof Attribute }
|
AttrNode() { toAst(this) instanceof Py::Attribute }
|
||||||
|
|
||||||
/** Gets the flow node corresponding to the object of the attribute expression corresponding to this flow node */
|
/** Gets the flow node corresponding to the object of the attribute expression corresponding to this flow node */
|
||||||
ControlFlowNode getObject() {
|
ControlFlowNode getObject() {
|
||||||
exists(Attribute a |
|
exists(Py::Attribute a |
|
||||||
this.getNode() = a and
|
this.getNode() = a and
|
||||||
a.getObject() = result.getNode() and
|
a.getObject() = result.getNode() and
|
||||||
result.getBasicBlock().dominates(this.getBasicBlock())
|
result.getBasicBlock().dominates(this.getBasicBlock())
|
||||||
@@ -339,7 +339,7 @@ class AttrNode extends ControlFlowNode {
|
|||||||
* with the matching name
|
* with the matching name
|
||||||
*/
|
*/
|
||||||
ControlFlowNode getObject(string name) {
|
ControlFlowNode getObject(string name) {
|
||||||
exists(Attribute a |
|
exists(Py::Attribute a |
|
||||||
this.getNode() = a and
|
this.getNode() = a and
|
||||||
a.getObject() = result.getNode() and
|
a.getObject() = result.getNode() and
|
||||||
a.getName() = name and
|
a.getName() = name and
|
||||||
@@ -348,57 +348,57 @@ class AttrNode extends ControlFlowNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Gets the attribute name of the attribute expression corresponding to this flow node */
|
/** Gets the attribute name of the attribute expression corresponding to this flow node */
|
||||||
string getName() { exists(Attribute a | this.getNode() = a and a.getName() = result) }
|
string getName() { exists(Py::Attribute a | this.getNode() = a and a.getName() = result) }
|
||||||
|
|
||||||
override Attribute getNode() { result = super.getNode() }
|
override Py::Attribute getNode() { result = super.getNode() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/** A control flow node corresponding to a `from ... import ...` expression */
|
/** A control flow node corresponding to a `from ... import ...` expression */
|
||||||
class ImportMemberNode extends ControlFlowNode {
|
class ImportMemberNode extends ControlFlowNode {
|
||||||
ImportMemberNode() { toAst(this) instanceof ImportMember }
|
ImportMemberNode() { toAst(this) instanceof Py::ImportMember }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the flow node corresponding to the module in the import-member expression corresponding to this flow node,
|
* Gets the flow node corresponding to the module in the import-member expression corresponding to this flow node,
|
||||||
* with the matching name
|
* with the matching name
|
||||||
*/
|
*/
|
||||||
ControlFlowNode getModule(string name) {
|
ControlFlowNode getModule(string name) {
|
||||||
exists(ImportMember i | this.getNode() = i and i.getModule() = result.getNode() |
|
exists(Py::ImportMember i | this.getNode() = i and i.getModule() = result.getNode() |
|
||||||
i.getName() = name and
|
i.getName() = name and
|
||||||
result.getBasicBlock().dominates(this.getBasicBlock())
|
result.getBasicBlock().dominates(this.getBasicBlock())
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override ImportMember getNode() { result = super.getNode() }
|
override Py::ImportMember getNode() { result = super.getNode() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/** A control flow node corresponding to an artificial expression representing an import */
|
/** A control flow node corresponding to an artificial expression representing an import */
|
||||||
class ImportExprNode extends ControlFlowNode {
|
class ImportExprNode extends ControlFlowNode {
|
||||||
ImportExprNode() { toAst(this) instanceof ImportExpr }
|
ImportExprNode() { toAst(this) instanceof Py::ImportExpr }
|
||||||
|
|
||||||
override ImportExpr getNode() { result = super.getNode() }
|
override Py::ImportExpr getNode() { result = super.getNode() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/** A control flow node corresponding to a `from ... import *` statement */
|
/** A control flow node corresponding to a `from ... import *` statement */
|
||||||
class ImportStarNode extends ControlFlowNode {
|
class ImportStarNode extends ControlFlowNode {
|
||||||
ImportStarNode() { toAst(this) instanceof ImportStar }
|
ImportStarNode() { toAst(this) instanceof Py::ImportStar }
|
||||||
|
|
||||||
/** Gets the flow node corresponding to the module in the import-star corresponding to this flow node */
|
/** Gets the flow node corresponding to the module in the import-star corresponding to this flow node */
|
||||||
ControlFlowNode getModule() {
|
ControlFlowNode getModule() {
|
||||||
exists(ImportStar i | this.getNode() = i and i.getModuleExpr() = result.getNode() |
|
exists(Py::ImportStar i | this.getNode() = i and i.getModuleExpr() = result.getNode() |
|
||||||
result.getBasicBlock().dominates(this.getBasicBlock())
|
result.getBasicBlock().dominates(this.getBasicBlock())
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override ImportStar getNode() { result = super.getNode() }
|
override Py::ImportStar getNode() { result = super.getNode() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/** A control flow node corresponding to a subscript expression, such as `value[slice]` */
|
/** A control flow node corresponding to a subscript expression, such as `value[slice]` */
|
||||||
class SubscriptNode extends ControlFlowNode {
|
class SubscriptNode extends ControlFlowNode {
|
||||||
SubscriptNode() { toAst(this) instanceof Subscript }
|
SubscriptNode() { toAst(this) instanceof Py::Subscript }
|
||||||
|
|
||||||
/** flow node corresponding to the value of the sequence in a subscript operation */
|
/** flow node corresponding to the value of the sequence in a subscript operation */
|
||||||
ControlFlowNode getObject() {
|
ControlFlowNode getObject() {
|
||||||
exists(Subscript s |
|
exists(Py::Subscript s |
|
||||||
this.getNode() = s and
|
this.getNode() = s and
|
||||||
s.getObject() = result.getNode() and
|
s.getObject() = result.getNode() and
|
||||||
result.getBasicBlock().dominates(this.getBasicBlock())
|
result.getBasicBlock().dominates(this.getBasicBlock())
|
||||||
@@ -407,23 +407,23 @@ class SubscriptNode extends ControlFlowNode {
|
|||||||
|
|
||||||
/** flow node corresponding to the index in a subscript operation */
|
/** flow node corresponding to the index in a subscript operation */
|
||||||
ControlFlowNode getIndex() {
|
ControlFlowNode getIndex() {
|
||||||
exists(Subscript s |
|
exists(Py::Subscript s |
|
||||||
this.getNode() = s and
|
this.getNode() = s and
|
||||||
s.getIndex() = result.getNode() and
|
s.getIndex() = result.getNode() and
|
||||||
result.getBasicBlock().dominates(this.getBasicBlock())
|
result.getBasicBlock().dominates(this.getBasicBlock())
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override Subscript getNode() { result = super.getNode() }
|
override Py::Subscript getNode() { result = super.getNode() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/** A control flow node corresponding to a comparison operation, such as `x<y` */
|
/** A control flow node corresponding to a comparison operation, such as `x<y` */
|
||||||
class CompareNode extends ControlFlowNode {
|
class CompareNode extends ControlFlowNode {
|
||||||
CompareNode() { toAst(this) instanceof Compare }
|
CompareNode() { toAst(this) instanceof Py::Compare }
|
||||||
|
|
||||||
/** Whether left and right are a pair of operands for this comparison */
|
/** Whether left and right are a pair of operands for this comparison */
|
||||||
predicate operands(ControlFlowNode left, Cmpop op, ControlFlowNode right) {
|
predicate operands(ControlFlowNode left, Py::Cmpop op, ControlFlowNode right) {
|
||||||
exists(Compare c, Expr eleft, Expr eright |
|
exists(Py::Compare c, Py::Expr eleft, Py::Expr eright |
|
||||||
this.getNode() = c and left.getNode() = eleft and right.getNode() = eright
|
this.getNode() = c and left.getNode() = eleft and right.getNode() = eright
|
||||||
|
|
|
|
||||||
eleft = c.getLeft() and eright = c.getComparator(0) and op = c.getOp(0)
|
eleft = c.getLeft() and eright = c.getComparator(0) and op = c.getOp(0)
|
||||||
@@ -436,26 +436,26 @@ class CompareNode extends ControlFlowNode {
|
|||||||
right.getBasicBlock().dominates(this.getBasicBlock())
|
right.getBasicBlock().dominates(this.getBasicBlock())
|
||||||
}
|
}
|
||||||
|
|
||||||
override Compare getNode() { result = super.getNode() }
|
override Py::Compare getNode() { result = super.getNode() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/** A control flow node corresponding to a conditional expression such as, `body if test else orelse` */
|
/** A control flow node corresponding to a conditional expression such as, `body if test else orelse` */
|
||||||
class IfExprNode extends ControlFlowNode {
|
class IfExprNode extends ControlFlowNode {
|
||||||
IfExprNode() { toAst(this) instanceof IfExp }
|
IfExprNode() { toAst(this) instanceof Py::IfExp }
|
||||||
|
|
||||||
/** flow node corresponding to one of the operands of an if-expression */
|
/** flow node corresponding to one of the operands of an if-expression */
|
||||||
ControlFlowNode getAnOperand() { result = this.getAPredecessor() }
|
ControlFlowNode getAnOperand() { result = this.getAPredecessor() }
|
||||||
|
|
||||||
override IfExp getNode() { result = super.getNode() }
|
override Py::IfExp getNode() { result = super.getNode() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/** A control flow node corresponding to an assignment expression such as `lhs := rhs`. */
|
/** A control flow node corresponding to an assignment expression such as `lhs := rhs`. */
|
||||||
class AssignmentExprNode extends ControlFlowNode {
|
class AssignmentExprNode extends ControlFlowNode {
|
||||||
AssignmentExprNode() { toAst(this) instanceof AssignExpr }
|
AssignmentExprNode() { toAst(this) instanceof Py::AssignExpr }
|
||||||
|
|
||||||
/** Gets the flow node corresponding to the left-hand side of the assignment expression */
|
/** Gets the flow node corresponding to the left-hand side of the assignment expression */
|
||||||
ControlFlowNode getTarget() {
|
ControlFlowNode getTarget() {
|
||||||
exists(AssignExpr a |
|
exists(Py::AssignExpr a |
|
||||||
this.getNode() = a and
|
this.getNode() = a and
|
||||||
a.getTarget() = result.getNode() and
|
a.getTarget() = result.getNode() and
|
||||||
result.getBasicBlock().dominates(this.getBasicBlock())
|
result.getBasicBlock().dominates(this.getBasicBlock())
|
||||||
@@ -464,27 +464,27 @@ class AssignmentExprNode extends ControlFlowNode {
|
|||||||
|
|
||||||
/** Gets the flow node corresponding to the right-hand side of the assignment expression */
|
/** Gets the flow node corresponding to the right-hand side of the assignment expression */
|
||||||
ControlFlowNode getValue() {
|
ControlFlowNode getValue() {
|
||||||
exists(AssignExpr a |
|
exists(Py::AssignExpr a |
|
||||||
this.getNode() = a and
|
this.getNode() = a and
|
||||||
a.getValue() = result.getNode() and
|
a.getValue() = result.getNode() and
|
||||||
result.getBasicBlock().dominates(this.getBasicBlock())
|
result.getBasicBlock().dominates(this.getBasicBlock())
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
override AssignExpr getNode() { result = super.getNode() }
|
override Py::AssignExpr getNode() { result = super.getNode() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/** A control flow node corresponding to a binary expression, such as `x + y` */
|
/** A control flow node corresponding to a binary expression, such as `x + y` */
|
||||||
class BinaryExprNode extends ControlFlowNode {
|
class BinaryExprNode extends ControlFlowNode {
|
||||||
BinaryExprNode() { toAst(this) instanceof BinaryExpr }
|
BinaryExprNode() { toAst(this) instanceof Py::BinaryExpr }
|
||||||
|
|
||||||
/** flow node corresponding to one of the operands of a binary expression */
|
/** flow node corresponding to one of the operands of a binary expression */
|
||||||
ControlFlowNode getAnOperand() { result = this.getLeft() or result = this.getRight() }
|
ControlFlowNode getAnOperand() { result = this.getLeft() or result = this.getRight() }
|
||||||
|
|
||||||
override BinaryExpr getNode() { result = super.getNode() }
|
override Py::BinaryExpr getNode() { result = super.getNode() }
|
||||||
|
|
||||||
ControlFlowNode getLeft() {
|
ControlFlowNode getLeft() {
|
||||||
exists(BinaryExpr b |
|
exists(Py::BinaryExpr b |
|
||||||
this.getNode() = b and
|
this.getNode() = b and
|
||||||
result.getNode() = b.getLeft() and
|
result.getNode() = b.getLeft() and
|
||||||
result.getBasicBlock().dominates(this.getBasicBlock())
|
result.getBasicBlock().dominates(this.getBasicBlock())
|
||||||
@@ -492,7 +492,7 @@ class BinaryExprNode extends ControlFlowNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ControlFlowNode getRight() {
|
ControlFlowNode getRight() {
|
||||||
exists(BinaryExpr b |
|
exists(Py::BinaryExpr b |
|
||||||
this.getNode() = b and
|
this.getNode() = b and
|
||||||
result.getNode() = b.getRight() and
|
result.getNode() = b.getRight() and
|
||||||
result.getBasicBlock().dominates(this.getBasicBlock())
|
result.getBasicBlock().dominates(this.getBasicBlock())
|
||||||
@@ -500,11 +500,11 @@ class BinaryExprNode extends ControlFlowNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Gets the operator of this binary expression node. */
|
/** Gets the operator of this binary expression node. */
|
||||||
Operator getOp() { result = this.getNode().getOp() }
|
Py::Operator getOp() { result = this.getNode().getOp() }
|
||||||
|
|
||||||
/** Whether left and right are a pair of operands for this binary expression */
|
/** Whether left and right are a pair of operands for this binary expression */
|
||||||
predicate operands(ControlFlowNode left, Operator op, ControlFlowNode right) {
|
predicate operands(ControlFlowNode left, Py::Operator op, ControlFlowNode right) {
|
||||||
exists(BinaryExpr b, Expr eleft, Expr eright |
|
exists(Py::BinaryExpr b, Py::Expr eleft, Py::Expr eright |
|
||||||
this.getNode() = b and left.getNode() = eleft and right.getNode() = eright
|
this.getNode() = b and left.getNode() = eleft and right.getNode() = eright
|
||||||
|
|
|
|
||||||
eleft = b.getLeft() and eright = b.getRight() and op = b.getOp()
|
eleft = b.getLeft() and eright = b.getRight() and op = b.getOp()
|
||||||
@@ -516,20 +516,20 @@ class BinaryExprNode extends ControlFlowNode {
|
|||||||
|
|
||||||
/** A control flow node corresponding to a boolean shortcut (and/or) operation */
|
/** A control flow node corresponding to a boolean shortcut (and/or) operation */
|
||||||
class BoolExprNode extends ControlFlowNode {
|
class BoolExprNode extends ControlFlowNode {
|
||||||
BoolExprNode() { toAst(this) instanceof BoolExpr }
|
BoolExprNode() { toAst(this) instanceof Py::BoolExpr }
|
||||||
|
|
||||||
/** flow node corresponding to one of the operands of a boolean expression */
|
/** flow node corresponding to one of the operands of a boolean expression */
|
||||||
ControlFlowNode getAnOperand() {
|
ControlFlowNode getAnOperand() {
|
||||||
exists(BoolExpr b | this.getNode() = b and result.getNode() = b.getAValue()) and
|
exists(Py::BoolExpr b | this.getNode() = b and result.getNode() = b.getAValue()) and
|
||||||
this.getBasicBlock().dominates(result.getBasicBlock())
|
this.getBasicBlock().dominates(result.getBasicBlock())
|
||||||
}
|
}
|
||||||
|
|
||||||
override BoolExpr getNode() { result = super.getNode() }
|
override Py::BoolExpr getNode() { result = super.getNode() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/** A control flow node corresponding to a unary expression: (`+x`), (`-x`) or (`~x`) */
|
/** A control flow node corresponding to a unary expression: (`+x`), (`-x`) or (`~x`) */
|
||||||
class UnaryExprNode extends ControlFlowNode {
|
class UnaryExprNode extends ControlFlowNode {
|
||||||
UnaryExprNode() { toAst(this) instanceof UnaryExpr }
|
UnaryExprNode() { toAst(this) instanceof Py::UnaryExpr }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets flow node corresponding to the operand of a unary expression.
|
* Gets flow node corresponding to the operand of a unary expression.
|
||||||
@@ -540,7 +540,7 @@ class UnaryExprNode extends ControlFlowNode {
|
|||||||
*/
|
*/
|
||||||
ControlFlowNode getOperand() { result = this.getAPredecessor() }
|
ControlFlowNode getOperand() { result = this.getAPredecessor() }
|
||||||
|
|
||||||
override UnaryExpr getNode() { result = super.getNode() }
|
override Py::UnaryExpr getNode() { result = super.getNode() }
|
||||||
|
|
||||||
override ControlFlowNode getAChild() { result = this.getAPredecessor() }
|
override ControlFlowNode getAChild() { result = this.getAPredecessor() }
|
||||||
}
|
}
|
||||||
@@ -555,22 +555,22 @@ class DefinitionNode extends ControlFlowNode {
|
|||||||
cached
|
cached
|
||||||
DefinitionNode() {
|
DefinitionNode() {
|
||||||
Stages::AST::ref() and
|
Stages::AST::ref() and
|
||||||
exists(Assign a | this.getNode() = a.getATarget())
|
exists(Py::Assign a | this.getNode() = a.getATarget())
|
||||||
or
|
or
|
||||||
exists(AssignExpr a | this.getNode() = a.getTarget())
|
exists(Py::AssignExpr a | this.getNode() = a.getTarget())
|
||||||
or
|
or
|
||||||
exists(AnnAssign a | this.getNode() = a.getTarget() and exists(a.getValue()))
|
exists(Py::AnnAssign a | this.getNode() = a.getTarget() and exists(a.getValue()))
|
||||||
or
|
or
|
||||||
exists(Alias a | this.getNode() = a.getAsname())
|
exists(Py::Alias a | this.getNode() = a.getAsname())
|
||||||
or
|
or
|
||||||
augstore(_, this)
|
augstore(_, this)
|
||||||
or
|
or
|
||||||
// `x, y = 1, 2` where LHS is a combination of list or tuples
|
// `x, y = 1, 2` where LHS is a combination of list or tuples
|
||||||
exists(Assign a | this.getNode() = list_or_tuple_nested_element(a.getATarget()))
|
exists(Py::Assign a | this.getNode() = list_or_tuple_nested_element(a.getATarget()))
|
||||||
or
|
or
|
||||||
exists(For for | this.getNode() = for.getTarget())
|
exists(Py::For for | this.getNode() = for.getTarget())
|
||||||
or
|
or
|
||||||
exists(Parameter param | this.getNode() = param.asName() and exists(param.getDefault()))
|
exists(Py::Parameter param | this.getNode() = param.asName() and exists(param.getDefault()))
|
||||||
}
|
}
|
||||||
|
|
||||||
/** flow node corresponding to the value assigned for the definition corresponding to this flow node */
|
/** flow node corresponding to the value assigned for the definition corresponding to this flow node */
|
||||||
@@ -584,16 +584,16 @@ class DefinitionNode extends ControlFlowNode {
|
|||||||
// since the default value for a parameter is evaluated in the same basic block as
|
// since the default value for a parameter is evaluated in the same basic block as
|
||||||
// the function definition, but the parameter belongs to the basic block of the function,
|
// the function definition, but the parameter belongs to the basic block of the function,
|
||||||
// there is no dominance relationship between the two.
|
// there is no dominance relationship between the two.
|
||||||
exists(Parameter param | this.getNode() = param.asName())
|
exists(Py::Parameter param | this.getNode() = param.asName())
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Expr list_or_tuple_nested_element(Expr list_or_tuple) {
|
private Py::Expr list_or_tuple_nested_element(Py::Expr list_or_tuple) {
|
||||||
exists(Expr elt |
|
exists(Py::Expr elt |
|
||||||
elt = list_or_tuple.(Tuple).getAnElt()
|
elt = list_or_tuple.(Py::Tuple).getAnElt()
|
||||||
or
|
or
|
||||||
elt = list_or_tuple.(List).getAnElt()
|
elt = list_or_tuple.(Py::List).getAnElt()
|
||||||
|
|
|
|
||||||
result = elt
|
result = elt
|
||||||
or
|
or
|
||||||
@@ -603,12 +603,12 @@ private Expr list_or_tuple_nested_element(Expr list_or_tuple) {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* A control flow node corresponding to a deletion statement, such as `del x`.
|
* A control flow node corresponding to a deletion statement, such as `del x`.
|
||||||
* There can be multiple `DeletionNode`s for each `Delete` such that each
|
* There can be multiple `DeletionNode`s for each `Py::Delete` such that each
|
||||||
* target has own `DeletionNode`. The CFG for `del a, x.y` looks like:
|
* target has own `DeletionNode`. The CFG for `del a, x.y` looks like:
|
||||||
* `NameNode('a') -> DeletionNode -> NameNode('b') -> AttrNode('y') -> DeletionNode`.
|
* `NameNode('a') -> DeletionNode -> NameNode('b') -> AttrNode('y') -> DeletionNode`.
|
||||||
*/
|
*/
|
||||||
class DeletionNode extends ControlFlowNode {
|
class DeletionNode extends ControlFlowNode {
|
||||||
DeletionNode() { toAst(this) instanceof Delete }
|
DeletionNode() { toAst(this) instanceof Py::Delete }
|
||||||
|
|
||||||
/** Gets the unique target of this deletion node. */
|
/** Gets the unique target of this deletion node. */
|
||||||
ControlFlowNode getTarget() { result.getASuccessor() = this }
|
ControlFlowNode getTarget() { result.getASuccessor() = this }
|
||||||
@@ -617,9 +617,9 @@ class DeletionNode extends ControlFlowNode {
|
|||||||
/** A control flow node corresponding to a sequence (tuple or list) literal */
|
/** A control flow node corresponding to a sequence (tuple or list) literal */
|
||||||
abstract class SequenceNode extends ControlFlowNode {
|
abstract class SequenceNode extends ControlFlowNode {
|
||||||
SequenceNode() {
|
SequenceNode() {
|
||||||
toAst(this) instanceof Tuple
|
toAst(this) instanceof Py::Tuple
|
||||||
or
|
or
|
||||||
toAst(this) instanceof List
|
toAst(this) instanceof Py::List
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Gets the control flow node for an element of this sequence */
|
/** Gets the control flow node for an element of this sequence */
|
||||||
@@ -632,11 +632,11 @@ abstract class SequenceNode extends ControlFlowNode {
|
|||||||
|
|
||||||
/** A control flow node corresponding to a tuple expression such as `( 1, 3, 5, 7, 9 )` */
|
/** A control flow node corresponding to a tuple expression such as `( 1, 3, 5, 7, 9 )` */
|
||||||
class TupleNode extends SequenceNode {
|
class TupleNode extends SequenceNode {
|
||||||
TupleNode() { toAst(this) instanceof Tuple }
|
TupleNode() { toAst(this) instanceof Py::Tuple }
|
||||||
|
|
||||||
override ControlFlowNode getElement(int n) {
|
override ControlFlowNode getElement(int n) {
|
||||||
Stages::AST::ref() and
|
Stages::AST::ref() and
|
||||||
exists(Tuple t | this.getNode() = t and result.getNode() = t.getElt(n)) and
|
exists(Py::Tuple t | this.getNode() = t and result.getNode() = t.getElt(n)) and
|
||||||
(
|
(
|
||||||
result.getBasicBlock().dominates(this.getBasicBlock())
|
result.getBasicBlock().dominates(this.getBasicBlock())
|
||||||
or
|
or
|
||||||
@@ -647,10 +647,10 @@ class TupleNode extends SequenceNode {
|
|||||||
|
|
||||||
/** A control flow node corresponding to a list expression, such as `[ 1, 3, 5, 7, 9 ]` */
|
/** A control flow node corresponding to a list expression, such as `[ 1, 3, 5, 7, 9 ]` */
|
||||||
class ListNode extends SequenceNode {
|
class ListNode extends SequenceNode {
|
||||||
ListNode() { toAst(this) instanceof List }
|
ListNode() { toAst(this) instanceof Py::List }
|
||||||
|
|
||||||
override ControlFlowNode getElement(int n) {
|
override ControlFlowNode getElement(int n) {
|
||||||
exists(List l | this.getNode() = l and result.getNode() = l.getElt(n)) and
|
exists(Py::List l | this.getNode() = l and result.getNode() = l.getElt(n)) and
|
||||||
(
|
(
|
||||||
result.getBasicBlock().dominates(this.getBasicBlock())
|
result.getBasicBlock().dominates(this.getBasicBlock())
|
||||||
or
|
or
|
||||||
@@ -661,10 +661,10 @@ class ListNode extends SequenceNode {
|
|||||||
|
|
||||||
/** A control flow node corresponding to a set expression, such as `{ 1, 3, 5, 7, 9 }` */
|
/** A control flow node corresponding to a set expression, such as `{ 1, 3, 5, 7, 9 }` */
|
||||||
class SetNode extends ControlFlowNode {
|
class SetNode extends ControlFlowNode {
|
||||||
SetNode() { toAst(this) instanceof Set }
|
SetNode() { toAst(this) instanceof Py::Set }
|
||||||
|
|
||||||
ControlFlowNode getAnElement() {
|
ControlFlowNode getAnElement() {
|
||||||
exists(Set s | this.getNode() = s and result.getNode() = s.getElt(_)) and
|
exists(Py::Set s | this.getNode() = s and result.getNode() = s.getElt(_)) and
|
||||||
(
|
(
|
||||||
result.getBasicBlock().dominates(this.getBasicBlock())
|
result.getBasicBlock().dominates(this.getBasicBlock())
|
||||||
or
|
or
|
||||||
@@ -675,20 +675,20 @@ class SetNode extends ControlFlowNode {
|
|||||||
|
|
||||||
/** A control flow node corresponding to a dictionary literal, such as `{ 'a': 1, 'b': 2 }` */
|
/** A control flow node corresponding to a dictionary literal, such as `{ 'a': 1, 'b': 2 }` */
|
||||||
class DictNode extends ControlFlowNode {
|
class DictNode extends ControlFlowNode {
|
||||||
DictNode() { toAst(this) instanceof Dict }
|
DictNode() { toAst(this) instanceof Py::Dict }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a key of this dictionary literal node, for those items that have keys
|
* Gets a key of this dictionary literal node, for those items that have keys
|
||||||
* E.g, in {'a':1, **b} this returns only 'a'
|
* E.g, in {'a':1, **b} this returns only 'a'
|
||||||
*/
|
*/
|
||||||
ControlFlowNode getAKey() {
|
ControlFlowNode getAKey() {
|
||||||
exists(Dict d | this.getNode() = d and result.getNode() = d.getAKey()) and
|
exists(Py::Dict d | this.getNode() = d and result.getNode() = d.getAKey()) and
|
||||||
result.getBasicBlock().dominates(this.getBasicBlock())
|
result.getBasicBlock().dominates(this.getBasicBlock())
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Gets a value of this dictionary literal node */
|
/** Gets a value of this dictionary literal node */
|
||||||
ControlFlowNode getAValue() {
|
ControlFlowNode getAValue() {
|
||||||
exists(Dict d | this.getNode() = d and result.getNode() = d.getAValue()) and
|
exists(Py::Dict d | this.getNode() = d and result.getNode() = d.getAValue()) and
|
||||||
result.getBasicBlock().dominates(this.getBasicBlock())
|
result.getBasicBlock().dominates(this.getBasicBlock())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -712,21 +712,23 @@ class IterableNode extends ControlFlowNode {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private AstNode assigned_value(Expr lhs) {
|
private Py::AstNode assigned_value(Py::Expr lhs) {
|
||||||
/* lhs = result */
|
/* lhs = result */
|
||||||
exists(Assign a | a.getATarget() = lhs and result = a.getValue())
|
exists(Py::Assign a | a.getATarget() = lhs and result = a.getValue())
|
||||||
or
|
or
|
||||||
/* lhs := result */
|
/* lhs := result */
|
||||||
exists(AssignExpr a | a.getTarget() = lhs and result = a.getValue())
|
exists(Py::AssignExpr a | a.getTarget() = lhs and result = a.getValue())
|
||||||
or
|
or
|
||||||
/* lhs : annotation = result */
|
/* lhs : annotation = result */
|
||||||
exists(AnnAssign a | a.getTarget() = lhs and result = a.getValue())
|
exists(Py::AnnAssign a | a.getTarget() = lhs and result = a.getValue())
|
||||||
or
|
or
|
||||||
/* import result as lhs */
|
/* import result as lhs */
|
||||||
exists(Alias a | a.getAsname() = lhs and result = a.getValue())
|
exists(Py::Alias a | a.getAsname() = lhs and result = a.getValue())
|
||||||
or
|
or
|
||||||
/* lhs += x => result = (lhs + x) */
|
/* lhs += x => result = (lhs + x) */
|
||||||
exists(AugAssign a, BinaryExpr b | b = a.getOperation() and result = b and lhs = b.getLeft())
|
exists(Py::AugAssign a, Py::BinaryExpr b |
|
||||||
|
b = a.getOperation() and result = b and lhs = b.getLeft()
|
||||||
|
)
|
||||||
or
|
or
|
||||||
/*
|
/*
|
||||||
* ..., lhs, ... = ..., result, ...
|
* ..., lhs, ... = ..., result, ...
|
||||||
@@ -734,31 +736,31 @@ private AstNode assigned_value(Expr lhs) {
|
|||||||
* ..., (..., lhs, ...), ... = ..., (..., result, ...), ...
|
* ..., (..., lhs, ...), ... = ..., (..., result, ...), ...
|
||||||
*/
|
*/
|
||||||
|
|
||||||
exists(Assign a | nested_sequence_assign(a.getATarget(), a.getValue(), lhs, result))
|
exists(Py::Assign a | nested_sequence_assign(a.getATarget(), a.getValue(), lhs, result))
|
||||||
or
|
or
|
||||||
/* for lhs in seq: => `result` is the `for` node, representing the `iter(next(seq))` operation. */
|
/* for lhs in seq: => `result` is the `for` node, representing the `iter(next(seq))` operation. */
|
||||||
result.(For).getTarget() = lhs
|
result.(Py::For).getTarget() = lhs
|
||||||
or
|
or
|
||||||
exists(Parameter param | lhs = param.asName() and result = param.getDefault())
|
exists(Py::Parameter param | lhs = param.asName() and result = param.getDefault())
|
||||||
}
|
}
|
||||||
|
|
||||||
predicate nested_sequence_assign(
|
predicate nested_sequence_assign(
|
||||||
Expr left_parent, Expr right_parent, Expr left_result, Expr right_result
|
Py::Expr left_parent, Py::Expr right_parent, Py::Expr left_result, Py::Expr right_result
|
||||||
) {
|
) {
|
||||||
exists(Assign a |
|
exists(Py::Assign a |
|
||||||
a.getATarget().getASubExpression*() = left_parent and
|
a.getATarget().getASubExpression*() = left_parent and
|
||||||
a.getValue().getASubExpression*() = right_parent
|
a.getValue().getASubExpression*() = right_parent
|
||||||
) and
|
) and
|
||||||
exists(int i, Expr left_elem, Expr right_elem |
|
exists(int i, Py::Expr left_elem, Py::Expr right_elem |
|
||||||
(
|
(
|
||||||
left_elem = left_parent.(Tuple).getElt(i)
|
left_elem = left_parent.(Py::Tuple).getElt(i)
|
||||||
or
|
or
|
||||||
left_elem = left_parent.(List).getElt(i)
|
left_elem = left_parent.(Py::List).getElt(i)
|
||||||
) and
|
) and
|
||||||
(
|
(
|
||||||
right_elem = right_parent.(Tuple).getElt(i)
|
right_elem = right_parent.(Py::Tuple).getElt(i)
|
||||||
or
|
or
|
||||||
right_elem = right_parent.(List).getElt(i)
|
right_elem = right_parent.(Py::List).getElt(i)
|
||||||
)
|
)
|
||||||
|
|
|
|
||||||
left_result = left_elem and right_result = right_elem
|
left_result = left_elem and right_result = right_elem
|
||||||
@@ -769,9 +771,9 @@ predicate nested_sequence_assign(
|
|||||||
|
|
||||||
/** A flow node for a `for` statement. */
|
/** A flow node for a `for` statement. */
|
||||||
class ForNode extends ControlFlowNode {
|
class ForNode extends ControlFlowNode {
|
||||||
ForNode() { toAst(this) instanceof For }
|
ForNode() { toAst(this) instanceof Py::For }
|
||||||
|
|
||||||
override For getNode() { result = super.getNode() }
|
override Py::For getNode() { result = super.getNode() }
|
||||||
|
|
||||||
/** Holds if this `for` statement causes iteration over `sequence` storing each step of the iteration in `target` */
|
/** Holds if this `for` statement causes iteration over `sequence` storing each step of the iteration in `target` */
|
||||||
predicate iterates(ControlFlowNode target, ControlFlowNode sequence) {
|
predicate iterates(ControlFlowNode target, ControlFlowNode sequence) {
|
||||||
@@ -782,7 +784,7 @@ class ForNode extends ControlFlowNode {
|
|||||||
|
|
||||||
/** Gets the sequence node for this `for` statement. */
|
/** Gets the sequence node for this `for` statement. */
|
||||||
ControlFlowNode getSequence() {
|
ControlFlowNode getSequence() {
|
||||||
exists(For for |
|
exists(Py::For for |
|
||||||
toAst(this) = for and
|
toAst(this) = for and
|
||||||
for.getIter() = result.getNode()
|
for.getIter() = result.getNode()
|
||||||
|
|
|
|
||||||
@@ -792,7 +794,7 @@ class ForNode extends ControlFlowNode {
|
|||||||
|
|
||||||
/** A possible `target` for this `for` statement, not accounting for loop unrolling */
|
/** A possible `target` for this `for` statement, not accounting for loop unrolling */
|
||||||
private ControlFlowNode possibleTarget() {
|
private ControlFlowNode possibleTarget() {
|
||||||
exists(For for |
|
exists(Py::For for |
|
||||||
toAst(this) = for and
|
toAst(this) = for and
|
||||||
for.getTarget() = result.getNode() and
|
for.getTarget() = result.getNode() and
|
||||||
this.getBasicBlock().dominates(result.getBasicBlock())
|
this.getBasicBlock().dominates(result.getBasicBlock())
|
||||||
@@ -809,11 +811,11 @@ class ForNode extends ControlFlowNode {
|
|||||||
|
|
||||||
/** A flow node for a `raise` statement */
|
/** A flow node for a `raise` statement */
|
||||||
class RaiseStmtNode extends ControlFlowNode {
|
class RaiseStmtNode extends ControlFlowNode {
|
||||||
RaiseStmtNode() { toAst(this) instanceof Raise }
|
RaiseStmtNode() { toAst(this) instanceof Py::Raise }
|
||||||
|
|
||||||
/** Gets the control flow node for the exception raised by this raise statement */
|
/** Gets the control flow node for the exception raised by this raise statement */
|
||||||
ControlFlowNode getException() {
|
ControlFlowNode getException() {
|
||||||
exists(Raise r |
|
exists(Py::Raise r |
|
||||||
r = toAst(this) and
|
r = toAst(this) and
|
||||||
r.getException() = toAst(result) and
|
r.getException() = toAst(result) and
|
||||||
result.getBasicBlock().dominates(this.getBasicBlock())
|
result.getBasicBlock().dominates(this.getBasicBlock())
|
||||||
@@ -827,36 +829,36 @@ class RaiseStmtNode extends ControlFlowNode {
|
|||||||
*/
|
*/
|
||||||
class NameNode extends ControlFlowNode {
|
class NameNode extends ControlFlowNode {
|
||||||
NameNode() {
|
NameNode() {
|
||||||
exists(Name n | py_flow_bb_node(this, n, _, _))
|
exists(Py::Name n | py_flow_bb_node(this, n, _, _))
|
||||||
or
|
or
|
||||||
exists(PlaceHolder p | py_flow_bb_node(this, p, _, _))
|
exists(Py::PlaceHolder p | py_flow_bb_node(this, p, _, _))
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Whether this flow node defines the variable `v`. */
|
/** Whether this flow node defines the variable `v`. */
|
||||||
predicate defines(Variable v) {
|
predicate defines(Py::Variable v) {
|
||||||
exists(Name d | this.getNode() = d and d.defines(v)) and
|
exists(Py::Name d | this.getNode() = d and d.defines(v)) and
|
||||||
not this.isLoad()
|
not this.isLoad()
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Whether this flow node deletes the variable `v`. */
|
/** Whether this flow node deletes the variable `v`. */
|
||||||
predicate deletes(Variable v) { exists(Name d | this.getNode() = d and d.deletes(v)) }
|
predicate deletes(Py::Variable v) { exists(Py::Name d | this.getNode() = d and d.deletes(v)) }
|
||||||
|
|
||||||
/** Whether this flow node uses the variable `v`. */
|
/** Whether this flow node uses the variable `v`. */
|
||||||
predicate uses(Variable v) {
|
predicate uses(Py::Variable v) {
|
||||||
this.isLoad() and
|
this.isLoad() and
|
||||||
exists(Name u | this.getNode() = u and u.uses(v))
|
exists(Py::Name u | this.getNode() = u and u.uses(v))
|
||||||
or
|
or
|
||||||
exists(PlaceHolder u |
|
exists(Py::PlaceHolder u |
|
||||||
this.getNode() = u and u.getVariable() = v and u.getCtx() instanceof Load
|
this.getNode() = u and u.getVariable() = v and u.getCtx() instanceof Py::Load
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
Scopes::use_of_global_variable(this, v.getScope(), v.getId())
|
Scopes::use_of_global_variable(this, v.getScope(), v.getId())
|
||||||
}
|
}
|
||||||
|
|
||||||
string getId() {
|
string getId() {
|
||||||
result = this.getNode().(Name).getId()
|
result = this.getNode().(Py::Name).getId()
|
||||||
or
|
or
|
||||||
result = this.getNode().(PlaceHolder).getId()
|
result = this.getNode().(Py::PlaceHolder).getId()
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Whether this is a use of a local variable. */
|
/** Whether this is a use of a local variable. */
|
||||||
@@ -868,37 +870,39 @@ class NameNode extends ControlFlowNode {
|
|||||||
/** Whether this is a use of a global (including builtin) variable. */
|
/** Whether this is a use of a global (including builtin) variable. */
|
||||||
predicate isGlobal() { Scopes::use_of_global_variable(this, _, _) }
|
predicate isGlobal() { Scopes::use_of_global_variable(this, _, _) }
|
||||||
|
|
||||||
predicate isSelf() { exists(SsaVariable selfvar | selfvar.isSelf() and selfvar.getAUse() = this) }
|
predicate isSelf() {
|
||||||
|
exists(Py::SsaVariable selfvar | selfvar.isSelf() and selfvar.getAUse() = this)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** A control flow node corresponding to a named constant, one of `None`, `True` or `False`. */
|
/** A control flow node corresponding to a named constant, one of `None`, `True` or `False`. */
|
||||||
class NameConstantNode extends NameNode {
|
class NameConstantNode extends NameNode {
|
||||||
NameConstantNode() { exists(NameConstant n | py_flow_bb_node(this, n, _, _)) }
|
NameConstantNode() { exists(Py::NameConstant n | py_flow_bb_node(this, n, _, _)) }
|
||||||
/*
|
/*
|
||||||
* We ought to override uses as well, but that has
|
* We ought to override uses as well, but that has
|
||||||
* a serious performance impact.
|
* a serious performance impact.
|
||||||
* deprecated predicate uses(Variable v) { none() }
|
* deprecated predicate uses(Py::Variable v) { none() }
|
||||||
*/
|
*/
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/** A control flow node corresponding to a starred expression, `*a`. */
|
/** A control flow node corresponding to a starred expression, `*a`. */
|
||||||
class StarredNode extends ControlFlowNode {
|
class StarredNode extends ControlFlowNode {
|
||||||
StarredNode() { toAst(this) instanceof Starred }
|
StarredNode() { toAst(this) instanceof Py::Starred }
|
||||||
|
|
||||||
ControlFlowNode getValue() { toAst(result) = toAst(this).(Starred).getValue() }
|
ControlFlowNode getValue() { toAst(result) = toAst(this).(Py::Starred).getValue() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/** The ControlFlowNode for an 'except' statement. */
|
/** The ControlFlowNode for an 'except' statement. */
|
||||||
class ExceptFlowNode extends ControlFlowNode {
|
class ExceptFlowNode extends ControlFlowNode {
|
||||||
ExceptFlowNode() { this.getNode() instanceof ExceptStmt }
|
ExceptFlowNode() { this.getNode() instanceof Py::ExceptStmt }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the type handled by this exception handler.
|
* Gets the type handled by this exception handler.
|
||||||
* `ExceptionType` in `except ExceptionType as e:`
|
* `Py::ExceptionType` in `except Py::ExceptionType as e:`
|
||||||
*/
|
*/
|
||||||
ControlFlowNode getType() {
|
ControlFlowNode getType() {
|
||||||
exists(ExceptStmt ex |
|
exists(Py::ExceptStmt ex |
|
||||||
this.getBasicBlock().dominates(result.getBasicBlock()) and
|
this.getBasicBlock().dominates(result.getBasicBlock()) and
|
||||||
ex = this.getNode() and
|
ex = this.getNode() and
|
||||||
result.getNode() = ex.getType()
|
result.getNode() = ex.getType()
|
||||||
@@ -907,10 +911,10 @@ class ExceptFlowNode extends ControlFlowNode {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the name assigned to the handled exception, if any.
|
* Gets the name assigned to the handled exception, if any.
|
||||||
* `e` in `except ExceptionType as e:`
|
* `e` in `except Py::ExceptionType as e:`
|
||||||
*/
|
*/
|
||||||
ControlFlowNode getName() {
|
ControlFlowNode getName() {
|
||||||
exists(ExceptStmt ex |
|
exists(Py::ExceptStmt ex |
|
||||||
this.getBasicBlock().dominates(result.getBasicBlock()) and
|
this.getBasicBlock().dominates(result.getBasicBlock()) and
|
||||||
ex = this.getNode() and
|
ex = this.getNode() and
|
||||||
result.getNode() = ex.getName()
|
result.getNode() = ex.getName()
|
||||||
@@ -920,30 +924,30 @@ class ExceptFlowNode extends ControlFlowNode {
|
|||||||
|
|
||||||
/** The ControlFlowNode for an 'except*' statement. */
|
/** The ControlFlowNode for an 'except*' statement. */
|
||||||
class ExceptGroupFlowNode extends ControlFlowNode {
|
class ExceptGroupFlowNode extends ControlFlowNode {
|
||||||
ExceptGroupFlowNode() { this.getNode() instanceof ExceptGroupStmt }
|
ExceptGroupFlowNode() { this.getNode() instanceof Py::ExceptGroupStmt }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the type handled by this exception handler.
|
* Gets the type handled by this exception handler.
|
||||||
* `ExceptionType` in `except* ExceptionType as e:`
|
* `Py::ExceptionType` in `except* Py::ExceptionType as e:`
|
||||||
*/
|
*/
|
||||||
ControlFlowNode getType() {
|
ControlFlowNode getType() {
|
||||||
this.getBasicBlock().dominates(result.getBasicBlock()) and
|
this.getBasicBlock().dominates(result.getBasicBlock()) and
|
||||||
result.getNode() = this.getNode().(ExceptGroupStmt).getType()
|
result.getNode() = this.getNode().(Py::ExceptGroupStmt).getType()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the name assigned to the handled exception, if any.
|
* Gets the name assigned to the handled exception, if any.
|
||||||
* `e` in `except* ExceptionType as e:`
|
* `e` in `except* Py::ExceptionType as e:`
|
||||||
*/
|
*/
|
||||||
ControlFlowNode getName() {
|
ControlFlowNode getName() {
|
||||||
this.getBasicBlock().dominates(result.getBasicBlock()) and
|
this.getBasicBlock().dominates(result.getBasicBlock()) and
|
||||||
result.getNode() = this.getNode().(ExceptGroupStmt).getName()
|
result.getNode() = this.getNode().(Py::ExceptGroupStmt).getName()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private module Scopes {
|
private module Scopes {
|
||||||
private predicate fast_local(NameNode n) {
|
private predicate fast_local(NameNode n) {
|
||||||
exists(FastLocalVariable v |
|
exists(Py::FastLocalVariable v |
|
||||||
n.uses(v) and
|
n.uses(v) and
|
||||||
v.getScope() = n.getScope()
|
v.getScope() = n.getScope()
|
||||||
)
|
)
|
||||||
@@ -952,15 +956,15 @@ private module Scopes {
|
|||||||
predicate local(NameNode n) {
|
predicate local(NameNode n) {
|
||||||
fast_local(n)
|
fast_local(n)
|
||||||
or
|
or
|
||||||
exists(SsaVariable var |
|
exists(Py::SsaVariable var |
|
||||||
var.getAUse() = n and
|
var.getAUse() = n and
|
||||||
n.getScope() instanceof Class and
|
n.getScope() instanceof Py::Class and
|
||||||
exists(var.getDefinition())
|
exists(var.getDefinition())
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
predicate non_local(NameNode n) {
|
predicate non_local(NameNode n) {
|
||||||
exists(FastLocalVariable flv |
|
exists(Py::FastLocalVariable flv |
|
||||||
flv.getALoad() = n.getNode() and
|
flv.getALoad() = n.getNode() and
|
||||||
not flv.getScope() = n.getScope()
|
not flv.getScope() = n.getScope()
|
||||||
)
|
)
|
||||||
@@ -968,20 +972,20 @@ private module Scopes {
|
|||||||
|
|
||||||
// magic is fine, but we get questionable join-ordering of it
|
// magic is fine, but we get questionable join-ordering of it
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
predicate use_of_global_variable(NameNode n, Module scope, string name) {
|
predicate use_of_global_variable(NameNode n, Py::Module scope, string name) {
|
||||||
n.isLoad() and
|
n.isLoad() and
|
||||||
not non_local(n) and
|
not non_local(n) and
|
||||||
not exists(SsaVariable var | var.getAUse() = n |
|
not exists(Py::SsaVariable var | var.getAUse() = n |
|
||||||
var.getVariable() instanceof FastLocalVariable
|
var.getVariable() instanceof Py::FastLocalVariable
|
||||||
or
|
or
|
||||||
n.getScope() instanceof Class and
|
n.getScope() instanceof Py::Class and
|
||||||
not maybe_undefined(var)
|
not maybe_undefined(var)
|
||||||
) and
|
) and
|
||||||
name = n.getId() and
|
name = n.getId() and
|
||||||
scope = n.getEnclosingModule()
|
scope = n.getEnclosingModule()
|
||||||
}
|
}
|
||||||
|
|
||||||
private predicate maybe_undefined(SsaVariable var) {
|
private predicate maybe_undefined(Py::SsaVariable var) {
|
||||||
not exists(var.getDefinition()) and not py_ssa_phi(var, _)
|
not exists(var.getDefinition()) and not py_ssa_phi(var, _)
|
||||||
or
|
or
|
||||||
var.getDefinition().isDelete()
|
var.getDefinition().isDelete()
|
||||||
@@ -1058,13 +1062,13 @@ class BasicBlock extends @py_flow_node {
|
|||||||
private predicate oneNodeBlock() { this.firstNode() = this.getLastNode() }
|
private predicate oneNodeBlock() { this.firstNode() = this.getLastNode() }
|
||||||
|
|
||||||
private predicate startLocationInfo(string file, int line, int col) {
|
private predicate startLocationInfo(string file, int line, int col) {
|
||||||
if this.firstNode().getNode() instanceof Scope
|
if this.firstNode().getNode() instanceof Py::Scope
|
||||||
then this.firstNode().getASuccessor().getLocation().hasLocationInfo(file, line, col, _, _)
|
then this.firstNode().getASuccessor().getLocation().hasLocationInfo(file, line, col, _, _)
|
||||||
else this.firstNode().getLocation().hasLocationInfo(file, line, col, _, _)
|
else this.firstNode().getLocation().hasLocationInfo(file, line, col, _, _)
|
||||||
}
|
}
|
||||||
|
|
||||||
private predicate endLocationInfo(int endl, int endc) {
|
private predicate endLocationInfo(int endl, int endc) {
|
||||||
if this.getLastNode().getNode() instanceof Scope and not this.oneNodeBlock()
|
if this.getLastNode().getNode() instanceof Py::Scope and not this.oneNodeBlock()
|
||||||
then this.getLastNode().getAPredecessor().getLocation().hasLocationInfo(_, _, _, endl, endc)
|
then this.getLastNode().getAPredecessor().getLocation().hasLocationInfo(_, _, _, endl, endc)
|
||||||
else this.getLastNode().getLocation().hasLocationInfo(_, _, _, endl, endc)
|
else this.getLastNode().getLocation().hasLocationInfo(_, _, _, endl, endc)
|
||||||
}
|
}
|
||||||
@@ -1081,7 +1085,7 @@ class BasicBlock extends @py_flow_node {
|
|||||||
|
|
||||||
/** Whether flow from this basic block reaches a normal exit from its scope */
|
/** Whether flow from this basic block reaches a normal exit from its scope */
|
||||||
predicate reachesExit() {
|
predicate reachesExit() {
|
||||||
exists(Scope s | s.getANormalExit().getBasicBlock() = this)
|
exists(Py::Scope s | s.getANormalExit().getBasicBlock() = this)
|
||||||
or
|
or
|
||||||
this.getASuccessor().reachesExit()
|
this.getASuccessor().reachesExit()
|
||||||
}
|
}
|
||||||
@@ -1122,7 +1126,7 @@ class BasicBlock extends @py_flow_node {
|
|||||||
|
|
||||||
/** Gets the scope of this block */
|
/** Gets the scope of this block */
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
Scope getScope() {
|
Py::Scope getScope() {
|
||||||
exists(ControlFlowNode n | n.getBasicBlock() = this |
|
exists(ControlFlowNode n | n.getBasicBlock() = this |
|
||||||
/* Take care not to use an entry or exit node as that node's scope will be the outer scope */
|
/* Take care not to use an entry or exit node as that node's scope will be the outer scope */
|
||||||
not py_scope_flow(n, _, -1) and
|
not py_scope_flow(n, _, -1) and
|
||||||
@@ -1145,17 +1149,17 @@ class BasicBlock extends @py_flow_node {
|
|||||||
predicate reaches(BasicBlock other) { this = other or this.strictlyReaches(other) }
|
predicate reaches(BasicBlock other) { this = other or this.strictlyReaches(other) }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the `ConditionBlock`, if any, that controls this block and
|
* Gets the `Py::ConditionBlock`, if any, that controls this block and
|
||||||
* does not control any other `ConditionBlock`s that control this block.
|
* does not control any other `Py::ConditionBlock`s that control this block.
|
||||||
* That is the `ConditionBlock` that is closest dominator.
|
* That is the `Py::ConditionBlock` that is closest dominator.
|
||||||
*/
|
*/
|
||||||
ConditionBlock getImmediatelyControllingBlock() {
|
Py::ConditionBlock getImmediatelyControllingBlock() {
|
||||||
result = this.nonControllingImmediateDominator*().getImmediateDominator()
|
result = this.nonControllingImmediateDominator*().getImmediateDominator()
|
||||||
}
|
}
|
||||||
|
|
||||||
private BasicBlock nonControllingImmediateDominator() {
|
private BasicBlock nonControllingImmediateDominator() {
|
||||||
result = this.getImmediateDominator() and
|
result = this.getImmediateDominator() and
|
||||||
not result.(ConditionBlock).controls(this, _)
|
not result.(Py::ConditionBlock).controls(this, _)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1175,7 +1179,7 @@ private class ControlFlowNodeAlias = ControlFlowNode;
|
|||||||
|
|
||||||
final private class FinalBasicBlock = BasicBlock;
|
final private class FinalBasicBlock = BasicBlock;
|
||||||
|
|
||||||
module Cfg implements BB::CfgSig<Location> {
|
module Cfg implements BB::CfgSig<Py::Location> {
|
||||||
private import codeql.controlflow.SuccessorType
|
private import codeql.controlflow.SuccessorType
|
||||||
|
|
||||||
class ControlFlowNode = ControlFlowNodeAlias;
|
class ControlFlowNode = ControlFlowNodeAlias;
|
||||||
@@ -1186,7 +1190,7 @@ module Cfg implements BB::CfgSig<Location> {
|
|||||||
// Using the location of the first node is simple
|
// Using the location of the first node is simple
|
||||||
// and we just need a way to identify the basic block
|
// and we just need a way to identify the basic block
|
||||||
// during debugging, so this will be serviceable.
|
// during debugging, so this will be serviceable.
|
||||||
Location getLocation() { result = super.getNode(0).getLocation() }
|
Py::Location getLocation() { result = super.getNode(0).getLocation() }
|
||||||
|
|
||||||
int length() { result = count(int i | exists(this.getNode(i))) }
|
int length() { result = count(int i | exists(this.getNode(i))) }
|
||||||
|
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ overlay[local]
|
|||||||
module;
|
module;
|
||||||
|
|
||||||
import python
|
import python
|
||||||
|
private import semmle.python.controlflow.internal.Cfg as Cfg
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A function, independent of defaults and binding.
|
* A function, independent of defaults and binding.
|
||||||
@@ -157,12 +158,12 @@ class Function extends Function_, Scope, AstNode {
|
|||||||
* DEPRECATED: bind a `Return` node explicitly instead, e.g.
|
* DEPRECATED: bind a `Return` node explicitly instead, e.g.
|
||||||
* `exists(Return ret | ret.getScope() = this and n.getNode() = ret.getValue())`.
|
* `exists(Return ret | ret.getScope() = this and n.getNode() = ret.getValue())`.
|
||||||
* This API is being phased out together with `AstNode.getAFlowNode()` to
|
* This API is being phased out together with `AstNode.getAFlowNode()` to
|
||||||
* untangle the AST and CFG hierarchies in preparation for migrating the
|
* untangle the AST and CFG hierarchies.
|
||||||
* dataflow library off the legacy CFG.
|
|
||||||
*
|
*
|
||||||
* Gets a control flow node for a return value of this function.
|
* Gets a control flow node for a return value of this function, from the
|
||||||
|
* new (shared) CFG.
|
||||||
*/
|
*/
|
||||||
deprecated ControlFlowNode getAReturnValueFlowNode() {
|
deprecated Cfg::ControlFlowNode getAReturnValueFlowNode() {
|
||||||
exists(Return ret |
|
exists(Return ret |
|
||||||
ret.getScope() = this and
|
ret.getScope() = this and
|
||||||
ret.getValue() = result.getNode()
|
ret.getValue() = result.getNode()
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ module;
|
|||||||
import python
|
import python
|
||||||
private import semmle.python.types.Builtins
|
private import semmle.python.types.Builtins
|
||||||
private import semmle.python.internal.CachedStages
|
private import semmle.python.internal.CachedStages
|
||||||
|
private import semmle.python.controlflow.internal.Cfg as Cfg
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* An alias in an import statement, the `mod as name` part of `import mod as name`. May be artificial;
|
* An alias in an import statement, the `mod as name` part of `import mod as name`. May be artificial;
|
||||||
@@ -163,7 +164,7 @@ class ImportMember extends ImportMember_ {
|
|||||||
result = this.getModule().(ImportExpr).getImportedModuleName() + "." + this.getName()
|
result = this.getModule().(ImportExpr).getImportedModuleName() + "." + this.getName()
|
||||||
}
|
}
|
||||||
|
|
||||||
deprecated override ImportMemberNode getAFlowNode() { result = super.getAFlowNode() }
|
deprecated override Cfg::ImportMemberNode getAFlowNode() { result = super.getAFlowNode() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/** An import statement */
|
/** An import statement */
|
||||||
|
|||||||
1613
python/ql/lib/semmle/python/controlflow/internal/AstNodeImpl.qll
Normal file
1613
python/ql/lib/semmle/python/controlflow/internal/AstNodeImpl.qll
Normal file
File diff suppressed because it is too large
Load Diff
1023
python/ql/lib/semmle/python/controlflow/internal/Cfg.qll
Normal file
1023
python/ql/lib/semmle/python/controlflow/internal/Cfg.qll
Normal file
File diff suppressed because it is too large
Load Diff
@@ -1,11 +1,12 @@
|
|||||||
/** Provides commonly used BarrierGuards. */
|
/** Provides commonly used BarrierGuards. */
|
||||||
|
|
||||||
private import python
|
private import python
|
||||||
|
private import semmle.python.controlflow.internal.Cfg as Cfg
|
||||||
private import semmle.python.dataflow.new.DataFlow
|
private import semmle.python.dataflow.new.DataFlow
|
||||||
|
|
||||||
private predicate constCompare(DataFlow::GuardNode g, ControlFlowNode node, boolean branch) {
|
private predicate constCompare(DataFlow::GuardNode g, Cfg::ControlFlowNode node, boolean branch) {
|
||||||
exists(CompareNode cn | cn = g |
|
exists(Cfg::CompareNode cn | cn = g |
|
||||||
exists(ImmutableLiteral const, Cmpop op, ControlFlowNode c |
|
exists(ImmutableLiteral const, Cmpop op, Cfg::ControlFlowNode c |
|
||||||
c.getNode() = const and
|
c.getNode() = const and
|
||||||
(
|
(
|
||||||
op = any(Eq eq) and branch = true
|
op = any(Eq eq) and branch = true
|
||||||
@@ -18,7 +19,7 @@ private predicate constCompare(DataFlow::GuardNode g, ControlFlowNode node, bool
|
|||||||
cn.operands(node, op, c)
|
cn.operands(node, op, c)
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
exists(NameConstant const, Cmpop op, ControlFlowNode c |
|
exists(NameConstant const, Cmpop op, Cfg::ControlFlowNode c |
|
||||||
c.getNode() = const and
|
c.getNode() = const and
|
||||||
(
|
(
|
||||||
op = any(Is is_) and branch = true
|
op = any(Is is_) and branch = true
|
||||||
@@ -31,12 +32,12 @@ private predicate constCompare(DataFlow::GuardNode g, ControlFlowNode node, bool
|
|||||||
cn.operands(node, op, c)
|
cn.operands(node, op, c)
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
exists(IterableNode const_iterable, Cmpop op |
|
exists(Cfg::IterableNode const_iterable, Cmpop op |
|
||||||
op = any(In in_) and branch = true
|
op = any(In in_) and branch = true
|
||||||
or
|
or
|
||||||
op = any(NotIn ni) and branch = false
|
op = any(NotIn ni) and branch = false
|
||||||
|
|
|
|
||||||
forall(ControlFlowNode elem | elem = const_iterable.getAnElement() |
|
forall(Cfg::ControlFlowNode elem | elem = const_iterable.getAnElement() |
|
||||||
elem.getNode() instanceof ImmutableLiteral
|
elem.getNode() instanceof ImmutableLiteral
|
||||||
) and
|
) and
|
||||||
cn.operands(node, op, const_iterable)
|
cn.operands(node, op, const_iterable)
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
private import python
|
private import python
|
||||||
|
private import semmle.python.controlflow.internal.Cfg as Cfg
|
||||||
private import semmle.python.dataflow.new.DataFlow
|
private import semmle.python.dataflow.new.DataFlow
|
||||||
// Need to import `semmle.python.Frameworks` since frameworks can extend `SensitiveDataSource::Range`
|
// Need to import `semmle.python.Frameworks` since frameworks can extend `SensitiveDataSource::Range`
|
||||||
private import semmle.python.Frameworks
|
private import semmle.python.Frameworks
|
||||||
@@ -105,7 +106,7 @@ private module SensitiveDataModeling {
|
|||||||
or
|
or
|
||||||
// to cover functions that we don't have the definition for, and where the
|
// to cover functions that we don't have the definition for, and where the
|
||||||
// reference to the function has not already been marked as being sensitive
|
// reference to the function has not already been marked as being sensitive
|
||||||
this.getFunction().asCfgNode().(NameNode).getId() = sensitiveString(classification)
|
this.getFunction().asCfgNode().(Cfg::NameNode).getId() = sensitiveString(classification)
|
||||||
}
|
}
|
||||||
|
|
||||||
override SensitiveDataClassification getClassification() { result = classification }
|
override SensitiveDataClassification getClassification() { result = classification }
|
||||||
@@ -251,12 +252,12 @@ private module SensitiveDataModeling {
|
|||||||
SensitiveDataClassification classification;
|
SensitiveDataClassification classification;
|
||||||
|
|
||||||
SensitiveVariableAssignment() {
|
SensitiveVariableAssignment() {
|
||||||
exists(DefinitionNode def |
|
exists(Cfg::DefinitionNode def |
|
||||||
def.(NameNode).getId() = sensitiveString(classification) and
|
def.(Cfg::NameNode).getId() = sensitiveString(classification) and
|
||||||
(
|
(
|
||||||
this.asCfgNode() = def.getValue()
|
this.asCfgNode() = def.getValue()
|
||||||
or
|
or
|
||||||
this.asCfgNode() = def.getValue().(ForNode).getSequence()
|
this.asCfgNode() = def.getValue().(Cfg::ForNode).getSequence()
|
||||||
) and
|
) and
|
||||||
not this.asExpr() instanceof FunctionExpr and
|
not this.asExpr() instanceof FunctionExpr and
|
||||||
not this.asExpr() instanceof ClassExpr
|
not this.asExpr() instanceof ClassExpr
|
||||||
@@ -293,7 +294,7 @@ private module SensitiveDataModeling {
|
|||||||
SensitiveDataClassification classification;
|
SensitiveDataClassification classification;
|
||||||
|
|
||||||
SensitiveSubscript() {
|
SensitiveSubscript() {
|
||||||
this.asCfgNode().(SubscriptNode).getIndex() =
|
this.asCfgNode().(Cfg::SubscriptNode).getIndex() =
|
||||||
sensitiveLookupStringConst(classification).asCfgNode()
|
sensitiveLookupStringConst(classification).asCfgNode()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ overlay[local]
|
|||||||
module;
|
module;
|
||||||
|
|
||||||
private import python
|
private import python
|
||||||
|
private import semmle.python.controlflow.internal.Cfg as Cfg
|
||||||
import DataFlowUtil
|
import DataFlowUtil
|
||||||
import DataFlowPublic
|
import DataFlowPublic
|
||||||
private import DataFlowPrivate
|
private import DataFlowPrivate
|
||||||
@@ -83,9 +84,9 @@ abstract class AttrWrite extends AttrRef {
|
|||||||
* ```python
|
* ```python
|
||||||
* object.attr = value
|
* object.attr = value
|
||||||
* ```
|
* ```
|
||||||
* Also gives access to the `value` being written, by extending `DefinitionNode`.
|
* Also gives access to the `value` being written, by extending `Cfg::DefinitionNode`.
|
||||||
*/
|
*/
|
||||||
private class AttributeAssignmentNode extends DefinitionNode, AttrNode { }
|
private class AttributeAssignmentNode extends Cfg::DefinitionNode, Cfg::AttrNode { }
|
||||||
|
|
||||||
/** A simple attribute assignment: `object.attr = value`. */
|
/** A simple attribute assignment: `object.attr = value`. */
|
||||||
private class AttributeAssignmentAsAttrWrite extends AttrWrite, CfgNode {
|
private class AttributeAssignmentAsAttrWrite extends AttrWrite, CfgNode {
|
||||||
@@ -131,13 +132,13 @@ private class GlobalAttributeAssignmentAsAttrWrite extends AttrWrite, CfgNode {
|
|||||||
override string getAttributeName() { result = node.getName() }
|
override string getAttributeName() { result = node.getName() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Represents `CallNode`s that may refer to calls to built-in functions or classes. */
|
/** Represents `Cfg::CallNode`s that may refer to calls to built-in functions or classes. */
|
||||||
private class BuiltInCallNode extends CallNode {
|
private class BuiltInCallNode extends Cfg::CallNode {
|
||||||
string name;
|
string name;
|
||||||
|
|
||||||
BuiltInCallNode() {
|
BuiltInCallNode() {
|
||||||
// TODO disallow instances where the name of the built-in may refer to an in-scope variable of that name.
|
// TODO disallow instances where the name of the built-in may refer to an in-scope variable of that name.
|
||||||
exists(NameNode id |
|
exists(Cfg::NameNode id |
|
||||||
name = Builtins::getBuiltinName() and
|
name = Builtins::getBuiltinName() and
|
||||||
this.getFunction() = id and
|
this.getFunction() = id and
|
||||||
id.getId() = name and
|
id.getId() = name and
|
||||||
@@ -145,7 +146,7 @@ private class BuiltInCallNode extends CallNode {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Gets the name of the built-in function that is called at this `CallNode` */
|
/** Gets the name of the built-in function that is called at this `Cfg::CallNode` */
|
||||||
string getBuiltinName() { result = name }
|
string getBuiltinName() { result = name }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -157,20 +158,20 @@ private class BuiltinAttrCallNode extends BuiltInCallNode {
|
|||||||
BuiltinAttrCallNode() { name in ["setattr", "getattr", "hasattr", "delattr"] }
|
BuiltinAttrCallNode() { name in ["setattr", "getattr", "hasattr", "delattr"] }
|
||||||
|
|
||||||
/** Gets the control flow node for object on which the attribute is accessed. */
|
/** Gets the control flow node for object on which the attribute is accessed. */
|
||||||
ControlFlowNode getObject() { result in [this.getArg(0), this.getArgByName("object")] }
|
Cfg::ControlFlowNode getObject() { result in [this.getArg(0), this.getArgByName("object")] }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the control flow node for the value that is being written to the attribute.
|
* Gets the control flow node for the value that is being written to the attribute.
|
||||||
* Only relevant for `setattr` calls.
|
* Only relevant for `setattr` calls.
|
||||||
*/
|
*/
|
||||||
ControlFlowNode getValue() {
|
Cfg::ControlFlowNode getValue() {
|
||||||
// only valid for `setattr`
|
// only valid for `setattr`
|
||||||
name = "setattr" and
|
name = "setattr" and
|
||||||
result in [this.getArg(2), this.getArgByName("value")]
|
result in [this.getArg(2), this.getArgByName("value")]
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Gets the control flow node that defines the name of the attribute being accessed. */
|
/** Gets the control flow node that defines the name of the attribute being accessed. */
|
||||||
ControlFlowNode getName() { result in [this.getArg(1), this.getArgByName("name")] }
|
Cfg::ControlFlowNode getName() { result in [this.getArg(1), this.getArgByName("name")] }
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Represents calls to the built-in `setattr`. */
|
/** Represents calls to the built-in `setattr`. */
|
||||||
@@ -205,10 +206,10 @@ private class SetAttrCallAsAttrWrite extends AttrWrite, CfgNode {
|
|||||||
* attr = value
|
* attr = value
|
||||||
* ...
|
* ...
|
||||||
* ```
|
* ```
|
||||||
* Instances of this class correspond to the `NameNode` for `attr`, and also gives access to `value` by
|
* Instances of this class correspond to the `Cfg::NameNode` for `attr`, and also gives access to `value` by
|
||||||
* virtue of being a `DefinitionNode`.
|
* virtue of being a `Cfg::DefinitionNode`.
|
||||||
*/
|
*/
|
||||||
private class ClassAttributeAssignmentNode extends DefinitionNode, NameNode {
|
private class ClassAttributeAssignmentNode extends Cfg::DefinitionNode, Cfg::NameNode {
|
||||||
ClassAttributeAssignmentNode() { this.getScope() = any(ClassExpr c).getInnerScope() }
|
ClassAttributeAssignmentNode() { this.getScope() = any(ClassExpr c).getInnerScope() }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -248,7 +249,7 @@ abstract class AttrRead extends AttrRef, Node, LocalSourceNode {
|
|||||||
|
|
||||||
/** A simple attribute read, e.g. `object.attr` */
|
/** A simple attribute read, e.g. `object.attr` */
|
||||||
private class AttributeReadAsAttrRead extends AttrRead, CfgNode {
|
private class AttributeReadAsAttrRead extends AttrRead, CfgNode {
|
||||||
override AttrNode node;
|
override Cfg::AttrNode node;
|
||||||
|
|
||||||
AttributeReadAsAttrRead() { node.isLoad() }
|
AttributeReadAsAttrRead() { node.isLoad() }
|
||||||
|
|
||||||
@@ -285,7 +286,7 @@ private class GetAttrCallAsAttrRead extends AttrRead, CfgNode {
|
|||||||
* is treated as if it is a read of the attribute `module.attr`, even if `module` is not imported directly.
|
* is treated as if it is a read of the attribute `module.attr`, even if `module` is not imported directly.
|
||||||
*/
|
*/
|
||||||
private class ModuleAttributeImportAsAttrRead extends AttrRead, CfgNode {
|
private class ModuleAttributeImportAsAttrRead extends AttrRead, CfgNode {
|
||||||
override ImportMemberNode node;
|
override Cfg::ImportMemberNode node;
|
||||||
|
|
||||||
override Node getObject() { result.asCfgNode() = node.getModule(_) }
|
override Node getObject() { result.asCfgNode() = node.getModule(_) }
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ overlay[local]
|
|||||||
module;
|
module;
|
||||||
|
|
||||||
private import python
|
private import python
|
||||||
|
private import semmle.python.controlflow.internal.Cfg as Cfg
|
||||||
private import semmle.python.dataflow.new.DataFlow
|
private import semmle.python.dataflow.new.DataFlow
|
||||||
private import semmle.python.dataflow.new.internal.ImportStar
|
private import semmle.python.dataflow.new.internal.ImportStar
|
||||||
|
|
||||||
@@ -67,7 +68,7 @@ module Builtins {
|
|||||||
DataFlow::CfgNode likelyBuiltin(string name) {
|
DataFlow::CfgNode likelyBuiltin(string name) {
|
||||||
exists(Module m |
|
exists(Module m |
|
||||||
result.getNode() =
|
result.getNode() =
|
||||||
any(NameNode n |
|
any(Cfg::NameNode n |
|
||||||
possible_builtin_accessed_in_module(n, name, m) and
|
possible_builtin_accessed_in_module(n, name, m) and
|
||||||
not possible_builtin_defined_in_module(name, m)
|
not possible_builtin_defined_in_module(name, m)
|
||||||
)
|
)
|
||||||
@@ -87,7 +88,7 @@ module Builtins {
|
|||||||
* Holds if `n` is an access of a global variable called `name` (which is also the name of a
|
* Holds if `n` is an access of a global variable called `name` (which is also the name of a
|
||||||
* built-in) inside the module `m`.
|
* built-in) inside the module `m`.
|
||||||
*/
|
*/
|
||||||
private predicate possible_builtin_accessed_in_module(NameNode n, string name, Module m) {
|
private predicate possible_builtin_accessed_in_module(Cfg::NameNode n, string name, Module m) {
|
||||||
n.isGlobal() and
|
n.isGlobal() and
|
||||||
n.isLoad() and
|
n.isLoad() and
|
||||||
name = n.getId() and
|
name = n.getId() and
|
||||||
|
|||||||
@@ -25,7 +25,7 @@
|
|||||||
* what callable this call might end up targeting.
|
* what callable this call might end up targeting.
|
||||||
*
|
*
|
||||||
* Specifically this means that we cannot use type-backtrackers from the function of a
|
* Specifically this means that we cannot use type-backtrackers from the function of a
|
||||||
* `CallNode`, since there is no `CallNode` to backtrack from for `func` in the example
|
* `Cfg::CallNode`, since there is no `Cfg::CallNode` to backtrack from for `func` in the example
|
||||||
* above.
|
* above.
|
||||||
*
|
*
|
||||||
* Note: This hasn't been 100% realized yet, so we don't currently expose a predicate to
|
* Note: This hasn't been 100% realized yet, so we don't currently expose a predicate to
|
||||||
@@ -35,6 +35,7 @@ overlay[local?]
|
|||||||
module;
|
module;
|
||||||
|
|
||||||
private import python
|
private import python
|
||||||
|
private import semmle.python.controlflow.internal.Cfg as Cfg
|
||||||
private import DataFlowPublic
|
private import DataFlowPublic
|
||||||
private import DataFlowPrivate
|
private import DataFlowPrivate
|
||||||
private import FlowSummaryImpl as FlowSummaryImpl
|
private import FlowSummaryImpl as FlowSummaryImpl
|
||||||
@@ -162,7 +163,7 @@ newtype TArgumentPosition =
|
|||||||
*/
|
*/
|
||||||
TLambdaSelfArgumentPosition() or
|
TLambdaSelfArgumentPosition() or
|
||||||
TPositionalArgumentPosition(int index) {
|
TPositionalArgumentPosition(int index) {
|
||||||
exists(any(CallNode c).getArg(index))
|
exists(any(Cfg::CallNode c).getArg(index))
|
||||||
or
|
or
|
||||||
// since synthetic calls within a summarized callable could use a unique argument
|
// since synthetic calls within a summarized callable could use a unique argument
|
||||||
// position, we need to ensure we make these available (these are specified as
|
// position, we need to ensure we make these available (these are specified as
|
||||||
@@ -174,7 +175,7 @@ newtype TArgumentPosition =
|
|||||||
index = 0
|
index = 0
|
||||||
} or
|
} or
|
||||||
TKeywordArgumentPosition(string name) {
|
TKeywordArgumentPosition(string name) {
|
||||||
exists(any(CallNode c).getArgByName(name))
|
exists(any(Cfg::CallNode c).getArgByName(name))
|
||||||
or
|
or
|
||||||
// see comment for TPositionalArgumentPosition
|
// see comment for TPositionalArgumentPosition
|
||||||
FlowSummaryImpl::ParsePositions::isParsedKeywordParameterPosition(_, name)
|
FlowSummaryImpl::ParsePositions::isParsedKeywordParameterPosition(_, name)
|
||||||
@@ -297,10 +298,12 @@ predicate hasPropertyDecorator(Function func) {
|
|||||||
*/
|
*/
|
||||||
overlay[local]
|
overlay[local]
|
||||||
predicate hasContextmanagerDecorator(Function func) {
|
predicate hasContextmanagerDecorator(Function func) {
|
||||||
exists(ControlFlowNode contextmanager |
|
exists(Cfg::ControlFlowNode contextmanager |
|
||||||
contextmanager.(NameNode).getId() = "contextmanager" and contextmanager.(NameNode).isGlobal()
|
contextmanager.(Cfg::NameNode).getId() = "contextmanager" and
|
||||||
|
contextmanager.(Cfg::NameNode).isGlobal()
|
||||||
or
|
or
|
||||||
contextmanager.(AttrNode).getObject("contextmanager").(NameNode).getId() = "contextlib"
|
contextmanager.(Cfg::AttrNode).getObject("contextmanager").(Cfg::NameNode).getId() =
|
||||||
|
"contextlib"
|
||||||
|
|
|
|
||||||
func.getADecorator() = contextmanager.getNode()
|
func.getADecorator() = contextmanager.getNode()
|
||||||
)
|
)
|
||||||
@@ -316,10 +319,10 @@ predicate hasContextmanagerDecorator(Function func) {
|
|||||||
*/
|
*/
|
||||||
overlay[local]
|
overlay[local]
|
||||||
private predicate hasOverloadDecorator(Function func) {
|
private predicate hasOverloadDecorator(Function func) {
|
||||||
exists(ControlFlowNode overload |
|
exists(Cfg::ControlFlowNode overload |
|
||||||
overload.(NameNode).getId() = "overload" and overload.(NameNode).isGlobal()
|
overload.(Cfg::NameNode).getId() = "overload" and overload.(Cfg::NameNode).isGlobal()
|
||||||
or
|
or
|
||||||
overload.(AttrNode).getObject("overload").(NameNode).isGlobal()
|
overload.(Cfg::AttrNode).getObject("overload").(Cfg::NameNode).isGlobal()
|
||||||
|
|
|
|
||||||
func.getADecorator() = overload.getNode()
|
func.getADecorator() = overload.getNode()
|
||||||
)
|
)
|
||||||
@@ -538,7 +541,7 @@ class LibraryCallableValue extends DataFlowCallable, TLibraryCallable {
|
|||||||
// =============================================================================
|
// =============================================================================
|
||||||
/** Gets a call to `type`. */
|
/** Gets a call to `type`. */
|
||||||
private CallCfgNode getTypeCall() {
|
private CallCfgNode getTypeCall() {
|
||||||
exists(NameNode id | id.getId() = "type" and id.isGlobal() |
|
exists(Cfg::NameNode id | id.getId() = "type" and id.isGlobal() |
|
||||||
result.getFunction().asCfgNode() = id
|
result.getFunction().asCfgNode() = id
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -550,7 +553,7 @@ private CallCfgNode getSuperCall() {
|
|||||||
// link below), but otherwise only 2 edgecases. Overall it seems ok to ignore this complexity.
|
// link below), but otherwise only 2 edgecases. Overall it seems ok to ignore this complexity.
|
||||||
//
|
//
|
||||||
// https://github.com/python/cpython/blob/18b1782192f85bd26db89f5bc850f8bee4247c1a/Lib/unittest/mock.py#L48-L50
|
// https://github.com/python/cpython/blob/18b1782192f85bd26db89f5bc850f8bee4247c1a/Lib/unittest/mock.py#L48-L50
|
||||||
exists(NameNode id | id.getId() = "super" and id.isGlobal() |
|
exists(Cfg::NameNode id | id.getId() = "super" and id.isGlobal() |
|
||||||
result.getFunction().asCfgNode() = id
|
result.getFunction().asCfgNode() = id
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -1036,7 +1039,7 @@ private module MethodCalls {
|
|||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate directCall(
|
private predicate directCall(
|
||||||
CallNode call, Function target, string functionName, Class cls, AttrRead attr, Node self
|
Cfg::CallNode call, Function target, string functionName, Class cls, AttrRead attr, Node self
|
||||||
) {
|
) {
|
||||||
target = findFunctionAccordingToMroKnownStartingClass(cls, functionName) and
|
target = findFunctionAccordingToMroKnownStartingClass(cls, functionName) and
|
||||||
directCall_join(call, functionName, cls, attr, self)
|
directCall_join(call, functionName, cls, attr, self)
|
||||||
@@ -1045,7 +1048,7 @@ private module MethodCalls {
|
|||||||
/** Extracted to give good join order */
|
/** Extracted to give good join order */
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate directCall_join(
|
private predicate directCall_join(
|
||||||
CallNode call, string functionName, Class cls, AttrRead attr, Node self
|
Cfg::CallNode call, string functionName, Class cls, AttrRead attr, Node self
|
||||||
) {
|
) {
|
||||||
call.getFunction() = attrReadTracker(attr).asCfgNode() and
|
call.getFunction() = attrReadTracker(attr).asCfgNode() and
|
||||||
attr.accesses(self, functionName) and
|
attr.accesses(self, functionName) and
|
||||||
@@ -1062,7 +1065,7 @@ private module MethodCalls {
|
|||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate callWithinMethodImplicitSelfOrCls(
|
private predicate callWithinMethodImplicitSelfOrCls(
|
||||||
CallNode call, Function target, string functionName, Class classWithMethod, AttrRead attr,
|
Cfg::CallNode call, Function target, string functionName, Class classWithMethod, AttrRead attr,
|
||||||
Node self
|
Node self
|
||||||
) {
|
) {
|
||||||
target = findFunctionAccordingToMro(getADirectSubclass*(classWithMethod), functionName) and
|
target = findFunctionAccordingToMro(getADirectSubclass*(classWithMethod), functionName) and
|
||||||
@@ -1072,7 +1075,7 @@ private module MethodCalls {
|
|||||||
/** Extracted to give good join order */
|
/** Extracted to give good join order */
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate callWithinMethodImplicitSelfOrCls_join(
|
private predicate callWithinMethodImplicitSelfOrCls_join(
|
||||||
CallNode call, string functionName, Class classWithMethod, AttrRead attr, Node self
|
Cfg::CallNode call, string functionName, Class classWithMethod, AttrRead attr, Node self
|
||||||
) {
|
) {
|
||||||
call.getFunction() = attrReadTracker(attr).asCfgNode() and
|
call.getFunction() = attrReadTracker(attr).asCfgNode() and
|
||||||
attr.accesses(self, functionName) and
|
attr.accesses(self, functionName) and
|
||||||
@@ -1084,7 +1087,7 @@ private module MethodCalls {
|
|||||||
* resolve the call to a known target (since the only super class might be the
|
* resolve the call to a known target (since the only super class might be the
|
||||||
* builtin `object`, so we never have the implementation of `__new__` in the DB).
|
* builtin `object`, so we never have the implementation of `__new__` in the DB).
|
||||||
*/
|
*/
|
||||||
predicate fromSuperNewCall(CallNode call, Class classUsedInSuper, AttrRead attr, Node self) {
|
predicate fromSuperNewCall(Cfg::CallNode call, Class classUsedInSuper, AttrRead attr, Node self) {
|
||||||
fromSuper_join(call, "__new__", classUsedInSuper, attr, self) and
|
fromSuper_join(call, "__new__", classUsedInSuper, attr, self) and
|
||||||
self in [classTracker(_), clsArgumentTracker(_)]
|
self in [classTracker(_), clsArgumentTracker(_)]
|
||||||
}
|
}
|
||||||
@@ -1106,7 +1109,7 @@ private module MethodCalls {
|
|||||||
*/
|
*/
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
predicate fromSuper(
|
predicate fromSuper(
|
||||||
CallNode call, Function target, string functionName, Class classUsedInSuper, AttrRead attr,
|
Cfg::CallNode call, Function target, string functionName, Class classUsedInSuper, AttrRead attr,
|
||||||
Node self
|
Node self
|
||||||
) {
|
) {
|
||||||
target = findFunctionAccordingToMro(getNextClassInMro(classUsedInSuper), functionName) and
|
target = findFunctionAccordingToMro(getNextClassInMro(classUsedInSuper), functionName) and
|
||||||
@@ -1116,7 +1119,7 @@ private module MethodCalls {
|
|||||||
/** Extracted to give good join order */
|
/** Extracted to give good join order */
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate fromSuper_join(
|
private predicate fromSuper_join(
|
||||||
CallNode call, string functionName, Class classUsedInSuper, AttrRead attr, Node self
|
Cfg::CallNode call, string functionName, Class classUsedInSuper, AttrRead attr, Node self
|
||||||
) {
|
) {
|
||||||
call.getFunction() = attrReadTracker(attr).asCfgNode() and
|
call.getFunction() = attrReadTracker(attr).asCfgNode() and
|
||||||
(
|
(
|
||||||
@@ -1135,7 +1138,7 @@ private module MethodCalls {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
predicate resolveMethodCall(CallNode call, Function target, CallType type, Node self) {
|
predicate resolveMethodCall(Cfg::CallNode call, Function target, CallType type, Node self) {
|
||||||
(
|
(
|
||||||
directCall(call, target, _, _, _, self)
|
directCall(call, target, _, _, _, self)
|
||||||
or
|
or
|
||||||
@@ -1182,7 +1185,7 @@ import MethodCalls
|
|||||||
* NOTE: We have this predicate mostly to be able to compare with old point-to
|
* NOTE: We have this predicate mostly to be able to compare with old point-to
|
||||||
* call-graph resolution. So it could be removed in the future.
|
* call-graph resolution. So it could be removed in the future.
|
||||||
*/
|
*/
|
||||||
predicate resolveClassCall(CallNode call, Class cls) {
|
predicate resolveClassCall(Cfg::CallNode call, Class cls) {
|
||||||
call.getFunction() = classTracker(cls).asCfgNode()
|
call.getFunction() = classTracker(cls).asCfgNode()
|
||||||
or
|
or
|
||||||
// `cls()` inside a classmethod (which also contains `type(self)()` inside a method)
|
// `cls()` inside a classmethod (which also contains `type(self)()` inside a method)
|
||||||
@@ -1212,7 +1215,7 @@ Function invokedFunctionFromClassConstruction(Class cls, string funcName) {
|
|||||||
*
|
*
|
||||||
* See https://docs.python.org/3/reference/datamodel.html#object.__call__
|
* See https://docs.python.org/3/reference/datamodel.html#object.__call__
|
||||||
*/
|
*/
|
||||||
predicate resolveClassInstanceCall(CallNode call, Function target, Node self) {
|
predicate resolveClassInstanceCall(Cfg::CallNode call, Function target, Node self) {
|
||||||
exists(Class cls |
|
exists(Class cls |
|
||||||
call.getFunction() = classInstanceTracker(cls).asCfgNode() and
|
call.getFunction() = classInstanceTracker(cls).asCfgNode() and
|
||||||
target = findFunctionAccordingToMroKnownStartingClass(cls, "__call__")
|
target = findFunctionAccordingToMroKnownStartingClass(cls, "__call__")
|
||||||
@@ -1231,7 +1234,7 @@ predicate resolveClassInstanceCall(CallNode call, Function target, Node self) {
|
|||||||
* Holds if `call` is a call to the `target`, with call-type `type`.
|
* Holds if `call` is a call to the `target`, with call-type `type`.
|
||||||
*/
|
*/
|
||||||
cached
|
cached
|
||||||
predicate resolveCall(CallNode call, Function target, CallType type) {
|
predicate resolveCall(Cfg::CallNode call, Function target, CallType type) {
|
||||||
Stages::DataFlow::ref() and
|
Stages::DataFlow::ref() and
|
||||||
(
|
(
|
||||||
type instanceof CallTypePlainFunction and
|
type instanceof CallTypePlainFunction and
|
||||||
@@ -1256,11 +1259,11 @@ predicate resolveCall(CallNode call, Function target, CallType type) {
|
|||||||
// =============================================================================
|
// =============================================================================
|
||||||
/**
|
/**
|
||||||
* Holds if the argument of `call` at position `apos` is `arg`. This is just a helper
|
* Holds if the argument of `call` at position `apos` is `arg`. This is just a helper
|
||||||
* predicate that maps ArgumentPositions to the arguments of the underlying `CallNode`.
|
* predicate that maps ArgumentPositions to the arguments of the underlying `Cfg::CallNode`.
|
||||||
*/
|
*/
|
||||||
overlay[local]
|
overlay[local]
|
||||||
cached
|
cached
|
||||||
predicate normalCallArg(CallNode call, Node arg, ArgumentPosition apos) {
|
predicate normalCallArg(Cfg::CallNode call, Node arg, ArgumentPosition apos) {
|
||||||
exists(int index |
|
exists(int index |
|
||||||
apos.isPositional(index) and
|
apos.isPositional(index) and
|
||||||
arg.asCfgNode() = call.getArg(index)
|
arg.asCfgNode() = call.getArg(index)
|
||||||
@@ -1275,7 +1278,7 @@ predicate normalCallArg(CallNode call, Node arg, ArgumentPosition apos) {
|
|||||||
exists(int index |
|
exists(int index |
|
||||||
apos.isStarArgs(index) and
|
apos.isStarArgs(index) and
|
||||||
arg.asCfgNode() = call.getStarArg() and
|
arg.asCfgNode() = call.getStarArg() and
|
||||||
// since `CallNode.getArg` doesn't include `*args`, we need to drop to the AST level
|
// since `Cfg::CallNode.getArg` doesn't include `*args`, we need to drop to the AST level
|
||||||
// to get the index. Notice that we only use the AST for getting the index, so we
|
// to get the index. Notice that we only use the AST for getting the index, so we
|
||||||
// don't need to check for dominance in regards to splitting.
|
// don't need to check for dominance in regards to splitting.
|
||||||
call.getStarArg().getNode() = call.getNode().getPositionalArg(index).(Starred).getValue()
|
call.getStarArg().getNode() = call.getNode().getPositionalArg(index).(Starred).getValue()
|
||||||
@@ -1349,7 +1352,9 @@ predicate normalCallArg(CallNode call, Node arg, ArgumentPosition apos) {
|
|||||||
* translated into `l.clear()`, and we can still have use-use flow.
|
* translated into `l.clear()`, and we can still have use-use flow.
|
||||||
*/
|
*/
|
||||||
cached
|
cached
|
||||||
predicate getCallArg(CallNode call, Function target, CallType type, Node arg, ArgumentPosition apos) {
|
predicate getCallArg(
|
||||||
|
Cfg::CallNode call, Function target, CallType type, Node arg, ArgumentPosition apos
|
||||||
|
) {
|
||||||
Stages::DataFlow::ref() and
|
Stages::DataFlow::ref() and
|
||||||
resolveCall(call, target, type) and
|
resolveCall(call, target, type) and
|
||||||
(
|
(
|
||||||
@@ -1442,10 +1447,12 @@ private predicate sameEnclosingCallable(Node node1, Node node2) {
|
|||||||
// DataFlowCall
|
// DataFlowCall
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
newtype TDataFlowCall =
|
newtype TDataFlowCall =
|
||||||
TNormalCall(CallNode call, Function target, CallType type) { resolveCall(call, target, type) } or
|
TNormalCall(Cfg::CallNode call, Function target, CallType type) {
|
||||||
|
call.injects(_) and resolveCall(call, target, type)
|
||||||
|
} or
|
||||||
/** A call to the generated function inside a comprehension */
|
/** A call to the generated function inside a comprehension */
|
||||||
TComprehensionCall(Comp c) or
|
TComprehensionCall(Comp c) or
|
||||||
TPotentialLibraryCall(CallNode call) or
|
TPotentialLibraryCall(Cfg::CallNode call) { call.injects(_) } or
|
||||||
/** A synthesized call inside a summarized callable */
|
/** A synthesized call inside a summarized callable */
|
||||||
TSummaryCall(
|
TSummaryCall(
|
||||||
FlowSummaryImpl::Public::SummarizedCallable c, FlowSummaryImpl::Private::SummaryNode receiver
|
FlowSummaryImpl::Public::SummarizedCallable c, FlowSummaryImpl::Private::SummaryNode receiver
|
||||||
@@ -1465,7 +1472,7 @@ abstract class DataFlowCall extends TDataFlowCall {
|
|||||||
abstract ArgumentNode getArgument(ArgumentPosition apos);
|
abstract ArgumentNode getArgument(ArgumentPosition apos);
|
||||||
|
|
||||||
/** Get the control flow node representing this call, if any. */
|
/** Get the control flow node representing this call, if any. */
|
||||||
abstract ControlFlowNode getNode();
|
abstract Cfg::ControlFlowNode getNode();
|
||||||
|
|
||||||
/** Gets the enclosing callable of this call. */
|
/** Gets the enclosing callable of this call. */
|
||||||
DataFlowCallable getEnclosingCallable() { result = getCallableScope(this.getScope()) }
|
DataFlowCallable getEnclosingCallable() { result = getCallableScope(this.getScope()) }
|
||||||
@@ -1496,28 +1503,28 @@ abstract class ExtractedDataFlowCall extends DataFlowCall {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A resolved call in source code with an underlying `CallNode`.
|
* A resolved call in source code with an underlying `Cfg::CallNode`.
|
||||||
*
|
*
|
||||||
* This is considered normal, compared with special calls such as `obj[0]` calling the
|
* This is considered normal, compared with special calls such as `obj[0]` calling the
|
||||||
* `__getitem__` method on the object. However, this also includes calls that go to the
|
* `__getitem__` method on the object. However, this also includes calls that go to the
|
||||||
* `__call__` special method.
|
* `__call__` special method.
|
||||||
*/
|
*/
|
||||||
class NormalCall extends ExtractedDataFlowCall, TNormalCall {
|
class NormalCall extends ExtractedDataFlowCall, TNormalCall {
|
||||||
CallNode call;
|
Cfg::CallNode call;
|
||||||
Function target;
|
Function target;
|
||||||
CallType type;
|
CallType type;
|
||||||
|
|
||||||
NormalCall() { this = TNormalCall(call, target, type) }
|
NormalCall() { this = TNormalCall(call, target, type) }
|
||||||
|
|
||||||
override string toString() {
|
override string toString() {
|
||||||
// note: if we used toString directly on the CallNode we would get
|
// note: if we used toString directly on the Cfg::CallNode we would get
|
||||||
// `ControlFlowNode for func()`
|
// `Cfg::ControlFlowNode for func()`
|
||||||
// but the `ControlFlowNode` part is just clutter, so we go directly to the AST node
|
// but the `Cfg::ControlFlowNode` part is just clutter, so we go directly to the AST node
|
||||||
// instead.
|
// instead.
|
||||||
result = call.getNode().toString()
|
result = call.getNode().toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
override ControlFlowNode getNode() { result = call }
|
override Cfg::ControlFlowNode getNode() { result = call }
|
||||||
|
|
||||||
override Scope getScope() { result = call.getScope() }
|
override Scope getScope() { result = call.getScope() }
|
||||||
|
|
||||||
@@ -1545,7 +1552,7 @@ class ComprehensionCall extends ExtractedDataFlowCall, TComprehensionCall {
|
|||||||
|
|
||||||
override string toString() { result = "comprehension call" }
|
override string toString() { result = "comprehension call" }
|
||||||
|
|
||||||
override ControlFlowNode getNode() { result.getNode() = c }
|
override Cfg::ControlFlowNode getNode() { result.getNode() = c }
|
||||||
|
|
||||||
override Scope getScope() { result = c.getScope() }
|
override Scope getScope() { result = c.getScope() }
|
||||||
|
|
||||||
@@ -1568,14 +1575,14 @@ class ComprehensionCall extends ExtractedDataFlowCall, TComprehensionCall {
|
|||||||
* in this class.
|
* in this class.
|
||||||
*/
|
*/
|
||||||
class PotentialLibraryCall extends ExtractedDataFlowCall, TPotentialLibraryCall {
|
class PotentialLibraryCall extends ExtractedDataFlowCall, TPotentialLibraryCall {
|
||||||
CallNode call;
|
Cfg::CallNode call;
|
||||||
|
|
||||||
PotentialLibraryCall() { this = TPotentialLibraryCall(call) }
|
PotentialLibraryCall() { this = TPotentialLibraryCall(call) }
|
||||||
|
|
||||||
override string toString() {
|
override string toString() {
|
||||||
// note: if we used toString directly on the CallNode we would get
|
// note: if we used toString directly on the Cfg::CallNode we would get
|
||||||
// `ControlFlowNode for func()`
|
// `Cfg::ControlFlowNode for func()`
|
||||||
// but the `ControlFlowNode` part is just clutter, so we go directly to the AST node
|
// but the `Cfg::ControlFlowNode` part is just clutter, so we go directly to the AST node
|
||||||
// instead.
|
// instead.
|
||||||
result = call.getNode().toString()
|
result = call.getNode().toString()
|
||||||
}
|
}
|
||||||
@@ -1592,10 +1599,10 @@ class PotentialLibraryCall extends ExtractedDataFlowCall, TPotentialLibraryCall
|
|||||||
// potential self argument, from `foo.bar()` -- note that this could also just be a
|
// potential self argument, from `foo.bar()` -- note that this could also just be a
|
||||||
// module reference, but we really don't have a good way of knowing :|
|
// module reference, but we really don't have a good way of knowing :|
|
||||||
apos.isSelf() and
|
apos.isSelf() and
|
||||||
result.asCfgNode() = call.getFunction().(AttrNode).getObject()
|
result.asCfgNode() = call.getFunction().(Cfg::AttrNode).getObject()
|
||||||
}
|
}
|
||||||
|
|
||||||
override ControlFlowNode getNode() { result = call }
|
override Cfg::ControlFlowNode getNode() { result = call }
|
||||||
|
|
||||||
override Scope getScope() { result = call.getScope() }
|
override Scope getScope() { result = call.getScope() }
|
||||||
}
|
}
|
||||||
@@ -1627,7 +1634,7 @@ class SummaryCall extends DataFlowCall, TSummaryCall {
|
|||||||
|
|
||||||
override ArgumentNode getArgument(ArgumentPosition apos) { none() }
|
override ArgumentNode getArgument(ArgumentPosition apos) { none() }
|
||||||
|
|
||||||
override ControlFlowNode getNode() { none() }
|
override Cfg::ControlFlowNode getNode() { none() }
|
||||||
|
|
||||||
override string toString() { result = "[summary] call to " + receiver + " in " + c }
|
override string toString() { result = "[summary] call to " + receiver + " in " + c }
|
||||||
|
|
||||||
@@ -1769,12 +1776,12 @@ private class SummaryPostUpdateNode extends FlowSummaryNode, PostUpdateNodeImpl
|
|||||||
* This is used for tracking flow through captured variables.
|
* This is used for tracking flow through captured variables.
|
||||||
*/
|
*/
|
||||||
class SynthCapturedVariablesArgumentNode extends Node, TSynthCapturedVariablesArgumentNode {
|
class SynthCapturedVariablesArgumentNode extends Node, TSynthCapturedVariablesArgumentNode {
|
||||||
ControlFlowNode callable;
|
Cfg::ControlFlowNode callable;
|
||||||
|
|
||||||
SynthCapturedVariablesArgumentNode() { this = TSynthCapturedVariablesArgumentNode(callable) }
|
SynthCapturedVariablesArgumentNode() { this = TSynthCapturedVariablesArgumentNode(callable) }
|
||||||
|
|
||||||
/** Gets the `CallNode` corresponding to this captured variables argument node. */
|
/** Gets the `Cfg::CallNode` corresponding to this captured variables argument node. */
|
||||||
CallNode getCallNode() { result.getFunction() = callable }
|
Cfg::CallNode getCallNode() { result.getFunction() = callable }
|
||||||
|
|
||||||
/** Gets the `CfgNode` that corresponds to this synthetic node. */
|
/** Gets the `CfgNode` that corresponds to this synthetic node. */
|
||||||
CfgNode getUnderlyingNode() { result.asCfgNode() = callable }
|
CfgNode getUnderlyingNode() { result.asCfgNode() = callable }
|
||||||
@@ -1792,7 +1799,7 @@ class CapturedVariablesArgumentNodeAsArgumentNode extends ArgumentNode,
|
|||||||
{
|
{
|
||||||
overlay[global]
|
overlay[global]
|
||||||
override predicate argumentOf(DataFlowCall call, ArgumentPosition pos) {
|
override predicate argumentOf(DataFlowCall call, ArgumentPosition pos) {
|
||||||
exists(CallNode callNode | callNode = this.getCallNode() |
|
exists(Cfg::CallNode callNode | callNode = this.getCallNode() |
|
||||||
callNode = call.getNode() and
|
callNode = call.getNode() and
|
||||||
exists(Function target | resolveCall(callNode, target, _) |
|
exists(Function target | resolveCall(callNode, target, _) |
|
||||||
target = any(VariableCapture::CapturedVariable v).getACapturingScope()
|
target = any(VariableCapture::CapturedVariable v).getACapturingScope()
|
||||||
@@ -1806,7 +1813,7 @@ class CapturedVariablesArgumentNodeAsArgumentNode extends ArgumentNode,
|
|||||||
class SynthCapturedVariablesArgumentPostUpdateNode extends PostUpdateNodeImpl,
|
class SynthCapturedVariablesArgumentPostUpdateNode extends PostUpdateNodeImpl,
|
||||||
TSynthCapturedVariablesArgumentPostUpdateNode
|
TSynthCapturedVariablesArgumentPostUpdateNode
|
||||||
{
|
{
|
||||||
ControlFlowNode callable;
|
Cfg::ControlFlowNode callable;
|
||||||
|
|
||||||
SynthCapturedVariablesArgumentPostUpdateNode() {
|
SynthCapturedVariablesArgumentPostUpdateNode() {
|
||||||
this = TSynthCapturedVariablesArgumentPostUpdateNode(callable)
|
this = TSynthCapturedVariablesArgumentPostUpdateNode(callable)
|
||||||
|
|||||||
@@ -2,8 +2,9 @@ overlay[local?]
|
|||||||
module;
|
module;
|
||||||
|
|
||||||
private import python
|
private import python
|
||||||
|
private import semmle.python.controlflow.internal.Cfg as Cfg
|
||||||
private import DataFlowPublic
|
private import DataFlowPublic
|
||||||
private import semmle.python.essa.SsaCompute
|
private import semmle.python.dataflow.new.internal.SsaImpl as SsaImpl
|
||||||
private import semmle.python.dataflow.new.internal.ImportResolution
|
private import semmle.python.dataflow.new.internal.ImportResolution
|
||||||
private import FlowSummaryImpl as FlowSummaryImpl
|
private import FlowSummaryImpl as FlowSummaryImpl
|
||||||
private import semmle.python.frameworks.data.ModelsAsData
|
private import semmle.python.frameworks.data.ModelsAsData
|
||||||
@@ -43,13 +44,28 @@ predicate isArgumentNode(ArgumentNode arg, DataFlowCall c, ArgumentPosition pos)
|
|||||||
// Nodes
|
// Nodes
|
||||||
//--------
|
//--------
|
||||||
overlay[local]
|
overlay[local]
|
||||||
predicate isExpressionNode(ControlFlowNode node) { node.getNode() instanceof Expr }
|
predicate isExpressionNode(Cfg::ControlFlowNode node) {
|
||||||
|
// Restrict to the `injects` representative so the dataflow layer creates
|
||||||
|
// exactly one `TCfgNode` per AST expression.
|
||||||
|
node.injects(_) and
|
||||||
|
(
|
||||||
|
node.getNode() instanceof Expr
|
||||||
|
or
|
||||||
|
// `Cfg::ForNode` wraps a `For` statement's iter position, but
|
||||||
|
// overrides `.getNode()` to return the `Py::For` statement (for
|
||||||
|
// legacy parity). The underlying AST is still an `Expr` (the iter
|
||||||
|
// expression); we want a dataflow node here so that for-loop
|
||||||
|
// content reads (`for y in l`) have a source expression node to
|
||||||
|
// read content from.
|
||||||
|
node instanceof Cfg::ForNode
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
// SyntheticPreUpdateNode
|
// SyntheticPreUpdateNode
|
||||||
// =============================================================================
|
// =============================================================================
|
||||||
class SyntheticPreUpdateNode extends Node, TSyntheticPreUpdateNode {
|
class SyntheticPreUpdateNode extends Node, TSyntheticPreUpdateNode {
|
||||||
CallNode node;
|
Cfg::CallNode node;
|
||||||
|
|
||||||
SyntheticPreUpdateNode() { this = TSyntheticPreUpdateNode(node) }
|
SyntheticPreUpdateNode() { this = TSyntheticPreUpdateNode(node) }
|
||||||
|
|
||||||
@@ -151,7 +167,7 @@ predicate synthStarArgsElementParameterNodeStoreStep(
|
|||||||
* been passed in a `**kwargs` argument.
|
* been passed in a `**kwargs` argument.
|
||||||
*/
|
*/
|
||||||
class SynthDictSplatArgumentNode extends Node, TSynthDictSplatArgumentNode {
|
class SynthDictSplatArgumentNode extends Node, TSynthDictSplatArgumentNode {
|
||||||
CallNode node;
|
Cfg::CallNode node;
|
||||||
|
|
||||||
SynthDictSplatArgumentNode() { this = TSynthDictSplatArgumentNode(node) }
|
SynthDictSplatArgumentNode() { this = TSynthDictSplatArgumentNode(node) }
|
||||||
|
|
||||||
@@ -165,7 +181,7 @@ class SynthDictSplatArgumentNode extends Node, TSynthDictSplatArgumentNode {
|
|||||||
private predicate synthDictSplatArgumentNodeStoreStep(
|
private predicate synthDictSplatArgumentNodeStoreStep(
|
||||||
ArgumentNode nodeFrom, DictionaryElementContent c, SynthDictSplatArgumentNode nodeTo
|
ArgumentNode nodeFrom, DictionaryElementContent c, SynthDictSplatArgumentNode nodeTo
|
||||||
) {
|
) {
|
||||||
exists(string name, CallNode call, ArgumentPosition keywordPos |
|
exists(string name, Cfg::CallNode call, ArgumentPosition keywordPos |
|
||||||
nodeTo = TSynthDictSplatArgumentNode(call) and
|
nodeTo = TSynthDictSplatArgumentNode(call) and
|
||||||
getCallArg(call, _, _, nodeFrom, keywordPos) and
|
getCallArg(call, _, _, nodeFrom, keywordPos) and
|
||||||
keywordPos.isKeyword(name) and
|
keywordPos.isKeyword(name) and
|
||||||
@@ -289,7 +305,7 @@ abstract class PostUpdateNodeImpl extends Node {
|
|||||||
* Synthetic post-update nodes for synthetic nodes need to be listed one by one.
|
* Synthetic post-update nodes for synthetic nodes need to be listed one by one.
|
||||||
*/
|
*/
|
||||||
class SyntheticPostUpdateNode extends PostUpdateNodeImpl, TSyntheticPostUpdateNode {
|
class SyntheticPostUpdateNode extends PostUpdateNodeImpl, TSyntheticPostUpdateNode {
|
||||||
ControlFlowNode node;
|
Cfg::ControlFlowNode node;
|
||||||
|
|
||||||
SyntheticPostUpdateNode() { this = TSyntheticPostUpdateNode(node) }
|
SyntheticPostUpdateNode() { this = TSyntheticPostUpdateNode(node) }
|
||||||
|
|
||||||
@@ -333,16 +349,42 @@ module LocalFlow {
|
|||||||
// `x = f(42)`
|
// `x = f(42)`
|
||||||
// nodeFrom is `f(42)`
|
// nodeFrom is `f(42)`
|
||||||
// nodeTo is `x`
|
// nodeTo is `x`
|
||||||
exists(AssignmentDefinition def |
|
//
|
||||||
|
// We use the CFG-level `DefinitionNode.getValue()` directly rather
|
||||||
|
// than going through SSA, because the new SSA library prunes write
|
||||||
|
// definitions that have no subsequent read in the same scope (e.g.
|
||||||
|
// a module-level `def f():` whose `f` is only read inside other
|
||||||
|
// functions). The CFG-level link is unconditional.
|
||||||
|
//
|
||||||
|
// The Name-target restriction mirrors legacy ESSA's
|
||||||
|
// `SsaDefinitions::assignment_definition`, which required
|
||||||
|
// `defn.(NameNode).defines(v)`. Subscript and attribute writes
|
||||||
|
// (`x[i] = 42`, `obj.attr = 42`) are intentionally excluded — their
|
||||||
|
// value flow is handled by the content-flow / `AttrWrite` machinery,
|
||||||
|
// not by a local-flow step *into* the Subscript/Attribute expression.
|
||||||
|
// Excluding them is essential for keeping augmented-assignment
|
||||||
|
// targets (`x[i] += 42`) classifiable as `LocalSourceNode` on the
|
||||||
|
// read side: the single canonical CFG node is both a load and a
|
||||||
|
// store, and any incoming local-flow step would disqualify it from
|
||||||
|
// being a local source.
|
||||||
|
exists(Cfg::DefinitionNode def |
|
||||||
nodeFrom.(CfgNode).getNode() = def.getValue() and
|
nodeFrom.(CfgNode).getNode() = def.getValue() and
|
||||||
nodeTo.(CfgNode).getNode() = def.getDefiningNode()
|
nodeTo.(CfgNode).getNode() = def and
|
||||||
|
def instanceof Cfg::NameNode and
|
||||||
|
// Parameter defaults are evaluated in the enclosing scope, while the
|
||||||
|
// parameter itself lives in the function's scope. The cross-scope
|
||||||
|
// edge is provided by `runtimeJumpStep` instead.
|
||||||
|
not exists(Py::Parameter param | def.getNode() = param.asName())
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
// With definition
|
// With definition
|
||||||
// `with f(42) as x:`
|
// `with f(42) as x:`
|
||||||
// nodeFrom is `f(42)`
|
// nodeFrom is `f(42)`
|
||||||
// nodeTo is `x`
|
// nodeTo is `x`
|
||||||
exists(With with, ControlFlowNode contextManager, WithDefinition withDef, ControlFlowNode var |
|
exists(
|
||||||
|
With with, Cfg::ControlFlowNode contextManager, SsaImpl::WithDefinition withDef,
|
||||||
|
Cfg::ControlFlowNode var
|
||||||
|
|
|
||||||
var = withDef.getDefiningNode()
|
var = withDef.getDefiningNode()
|
||||||
|
|
|
|
||||||
nodeFrom.(CfgNode).getNode() = contextManager and
|
nodeFrom.(CfgNode).getNode() = contextManager and
|
||||||
@@ -361,13 +403,13 @@ module LocalFlow {
|
|||||||
|
|
||||||
predicate expressionFlowStep(Node nodeFrom, Node nodeTo) {
|
predicate expressionFlowStep(Node nodeFrom, Node nodeTo) {
|
||||||
// If expressions
|
// If expressions
|
||||||
nodeFrom.asCfgNode() = nodeTo.asCfgNode().(IfExprNode).getAnOperand()
|
nodeFrom.asCfgNode() = nodeTo.asCfgNode().(Cfg::IfExprNode).getAnOperand()
|
||||||
or
|
or
|
||||||
// Assignment expressions
|
// Assignment expressions
|
||||||
nodeFrom.asCfgNode() = nodeTo.asCfgNode().(AssignmentExprNode).getValue()
|
nodeFrom.asCfgNode() = nodeTo.asCfgNode().(Cfg::AssignmentExprNode).getValue()
|
||||||
or
|
or
|
||||||
// boolean inline expressions such as `x or y` or `x and y`
|
// boolean inline expressions such as `x or y` or `x and y`
|
||||||
nodeFrom.asCfgNode() = nodeTo.asCfgNode().(BoolExprNode).getAnOperand()
|
nodeFrom.asCfgNode() = nodeTo.asCfgNode().(Cfg::BoolExprNode).getAnOperand()
|
||||||
or
|
or
|
||||||
// Flow inside an unpacking assignment
|
// Flow inside an unpacking assignment
|
||||||
iterableUnpackingFlowStep(nodeFrom, nodeTo)
|
iterableUnpackingFlowStep(nodeFrom, nodeTo)
|
||||||
@@ -376,12 +418,25 @@ module LocalFlow {
|
|||||||
matchFlowStep(nodeFrom, nodeTo)
|
matchFlowStep(nodeFrom, nodeTo)
|
||||||
}
|
}
|
||||||
|
|
||||||
predicate useToNextUse(NameNode nodeFrom, NameNode nodeTo) {
|
predicate useToNextUse(Cfg::NameNode nodeFrom, Cfg::NameNode nodeTo) {
|
||||||
AdjacentUses::adjacentUseUse(nodeFrom, nodeTo)
|
// The SSA-level adjacent-use predicate works on specific CFG variants
|
||||||
|
// (e.g. boolean-outcome `[true]`/`[false]` or emptiness `[empty]`/`[non-empty]`
|
||||||
|
// splits of the same AST node), but dataflow values are insensitive to
|
||||||
|
// those splits — there is at most one `CfgNode` per AST. Project both
|
||||||
|
// ends through `.getNode()` so all variants contribute their use-use
|
||||||
|
// edges to the canonical pair.
|
||||||
|
exists(Cfg::NameNode fromVariant, Cfg::NameNode toVariant |
|
||||||
|
SsaImpl::AdjacentUses::adjacentUseUse(fromVariant, toVariant) and
|
||||||
|
fromVariant.getNode() = nodeFrom.getNode() and
|
||||||
|
toVariant.getNode() = nodeTo.getNode()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
predicate defToFirstUse(EssaVariable var, NameNode nodeTo) {
|
predicate defToFirstUse(SsaImpl::EssaVariable var, Cfg::NameNode nodeTo) {
|
||||||
AdjacentUses::firstUse(var.getDefinition(), nodeTo)
|
exists(Cfg::NameNode toVariant |
|
||||||
|
SsaImpl::AdjacentUses::firstUse(var.getDefinition(), toVariant) and
|
||||||
|
toVariant.getNode() = nodeTo.getNode()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
predicate useUseFlowStep(Node nodeFrom, Node nodeTo) {
|
predicate useUseFlowStep(Node nodeFrom, Node nodeTo) {
|
||||||
@@ -390,12 +445,13 @@ module LocalFlow {
|
|||||||
// `x = f(y)`
|
// `x = f(y)`
|
||||||
// nodeFrom is `y` on first line
|
// nodeFrom is `y` on first line
|
||||||
// nodeTo is `y` on second line
|
// nodeTo is `y` on second line
|
||||||
exists(EssaDefinition def |
|
exists(SsaImpl::EssaDefinition def, Cfg::NameNode toVariant |
|
||||||
nodeFrom.(CfgNode).getNode() = def.(EssaNodeDefinition).getDefiningNode()
|
nodeFrom.(CfgNode).getNode() = def.(SsaImpl::EssaNodeDefinition).getDefiningNode()
|
||||||
or
|
or
|
||||||
nodeFrom.(ScopeEntryDefinitionNode).getDefinition() = def
|
nodeFrom.(ScopeEntryDefinitionNode).getDefinition() = def
|
||||||
|
|
|
|
||||||
AdjacentUses::firstUse(def, nodeTo.(CfgNode).getNode())
|
SsaImpl::AdjacentUses::firstUse(def, toVariant) and
|
||||||
|
toVariant.getNode() = nodeTo.(CfgNode).getNode().getNode()
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
// Next use after use
|
// Next use after use
|
||||||
@@ -557,9 +613,9 @@ predicate runtimeJumpStep(Node nodeFrom, Node nodeTo) {
|
|||||||
// a parameter with a default value, since the parameter will be in the scope of the
|
// a parameter with a default value, since the parameter will be in the scope of the
|
||||||
// function, while the default value itself will be in the scope that _defines_ the
|
// function, while the default value itself will be in the scope that _defines_ the
|
||||||
// function.
|
// function.
|
||||||
exists(ParameterDefinition param |
|
exists(SsaImpl::ParameterDefinition param |
|
||||||
// note: we go to the _control-flow node_ of the parameter, and not the ESSA node of the parameter, since for type-tracking, the ESSA node is not a LocalSourceNode, so we would get in trouble.
|
// note: we go to the _control-flow node_ of the parameter, and not the ESSA node of the parameter, since for type-tracking, the ESSA node is not a LocalSourceNode, so we would get in trouble.
|
||||||
nodeFrom.asCfgNode() = param.getDefault() and
|
nodeFrom.asCfgNode().getNode() = param.getParameter().(Parameter).getDefault() and
|
||||||
nodeTo.asCfgNode() = param.getDefiningNode()
|
nodeTo.asCfgNode() = param.getDefiningNode()
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
@@ -663,7 +719,7 @@ predicate neverSkipInPathGraph(Node n) {
|
|||||||
// ```
|
// ```
|
||||||
// we would end up saying that the path MUST not skip the x in `y = x`, which is just
|
// we would end up saying that the path MUST not skip the x in `y = x`, which is just
|
||||||
// annoying and doesn't help the path explanation become clearer.
|
// annoying and doesn't help the path explanation become clearer.
|
||||||
n.asCfgNode() = any(EssaNodeDefinition def).getDefiningNode()
|
n.asCfgNode() = any(SsaImpl::EssaNodeDefinition def).getDefiningNode()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -874,7 +930,7 @@ predicate listStoreStep(CfgNode nodeFrom, ListElementContent c, CfgNode nodeTo)
|
|||||||
// nodeFrom is `42`, cfg node
|
// nodeFrom is `42`, cfg node
|
||||||
// nodeTo is the list, `[..., 42, ...]`, cfg node
|
// nodeTo is the list, `[..., 42, ...]`, cfg node
|
||||||
// c denotes element of list
|
// c denotes element of list
|
||||||
nodeTo.getNode().(ListNode).getAnElement() = nodeFrom.getNode() and
|
nodeTo.getNode().(Cfg::ListNode).getAnElement() = nodeFrom.getNode() and
|
||||||
not nodeTo.getNode() instanceof UnpackingAssignmentSequenceTarget and
|
not nodeTo.getNode() instanceof UnpackingAssignmentSequenceTarget and
|
||||||
// Suppress unused variable warning
|
// Suppress unused variable warning
|
||||||
c = c
|
c = c
|
||||||
@@ -887,7 +943,7 @@ predicate setStoreStep(CfgNode nodeFrom, SetElementContent c, CfgNode nodeTo) {
|
|||||||
// nodeFrom is `42`, cfg node
|
// nodeFrom is `42`, cfg node
|
||||||
// nodeTo is the set, `{..., 42, ...}`, cfg node
|
// nodeTo is the set, `{..., 42, ...}`, cfg node
|
||||||
// c denotes element of list
|
// c denotes element of list
|
||||||
nodeTo.getNode().(SetNode).getAnElement() = nodeFrom.getNode() and
|
nodeTo.getNode().(Cfg::SetNode).getAnElement() = nodeFrom.getNode() and
|
||||||
// Suppress unused variable warning
|
// Suppress unused variable warning
|
||||||
c = c
|
c = c
|
||||||
}
|
}
|
||||||
@@ -900,7 +956,7 @@ predicate tupleStoreStep(CfgNode nodeFrom, TupleElementContent c, CfgNode nodeTo
|
|||||||
// nodeTo is the tuple, `(..., 42, ...)`, cfg node
|
// nodeTo is the tuple, `(..., 42, ...)`, cfg node
|
||||||
// c denotes element of tuple and index of nodeFrom
|
// c denotes element of tuple and index of nodeFrom
|
||||||
exists(int n |
|
exists(int n |
|
||||||
nodeTo.getNode().(TupleNode).getElement(n) = nodeFrom.getNode() and
|
nodeTo.getNode().(Cfg::TupleNode).getElement(n) = nodeFrom.getNode() and
|
||||||
not nodeTo.getNode() instanceof UnpackingAssignmentSequenceTarget and
|
not nodeTo.getNode() instanceof UnpackingAssignmentSequenceTarget and
|
||||||
c.getIndex() = n
|
c.getIndex() = n
|
||||||
)
|
)
|
||||||
@@ -914,7 +970,7 @@ predicate dictStoreStep(CfgNode nodeFrom, DictionaryElementContent c, Node nodeT
|
|||||||
// nodeTo is the dict, `{..., "key" = 42, ...}`, cfg node
|
// nodeTo is the dict, `{..., "key" = 42, ...}`, cfg node
|
||||||
// c denotes element of dictionary and the key `"key"`
|
// c denotes element of dictionary and the key `"key"`
|
||||||
exists(KeyValuePair item |
|
exists(KeyValuePair item |
|
||||||
item = nodeTo.asCfgNode().(DictNode).getNode().(Dict).getAnItem() and
|
item = nodeTo.asCfgNode().(Cfg::DictNode).getNode().(Dict).getAnItem() and
|
||||||
nodeFrom.getNode().getNode() = item.getValue() and
|
nodeFrom.getNode().getNode() = item.getValue() and
|
||||||
c.getKey() = item.getKey().(StringLiteral).getS()
|
c.getKey() = item.getKey().(StringLiteral).getS()
|
||||||
)
|
)
|
||||||
@@ -929,9 +985,9 @@ predicate dictStoreStep(CfgNode nodeFrom, DictionaryElementContent c, Node nodeT
|
|||||||
private predicate moreDictStoreSteps(CfgNode nodeFrom, DictionaryElementContent c, Node nodeTo) {
|
private predicate moreDictStoreSteps(CfgNode nodeFrom, DictionaryElementContent c, Node nodeTo) {
|
||||||
// NOTE: It's important to add logic to the newtype definition of
|
// NOTE: It's important to add logic to the newtype definition of
|
||||||
// DictionaryElementContent if you add new cases here.
|
// DictionaryElementContent if you add new cases here.
|
||||||
exists(SubscriptNode subscript |
|
exists(Cfg::SubscriptNode subscript |
|
||||||
nodeTo.(PostUpdateNode).getPreUpdateNode().asCfgNode() = subscript.getObject() and
|
nodeTo.(PostUpdateNode).getPreUpdateNode().asCfgNode() = subscript.getObject() and
|
||||||
nodeFrom.asCfgNode() = subscript.(DefinitionNode).getValue() and
|
nodeFrom.asCfgNode() = subscript.(Cfg::DefinitionNode).getValue() and
|
||||||
c.getKey() = subscript.getIndex().getNode().(StringLiteral).getText()
|
c.getKey() = subscript.getIndex().getNode().(StringLiteral).getText()
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
@@ -944,8 +1000,8 @@ private predicate moreDictStoreSteps(CfgNode nodeFrom, DictionaryElementContent
|
|||||||
}
|
}
|
||||||
|
|
||||||
predicate dictClearStep(Node node, DictionaryElementContent c) {
|
predicate dictClearStep(Node node, DictionaryElementContent c) {
|
||||||
exists(SubscriptNode subscript |
|
exists(Cfg::SubscriptNode subscript |
|
||||||
subscript instanceof DefinitionNode and
|
subscript instanceof Cfg::DefinitionNode and
|
||||||
node.asCfgNode() = subscript.getObject() and
|
node.asCfgNode() = subscript.getObject() and
|
||||||
c.getKey() = subscript.getIndex().getNode().(StringLiteral).getText()
|
c.getKey() = subscript.getIndex().getNode().(StringLiteral).getText()
|
||||||
)
|
)
|
||||||
@@ -1024,7 +1080,7 @@ predicate subscriptReadStep(CfgNode nodeFrom, Content c, CfgNode nodeTo) {
|
|||||||
// nodeFrom is `l`, cfg node
|
// nodeFrom is `l`, cfg node
|
||||||
// nodeTo is `l[3]`, cfg node
|
// nodeTo is `l[3]`, cfg node
|
||||||
// c is compatible with 3
|
// c is compatible with 3
|
||||||
nodeFrom.getNode() = nodeTo.getNode().(SubscriptNode).getObject() and
|
nodeFrom.getNode() = nodeTo.getNode().(Cfg::SubscriptNode).getObject() and
|
||||||
(
|
(
|
||||||
c instanceof ListElementContent
|
c instanceof ListElementContent
|
||||||
or
|
or
|
||||||
@@ -1033,10 +1089,10 @@ predicate subscriptReadStep(CfgNode nodeFrom, Content c, CfgNode nodeTo) {
|
|||||||
c instanceof DictionaryElementAnyContent
|
c instanceof DictionaryElementAnyContent
|
||||||
or
|
or
|
||||||
c.(TupleElementContent).getIndex() =
|
c.(TupleElementContent).getIndex() =
|
||||||
nodeTo.getNode().(SubscriptNode).getIndex().getNode().(IntegerLiteral).getValue()
|
nodeTo.getNode().(Cfg::SubscriptNode).getIndex().getNode().(IntegerLiteral).getValue()
|
||||||
or
|
or
|
||||||
c.(DictionaryElementContent).getKey() =
|
c.(DictionaryElementContent).getKey() =
|
||||||
nodeTo.getNode().(SubscriptNode).getIndex().getNode().(StringLiteral).getS()
|
nodeTo.getNode().(Cfg::SubscriptNode).getIndex().getNode().(StringLiteral).getS()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1091,7 +1147,7 @@ module Conversions {
|
|||||||
|
|
||||||
predicate formatReadStep(Node nodeFrom, ContentSet c, Node nodeTo) {
|
predicate formatReadStep(Node nodeFrom, ContentSet c, Node nodeTo) {
|
||||||
// % formatting
|
// % formatting
|
||||||
exists(BinaryExprNode fmt | fmt = nodeTo.asCfgNode() |
|
exists(Cfg::BinaryExprNode fmt | fmt = nodeTo.asCfgNode() |
|
||||||
fmt.getOp() instanceof Mod and
|
fmt.getOp() instanceof Mod and
|
||||||
fmt.getRight() = nodeFrom.asCfgNode()
|
fmt.getRight() = nodeFrom.asCfgNode()
|
||||||
) and
|
) and
|
||||||
|
|||||||
@@ -5,11 +5,14 @@ overlay[local]
|
|||||||
module;
|
module;
|
||||||
|
|
||||||
private import python
|
private import python
|
||||||
|
private import semmle.python.controlflow.internal.Cfg as Cfg
|
||||||
|
private import semmle.python.controlflow.internal.AstNodeImpl as CfgImpl
|
||||||
|
private import codeql.controlflow.SuccessorType
|
||||||
private import DataFlowPrivate
|
private import DataFlowPrivate
|
||||||
import semmle.python.dataflow.new.TypeTracking
|
import semmle.python.dataflow.new.TypeTracking
|
||||||
import Attributes
|
import Attributes
|
||||||
import LocalSources
|
import LocalSources
|
||||||
private import semmle.python.essa.SsaCompute
|
private import semmle.python.dataflow.new.internal.SsaImpl as SsaImpl
|
||||||
private import semmle.python.dataflow.new.internal.ImportStar
|
private import semmle.python.dataflow.new.internal.ImportStar
|
||||||
private import semmle.python.frameworks.data.ModelsAsData
|
private import semmle.python.frameworks.data.ModelsAsData
|
||||||
private import FlowSummaryImpl as FlowSummaryImpl
|
private import FlowSummaryImpl as FlowSummaryImpl
|
||||||
@@ -27,16 +30,18 @@ private import semmle.python.frameworks.data.ModelsAsData
|
|||||||
overlay[local]
|
overlay[local]
|
||||||
newtype TNode =
|
newtype TNode =
|
||||||
/** A node corresponding to a control flow node. */
|
/** A node corresponding to a control flow node. */
|
||||||
TCfgNode(ControlFlowNode node) {
|
TCfgNode(Cfg::ControlFlowNode node) {
|
||||||
isExpressionNode(node)
|
isExpressionNode(node)
|
||||||
or
|
or
|
||||||
node.getNode() instanceof Pattern
|
node.injects(_) and node.getNode() instanceof Pattern
|
||||||
} or
|
} or
|
||||||
/**
|
/**
|
||||||
* A node corresponding to a scope entry definition. That is, the value of a variable
|
* A node corresponding to a scope entry definition. That is, the value of a variable
|
||||||
* as it enters a scope.
|
* as it enters a scope.
|
||||||
*/
|
*/
|
||||||
TScopeEntryDefinitionNode(ScopeEntryDefinition def) { not def.getScope() instanceof Module } or
|
TScopeEntryDefinitionNode(SsaImpl::ScopeEntryDefinition def) {
|
||||||
|
not def.getScope() instanceof Module
|
||||||
|
} or
|
||||||
/**
|
/**
|
||||||
* A synthetic node representing the value of an object before a state change.
|
* A synthetic node representing the value of an object before a state change.
|
||||||
*
|
*
|
||||||
@@ -47,13 +52,15 @@ newtype TNode =
|
|||||||
// NOTE: since we can't rely on the call graph, but we want to have synthetic
|
// NOTE: since we can't rely on the call graph, but we want to have synthetic
|
||||||
// pre-update nodes for class calls, we end up getting synthetic pre-update nodes for
|
// pre-update nodes for class calls, we end up getting synthetic pre-update nodes for
|
||||||
// ALL calls :|
|
// ALL calls :|
|
||||||
TSyntheticPreUpdateNode(CallNode call) or
|
TSyntheticPreUpdateNode(Cfg::CallNode call) { call.injects(_) } or
|
||||||
/**
|
/**
|
||||||
* A synthetic node representing the value of an object after a state change.
|
* A synthetic node representing the value of an object after a state change.
|
||||||
* See QLDoc for `PostUpdateNode`.
|
* See QLDoc for `PostUpdateNode`.
|
||||||
*/
|
*/
|
||||||
TSyntheticPostUpdateNode(ControlFlowNode node) {
|
TSyntheticPostUpdateNode(Cfg::ControlFlowNode node) {
|
||||||
exists(CallNode call |
|
node.injects(_) and
|
||||||
|
(
|
||||||
|
exists(Cfg::CallNode call |
|
||||||
node = call.getArg(_)
|
node = call.getArg(_)
|
||||||
or
|
or
|
||||||
node = call.getArgByName(_)
|
node = call.getArgByName(_)
|
||||||
@@ -62,12 +69,12 @@ newtype TNode =
|
|||||||
node = call.getFunction()
|
node = call.getFunction()
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
node = any(AttrNode a).getObject()
|
node = any(Cfg::AttrNode a).getObject()
|
||||||
or
|
or
|
||||||
node = any(SubscriptNode s).getObject()
|
node = any(Cfg::SubscriptNode s).getObject()
|
||||||
or
|
or
|
||||||
// self parameter when used implicitly in `super()`
|
// self parameter when used implicitly in `super()`
|
||||||
exists(Class cls, Function func, ParameterDefinition def |
|
exists(Class cls, Function func, SsaImpl::ParameterDefinition def |
|
||||||
func = cls.getAMethod() and
|
func = cls.getAMethod() and
|
||||||
not isStaticmethod(func) and
|
not isStaticmethod(func) and
|
||||||
// this matches what we do in ExtractedParameterNode
|
// this matches what we do in ExtractedParameterNode
|
||||||
@@ -77,6 +84,7 @@ newtype TNode =
|
|||||||
or
|
or
|
||||||
// the iterable argument to the implicit comprehension function
|
// the iterable argument to the implicit comprehension function
|
||||||
node.getNode() = any(Comp c).getIterable()
|
node.getNode() = any(Comp c).getIterable()
|
||||||
|
)
|
||||||
} or
|
} or
|
||||||
/** A node representing a global (module-level) variable in a specific module. */
|
/** A node representing a global (module-level) variable in a specific module. */
|
||||||
TModuleVariableNode(Module m, GlobalVariable v) { v.getScope() = m } or
|
TModuleVariableNode(Module m, GlobalVariable v) { v.getScope() = m } or
|
||||||
@@ -112,7 +120,9 @@ newtype TNode =
|
|||||||
exists(ParameterPosition ppos | ppos.isStarArgs(_) | exists(callable.getParameter(ppos)))
|
exists(ParameterPosition ppos | ppos.isStarArgs(_) | exists(callable.getParameter(ppos)))
|
||||||
} or
|
} or
|
||||||
/** A synthetic node to capture keyword arguments that are passed to a `**kwargs` parameter. */
|
/** A synthetic node to capture keyword arguments that are passed to a `**kwargs` parameter. */
|
||||||
TSynthDictSplatArgumentNode(CallNode call) { exists(call.getArgByName(_)) } or
|
TSynthDictSplatArgumentNode(Cfg::CallNode call) {
|
||||||
|
call.injects(_) and exists(call.getArgByName(_))
|
||||||
|
} or
|
||||||
/** A synthetic node to allow flow to keyword parameters from a `**kwargs` argument. */
|
/** A synthetic node to allow flow to keyword parameters from a `**kwargs` argument. */
|
||||||
TSynthDictSplatParameterNode(DataFlowCallable callable) {
|
TSynthDictSplatParameterNode(DataFlowCallable callable) {
|
||||||
exists(ParameterPosition ppos | ppos.isKeyword(_) | exists(callable.getParameter(ppos)))
|
exists(ParameterPosition ppos | ppos.isKeyword(_) | exists(callable.getParameter(ppos)))
|
||||||
@@ -128,15 +138,15 @@ newtype TNode =
|
|||||||
* A synthetic node representing the values of the variables captured
|
* A synthetic node representing the values of the variables captured
|
||||||
* by the callable being called.
|
* by the callable being called.
|
||||||
*/
|
*/
|
||||||
TSynthCapturedVariablesArgumentNode(ControlFlowNode callable) {
|
TSynthCapturedVariablesArgumentNode(Cfg::ControlFlowNode callable) {
|
||||||
callable = any(CallNode c).getFunction()
|
callable.injects(_) and callable = any(Cfg::CallNode c).getFunction()
|
||||||
} or
|
} or
|
||||||
/**
|
/**
|
||||||
* A synthetic node representing the values of the variables captured
|
* A synthetic node representing the values of the variables captured
|
||||||
* by the callable being called, after the output has been computed.
|
* by the callable being called, after the output has been computed.
|
||||||
*/
|
*/
|
||||||
TSynthCapturedVariablesArgumentPostUpdateNode(ControlFlowNode callable) {
|
TSynthCapturedVariablesArgumentPostUpdateNode(Cfg::ControlFlowNode callable) {
|
||||||
callable = any(CallNode c).getFunction()
|
callable.injects(_) and callable = any(Cfg::CallNode c).getFunction()
|
||||||
} or
|
} or
|
||||||
/** A synthetic node representing the values of variables captured by a comprehension. */
|
/** A synthetic node representing the values of variables captured by a comprehension. */
|
||||||
TSynthCompCapturedVariablesArgumentNode(Comp comp) {
|
TSynthCompCapturedVariablesArgumentNode(Comp comp) {
|
||||||
@@ -194,7 +204,7 @@ class Node extends TNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Gets the control-flow node corresponding to this node, if any. */
|
/** Gets the control-flow node corresponding to this node, if any. */
|
||||||
ControlFlowNode asCfgNode() { none() }
|
Cfg::ControlFlowNode asCfgNode() { none() }
|
||||||
|
|
||||||
/** Gets the expression corresponding to this node, if any. */
|
/** Gets the expression corresponding to this node, if any. */
|
||||||
Expr asExpr() { none() }
|
Expr asExpr() { none() }
|
||||||
@@ -207,14 +217,14 @@ class Node extends TNode {
|
|||||||
|
|
||||||
/** A data-flow node corresponding to a control-flow node. */
|
/** A data-flow node corresponding to a control-flow node. */
|
||||||
class CfgNode extends Node, TCfgNode {
|
class CfgNode extends Node, TCfgNode {
|
||||||
ControlFlowNode node;
|
Cfg::ControlFlowNode node;
|
||||||
|
|
||||||
CfgNode() { this = TCfgNode(node) }
|
CfgNode() { this = TCfgNode(node) }
|
||||||
|
|
||||||
/** Gets the `ControlFlowNode` represented by this data-flow node. */
|
/** Gets the `Cfg::ControlFlowNode` represented by this data-flow node. */
|
||||||
ControlFlowNode getNode() { result = node }
|
Cfg::ControlFlowNode getNode() { result = node }
|
||||||
|
|
||||||
override ControlFlowNode asCfgNode() { result = node }
|
override Cfg::ControlFlowNode asCfgNode() { result = node }
|
||||||
|
|
||||||
/** Gets a textual representation of this element. */
|
/** Gets a textual representation of this element. */
|
||||||
override string toString() { result = node.toString() }
|
override string toString() { result = node.toString() }
|
||||||
@@ -224,9 +234,9 @@ class CfgNode extends Node, TCfgNode {
|
|||||||
override Location getLocation() { result = node.getLocation() }
|
override Location getLocation() { result = node.getLocation() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/** A data-flow node corresponding to a `CallNode` in the control-flow graph. */
|
/** A data-flow node corresponding to a `Cfg::CallNode` in the control-flow graph. */
|
||||||
class CallCfgNode extends CfgNode, LocalSourceNode {
|
class CallCfgNode extends CfgNode, LocalSourceNode {
|
||||||
override CallNode node;
|
override Cfg::CallNode node;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the data-flow node for the function component of the call corresponding to this data-flow
|
* Gets the data-flow node for the function component of the call corresponding to this data-flow
|
||||||
@@ -307,15 +317,15 @@ ExprNode exprNode(DataFlowExpr e) { result.getNode().getNode() = e }
|
|||||||
* as it enters a scope.
|
* as it enters a scope.
|
||||||
*/
|
*/
|
||||||
class ScopeEntryDefinitionNode extends Node, TScopeEntryDefinitionNode {
|
class ScopeEntryDefinitionNode extends Node, TScopeEntryDefinitionNode {
|
||||||
ScopeEntryDefinition def;
|
SsaImpl::ScopeEntryDefinition def;
|
||||||
|
|
||||||
ScopeEntryDefinitionNode() { this = TScopeEntryDefinitionNode(def) }
|
ScopeEntryDefinitionNode() { this = TScopeEntryDefinitionNode(def) }
|
||||||
|
|
||||||
/** Gets the `ScopeEntryDefinition` associated with this node. */
|
/** Gets the `SsaImpl::ScopeEntryDefinition` associated with this node. */
|
||||||
ScopeEntryDefinition getDefinition() { result = def }
|
SsaImpl::ScopeEntryDefinition getDefinition() { result = def }
|
||||||
|
|
||||||
/** Gets the source variable represented by this node. */
|
/** Gets the source variable represented by this node. */
|
||||||
SsaSourceVariable getVariable() { result = def.getSourceVariable() }
|
SsaImpl::SsaSourceVariable getVariable() { result = def.getSourceVariable() }
|
||||||
|
|
||||||
override Location getLocation() { result = def.getLocation() }
|
override Location getLocation() { result = def.getLocation() }
|
||||||
|
|
||||||
@@ -337,7 +347,7 @@ class ParameterNode extends Node instanceof ParameterNodeImpl {
|
|||||||
/** A parameter node found in the source code (not in a summary). */
|
/** A parameter node found in the source code (not in a summary). */
|
||||||
class ExtractedParameterNode extends ParameterNodeImpl, CfgNode {
|
class ExtractedParameterNode extends ParameterNodeImpl, CfgNode {
|
||||||
//, LocalSourceNode {
|
//, LocalSourceNode {
|
||||||
ParameterDefinition def;
|
SsaImpl::ParameterDefinition def;
|
||||||
|
|
||||||
ExtractedParameterNode() { node = def.getDefiningNode() }
|
ExtractedParameterNode() { node = def.getDefiningNode() }
|
||||||
|
|
||||||
@@ -368,10 +378,10 @@ Node getCallArgApproximation() {
|
|||||||
exists(Class c | result.asExpr() = c.getAMethod().getArg(0))
|
exists(Class c | result.asExpr() = c.getAMethod().getArg(0))
|
||||||
or
|
or
|
||||||
// the object part of an attribute expression (which might be a bound method)
|
// the object part of an attribute expression (which might be a bound method)
|
||||||
result.asCfgNode() = any(AttrNode a).getObject()
|
result.asCfgNode() = any(Cfg::AttrNode a).getObject()
|
||||||
or
|
or
|
||||||
// the function part of any call
|
// the function part of any call
|
||||||
result.asCfgNode() = any(CallNode c).getFunction()
|
result.asCfgNode() = any(Cfg::CallNode c).getFunction()
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Gets the extracted argument nodes that do not rely on `getCallArg`. */
|
/** Gets the extracted argument nodes that do not rely on `getCallArg`. */
|
||||||
@@ -380,7 +390,7 @@ private Node implicitArgumentNode() {
|
|||||||
normalCallArg(_, result, _)
|
normalCallArg(_, result, _)
|
||||||
or
|
or
|
||||||
// and self arguments
|
// and self arguments
|
||||||
result.asCfgNode() = any(CallNode c).getFunction().(AttrNode).getObject()
|
result.asCfgNode() = any(Cfg::CallNode c).getFunction().(Cfg::AttrNode).getObject()
|
||||||
or
|
or
|
||||||
// for comprehensions, we allow the synthetic `iterable` argument
|
// for comprehensions, we allow the synthetic `iterable` argument
|
||||||
result.asExpr() = any(Comp c).getIterable()
|
result.asExpr() = any(Comp c).getIterable()
|
||||||
@@ -489,17 +499,20 @@ class ModuleVariableNode extends Node, TModuleVariableNode {
|
|||||||
not result.getScope() = mod
|
not result.getScope() = mod
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Gets an `EssaNode` that corresponds to an assignment of this global variable. */
|
/** Gets a CFG node that corresponds to an assignment of this global variable. */
|
||||||
Node getAWrite() {
|
Node getAWrite() {
|
||||||
any(EssaNodeDefinition def).definedBy(var, result.asCfgNode().(DefinitionNode))
|
exists(Cfg::NameNode n |
|
||||||
|
n.defines(var) and
|
||||||
|
result.asCfgNode() = n
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Gets the possible values of the variable at the end of import time */
|
/** Gets the possible values of the variable at the end of import time */
|
||||||
CfgNode getADefiningWrite() {
|
CfgNode getADefiningWrite() {
|
||||||
exists(SsaVariable def |
|
exists(SsaImpl::EssaVariable def |
|
||||||
def = any(SsaVariable ssa_var).getAnUltimateDefinition() and
|
def = any(SsaImpl::EssaVariable ssa_var).getAnUltimateDefinition() and
|
||||||
def.getDefinition() = result.asCfgNode() and
|
def.getDefinition().(SsaImpl::EssaNodeDefinition).getDefiningNode() = result.asCfgNode() and
|
||||||
def.getVariable() = var
|
def.getSourceVariable().getVariable() = var
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -516,7 +529,7 @@ private ModuleVariableNode import_star_read(Node n) {
|
|||||||
overlay[global]
|
overlay[global]
|
||||||
pragma[nomagic]
|
pragma[nomagic]
|
||||||
private predicate resolved_import_star_module(Module m, string name, Node n) {
|
private predicate resolved_import_star_module(Module m, string name, Node n) {
|
||||||
exists(NameNode nn | nn = n.asCfgNode() |
|
exists(Cfg::NameNode nn | nn = n.asCfgNode() |
|
||||||
ImportStar::importStarResolvesTo(pragma[only_bind_into](nn), m) and
|
ImportStar::importStarResolvesTo(pragma[only_bind_into](nn), m) and
|
||||||
nn.getId() = name
|
nn.getId() = name
|
||||||
)
|
)
|
||||||
@@ -574,88 +587,88 @@ class StarPatternElementNode extends Node, TStarPatternElementNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a node that controls whether other nodes are evaluated.
|
* A node that participates in a conditional split: a CFG node whose
|
||||||
|
* evaluation outcome (true/false) is used to choose between two
|
||||||
|
* successor basic blocks. In the shared CFG, branching is detected
|
||||||
|
* via typed successor edges (boolean successor types) on the unique
|
||||||
|
* `injects` node for each AST expression.
|
||||||
*
|
*
|
||||||
* In the base case, this is the last node of `conditionBlock`, and `flipped` is `false`.
|
* Users typically obtain a `GuardNode` by casting from a more specific
|
||||||
* This definition accounts for (short circuting) `and`- and `or`-expressions, as the structure
|
* Cfg type: `g.(Cfg::CallNode)` for a call-based check, etc.
|
||||||
* of basic blocks will reflect their semantics.
|
|
||||||
*
|
|
||||||
* However, in the program
|
|
||||||
* ```python
|
|
||||||
* if not is_safe(path):
|
|
||||||
* return
|
|
||||||
* ```
|
|
||||||
* the last node in the `ConditionBlock` is `not is_safe(path)`.
|
|
||||||
*
|
|
||||||
* We would like to consider also `is_safe(path)` a guard node, albeit with `flipped` being `true`.
|
|
||||||
* Thus we recurse through `not`-expressions.
|
|
||||||
*/
|
*/
|
||||||
ControlFlowNode guardNode(ConditionBlock conditionBlock, boolean flipped) {
|
class GuardNode extends Cfg::ControlFlowNode {
|
||||||
// Base case: the last node truly does determine which successor is chosen
|
GuardNode() {
|
||||||
result = conditionBlock.getLastNode() and
|
// This node has boolean successor edges (directly or via wrapping).
|
||||||
flipped = false
|
outcomeOfGuard(this, _, _)
|
||||||
or
|
}
|
||||||
// Recursive cases:
|
|
||||||
// if a guard node is a `not`-expression,
|
/** Holds if this guard controls block `b` upon evaluating to `branch`. */
|
||||||
// the operand is also a guard node, but with inverted polarity.
|
predicate controlsBlock(Cfg::BasicBlock b, boolean branch) {
|
||||||
exists(UnaryExprNode notNode |
|
exists(CfgImpl::BasicBlock outcomeBB |
|
||||||
result = notNode.getOperand() and
|
outcomeOfGuard(this, outcomeBB, branch) and
|
||||||
notNode.getNode().getOp() instanceof Not
|
outcomeBB.dominates(b)
|
||||||
|
|
|
||||||
notNode = guardNode(conditionBlock, flipped.booleanNot())
|
|
||||||
)
|
|
||||||
or
|
|
||||||
// if a guard node is compared to a boolean literal,
|
|
||||||
// the other operand is also a guard node,
|
|
||||||
// but with polarity depending on the literal (and on the comparison).
|
|
||||||
exists(CompareNode cmpNode, Cmpop op, ControlFlowNode b, boolean should_flip |
|
|
||||||
(
|
|
||||||
cmpNode.operands(result, op, b) or
|
|
||||||
cmpNode.operands(b, op, result)
|
|
||||||
) and
|
|
||||||
not result.getNode() instanceof BooleanLiteral and
|
|
||||||
(
|
|
||||||
// comparing to the boolean
|
|
||||||
(op instanceof Eq or op instanceof Is) and
|
|
||||||
// we should flip if the value compared against, here the value of `b`, is false
|
|
||||||
should_flip = b.getNode().(BooleanLiteral).booleanValue().booleanNot()
|
|
||||||
or
|
|
||||||
// comparing to the negation of the boolean
|
|
||||||
(op instanceof NotEq or op instanceof IsNot) and
|
|
||||||
// again, we should flip if the value compared against, here the value of `not b`, is false.
|
|
||||||
// That is, if the value of `b` is true.
|
|
||||||
should_flip = b.getNode().(BooleanLiteral).booleanValue()
|
|
||||||
)
|
)
|
||||||
|
|
}
|
||||||
// we flip `flipped` according to `should_flip` via the formula `flipped xor should_flip`.
|
|
||||||
flipped in [true, false] and
|
|
||||||
cmpNode = guardNode(conditionBlock, flipped.booleanXor(should_flip))
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A node that controls whether other nodes are evaluated.
|
* Holds if `outcomeBB` is the basic block entered when `guard` evaluates
|
||||||
|
* to `branch`.
|
||||||
*
|
*
|
||||||
* The field `flipped` allows us to match `GuardNode`s underneath
|
* For a direct guard `if g:`, the outcome BB starts at the after-value
|
||||||
* `not`-expressions and still choose the appropriate branch.
|
* node for the matching branch. For wrapped guards like `not g` or
|
||||||
|
* `g == True`, we follow those wrappers up the AST to find the
|
||||||
|
* outermost expression that actually branches, with an appropriate
|
||||||
|
* polarity transform.
|
||||||
*/
|
*/
|
||||||
class GuardNode extends ControlFlowNode {
|
private predicate outcomeOfGuard(
|
||||||
ConditionBlock conditionBlock;
|
Cfg::ControlFlowNode guard, CfgImpl::BasicBlock outcomeBB, boolean branch
|
||||||
boolean flipped;
|
) {
|
||||||
|
// Base case: the guard has boolean successor edges.
|
||||||
GuardNode() { this = guardNode(conditionBlock, flipped) }
|
// Only the canonical representative (injects) can act as a guard base.
|
||||||
|
guard.injects(_) and
|
||||||
/** Holds if this guard controls block `b` upon evaluating to `branch`. */
|
exists(BooleanSuccessor t |
|
||||||
predicate controlsBlock(BasicBlock b, boolean branch) {
|
t.getValue() = branch and
|
||||||
branch in [true, false] and
|
outcomeBB = guard.(CfgImpl::ControlFlowNode).getASuccessor(t).getBasicBlock()
|
||||||
conditionBlock.controls(b, branch.booleanXor(flipped))
|
)
|
||||||
}
|
or
|
||||||
|
// Recursive: `not guard` — same outcome split as `guard`, flipped.
|
||||||
|
exists(Cfg::UnaryExprNode notNode, boolean notBranch |
|
||||||
|
notNode.injects(_) and
|
||||||
|
notNode.getOperand().getNode() = guard.getNode() and
|
||||||
|
notNode.getNode().getOp() instanceof Not and
|
||||||
|
outcomeOfGuard(notNode, outcomeBB, notBranch) and
|
||||||
|
branch = notBranch.booleanNot()
|
||||||
|
)
|
||||||
|
or
|
||||||
|
// Recursive: comparisons against a boolean literal.
|
||||||
|
exists(
|
||||||
|
Cfg::CompareNode cmpNode, Cmpop op, Cfg::ControlFlowNode otherOperand,
|
||||||
|
Cfg::ControlFlowNode guardOperand, boolean polarity, boolean cmpBranch
|
||||||
|
|
|
||||||
|
cmpNode.injects(_) and
|
||||||
|
guardOperand.getNode() = guard.getNode() and
|
||||||
|
(
|
||||||
|
cmpNode.operands(guardOperand, op, otherOperand) or
|
||||||
|
cmpNode.operands(otherOperand, op, guardOperand)
|
||||||
|
) and
|
||||||
|
not guard.getNode() instanceof BooleanLiteral and
|
||||||
|
(
|
||||||
|
(op instanceof Eq or op instanceof Is) and
|
||||||
|
polarity = otherOperand.getNode().(BooleanLiteral).booleanValue()
|
||||||
|
or
|
||||||
|
(op instanceof NotEq or op instanceof IsNot) and
|
||||||
|
polarity = otherOperand.getNode().(BooleanLiteral).booleanValue().booleanNot()
|
||||||
|
) and
|
||||||
|
outcomeOfGuard(cmpNode, outcomeBB, cmpBranch) and
|
||||||
|
branch = cmpBranch.booleanXor(polarity.booleanNot())
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds if the guard `g` validates `node` upon evaluating to `branch`.
|
* Holds if the guard `g` validates `node` upon evaluating to `branch`.
|
||||||
*/
|
*/
|
||||||
signature predicate guardChecksSig(GuardNode g, ControlFlowNode node, boolean branch);
|
signature predicate guardChecksSig(GuardNode g, Cfg::ControlFlowNode node, boolean branch);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides a set of barrier nodes for a guard that validates a node.
|
* Provides a set of barrier nodes for a guard that validates a node.
|
||||||
@@ -670,7 +683,9 @@ module BarrierGuard<guardChecksSig/3 guardChecks> {
|
|||||||
result = ParameterizedBarrierGuard<Unit, extendedGuardChecks/4>::getABarrierNode(_)
|
result = ParameterizedBarrierGuard<Unit, extendedGuardChecks/4>::getABarrierNode(_)
|
||||||
}
|
}
|
||||||
|
|
||||||
private predicate extendedGuardChecks(GuardNode g, ControlFlowNode node, boolean branch, Unit u) {
|
private predicate extendedGuardChecks(
|
||||||
|
GuardNode g, Cfg::ControlFlowNode node, boolean branch, Unit u
|
||||||
|
) {
|
||||||
guardChecks(g, node, branch) and
|
guardChecks(g, node, branch) and
|
||||||
u = u
|
u = u
|
||||||
}
|
}
|
||||||
@@ -680,7 +695,7 @@ bindingset[this]
|
|||||||
private signature class ParamSig;
|
private signature class ParamSig;
|
||||||
|
|
||||||
private module WithParam<ParamSig P> {
|
private module WithParam<ParamSig P> {
|
||||||
signature predicate guardChecksSig(GuardNode g, ControlFlowNode node, boolean branch, P param);
|
signature predicate guardChecksSig(GuardNode g, Cfg::ControlFlowNode node, boolean branch, P param);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -693,10 +708,16 @@ module ParameterizedBarrierGuard<ParamSig P, WithParam<P>::guardChecksSig/4 guar
|
|||||||
/** Gets a node that is safely guarded by the given guard check with parameter `param`. */
|
/** Gets a node that is safely guarded by the given guard check with parameter `param`. */
|
||||||
overlay[global]
|
overlay[global]
|
||||||
ExprNode getABarrierNode(P param) {
|
ExprNode getABarrierNode(P param) {
|
||||||
exists(GuardNode g, EssaDefinition def, ControlFlowNode node, boolean branch |
|
exists(GuardNode g, SsaImpl::EssaDefinition def, Cfg::ControlFlowNode node, boolean branch |
|
||||||
AdjacentUses::useOfDef(def, node) and
|
SsaImpl::AdjacentUses::useOfDef(def, node) and
|
||||||
guardChecks(g, node, branch, param) and
|
guardChecks(g, node, branch, param) and
|
||||||
AdjacentUses::useOfDef(def, result.asCfgNode()) and
|
SsaImpl::AdjacentUses::useOfDef(def, result.asCfgNode()) and
|
||||||
|
// The protected use must be a different SSA position than the test
|
||||||
|
// position itself: `controlsBlock` is reflexive on dominance, and
|
||||||
|
// the test expression is an SSA-use position on the def-use chain.
|
||||||
|
// Without this guard, the test position would be returned as a
|
||||||
|
// barrier and block flow before it can reach genuine branch uses.
|
||||||
|
node != result.asCfgNode() and
|
||||||
g.controlsBlock(result.asCfgNode().getBasicBlock(), branch)
|
g.controlsBlock(result.asCfgNode().getBasicBlock(), branch)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -712,7 +733,7 @@ module ExternalBarrierGuard {
|
|||||||
private import semmle.python.ApiGraphs
|
private import semmle.python.ApiGraphs
|
||||||
|
|
||||||
overlay[global]
|
overlay[global]
|
||||||
private predicate guardCheck(GuardNode g, ControlFlowNode node, boolean branch, string kind) {
|
private predicate guardCheck(GuardNode g, Cfg::ControlFlowNode node, boolean branch, string kind) {
|
||||||
exists(API::CallNode call, API::Node parameter |
|
exists(API::CallNode call, API::Node parameter |
|
||||||
parameter = call.getAParameter() and
|
parameter = call.getAParameter() and
|
||||||
parameter = ModelOutput::getABarrierGuardNode(kind, branch)
|
parameter = ModelOutput::getABarrierGuardNode(kind, branch)
|
||||||
@@ -748,10 +769,10 @@ newtype TContent =
|
|||||||
TSetElementContent() or
|
TSetElementContent() or
|
||||||
/** An element of a tuple at a specific index. */
|
/** An element of a tuple at a specific index. */
|
||||||
TTupleElementContent(int index) {
|
TTupleElementContent(int index) {
|
||||||
exists(any(TupleNode tn).getElement(index))
|
exists(any(Cfg::TupleNode tn).getElement(index))
|
||||||
or
|
or
|
||||||
// Arguments can overflow and end up in the starred parameter tuple.
|
// Arguments can overflow and end up in the starred parameter tuple.
|
||||||
exists(any(CallNode cn).getArg(index))
|
exists(any(Cfg::CallNode cn).getArg(index))
|
||||||
or
|
or
|
||||||
// since flow summaries might use tuples, we ensure that we at least have valid
|
// since flow summaries might use tuples, we ensure that we at least have valid
|
||||||
// TTupleElementContent for the 0..7 (7 was picked to match `small_tuple` in
|
// TTupleElementContent for the 0..7 (7 was picked to match `small_tuple` in
|
||||||
@@ -768,10 +789,14 @@ newtype TContent =
|
|||||||
or
|
or
|
||||||
// d["key"] = ...
|
// d["key"] = ...
|
||||||
key =
|
key =
|
||||||
any(SubscriptNode sub | sub.isStore() | sub.getIndex().getNode().(StringLiteral).getText())
|
any(Cfg::SubscriptNode sub |
|
||||||
|
sub.isStore()
|
||||||
|
|
|
||||||
|
sub.getIndex().getNode().(StringLiteral).getText()
|
||||||
|
)
|
||||||
or
|
or
|
||||||
// d.setdefault("key", ...)
|
// d.setdefault("key", ...)
|
||||||
exists(CallNode call | call.getFunction().(AttrNode).getName() = "setdefault" |
|
exists(Cfg::CallNode call | call.getFunction().(Cfg::AttrNode).getName() = "setdefault" |
|
||||||
key = call.getArg(0).getNode().(StringLiteral).getText()
|
key = call.getArg(0).getNode().(StringLiteral).getText()
|
||||||
)
|
)
|
||||||
} or
|
} or
|
||||||
|
|||||||
@@ -5,17 +5,18 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
private import python
|
private import python
|
||||||
|
private import semmle.python.controlflow.internal.Cfg as Cfg
|
||||||
|
private import semmle.python.dataflow.new.internal.SsaImpl as SsaImpl
|
||||||
private import semmle.python.dataflow.new.DataFlow
|
private import semmle.python.dataflow.new.DataFlow
|
||||||
private import semmle.python.dataflow.new.internal.ImportStar
|
private import semmle.python.dataflow.new.internal.ImportStar
|
||||||
private import semmle.python.dataflow.new.TypeTracking
|
private import semmle.python.dataflow.new.TypeTracking
|
||||||
private import semmle.python.dataflow.new.internal.DataFlowPrivate
|
private import semmle.python.dataflow.new.internal.DataFlowPrivate
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds if `init` is a package's `__init__.py` and `var` is a global variable in
|
* Holds if the name of `var` refers to a submodule of a package and `init` is
|
||||||
* `init` whose name matches a submodule of the package.
|
* the `__init__` module of that package. Locally inlined replacement for the
|
||||||
*
|
* legacy `SsaSource::init_module_submodule_defn` so that this module has no
|
||||||
* Inlined from `SsaSource::init_module_submodule_defn` to avoid pulling
|
* direct dependency on `semmle.python.essa.SsaDefinitions`.
|
||||||
* `semmle.python.essa.SsaDefinitions` into the new dataflow stack.
|
|
||||||
*/
|
*/
|
||||||
private predicate initModuleSubmoduleDefn(GlobalVariable var, Module init) {
|
private predicate initModuleSubmoduleDefn(GlobalVariable var, Module init) {
|
||||||
init.isPackageInit() and
|
init.isPackageInit() and
|
||||||
@@ -81,13 +82,19 @@ module ImportResolution {
|
|||||||
* Holds if there is an ESSA step from `defFrom` to `defTo`, which should be allowed
|
* Holds if there is an ESSA step from `defFrom` to `defTo`, which should be allowed
|
||||||
* for import resolution.
|
* for import resolution.
|
||||||
*/
|
*/
|
||||||
private predicate allowedEssaImportStep(EssaDefinition defFrom, EssaDefinition defTo) {
|
private predicate allowedEssaImportStep(
|
||||||
|
SsaImpl::EssaDefinition defFrom, SsaImpl::EssaDefinition defTo
|
||||||
|
) {
|
||||||
// to handle definitions guarded by if-then-else
|
// to handle definitions guarded by if-then-else
|
||||||
defFrom = defTo.(PhiFunction).getAnInput()
|
defFrom = defTo.(SsaImpl::PhiFunction).getAnInput()
|
||||||
or
|
or
|
||||||
// refined variable
|
// to handle uncertain writes such as `from X import *`, which create an
|
||||||
// example: https://github.com/nvbn/thefuck/blob/ceeaeab94b5df5a4fe9d94d61e4f6b0bbea96378/thefuck/utils.py#L25-L45
|
// uncertain SSA definition for every name in the importing scope. The
|
||||||
defFrom = defTo.(EssaNodeRefinement).getInput().getDefinition()
|
// immediately preceding definition is still potentially the value of the
|
||||||
|
// module export.
|
||||||
|
SsaImpl::Ssa::uncertainWriteDefinitionInput(defTo, defFrom)
|
||||||
|
// Note: legacy ESSA refinement-step (e.g. for `foo.bar = X`) is
|
||||||
|
// not modelled in the new SSA beyond the cases handled above.
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -104,30 +111,32 @@ module ImportResolution {
|
|||||||
// Definitions made inside `m` itself
|
// Definitions made inside `m` itself
|
||||||
//
|
//
|
||||||
// for code such as `foo = ...; foo.bar = ...` there will be TWO
|
// for code such as `foo = ...; foo.bar = ...` there will be TWO
|
||||||
// EssaDefinition/EssaVariable. One for `foo = ...` (AssignmentDefinition) and one
|
// SsaImpl::EssaDefinition/SsaImpl::EssaVariable. One for `foo = ...` (SsaImpl::AssignmentDefinition) and one
|
||||||
// for `foo.bar = ...`. The one for `foo.bar = ...` (EssaNodeRefinement). The
|
// for `foo.bar = ...`. The one for `foo.bar = ...` (EssaNodeRefinement). The
|
||||||
// EssaNodeRefinement is the one that will reach the end of the module (normal
|
// EssaNodeRefinement is the one that will reach the end of the module (normal
|
||||||
// exit).
|
// exit).
|
||||||
//
|
//
|
||||||
// However, we cannot just use the EssaNodeRefinement as the `val`, because the
|
// However, we cannot just use the EssaNodeRefinement as the `val`, because the
|
||||||
// normal data-flow depends on use-use flow, and use-use flow targets CFG nodes not
|
// normal data-flow depends on use-use flow, and use-use flow targets CFG nodes not
|
||||||
// EssaNodes. So we need to go back from the EssaDefinition/EssaVariable that
|
// EssaNodes. So we need to go back from the SsaImpl::EssaDefinition/SsaImpl::EssaVariable that
|
||||||
// reaches the end of the module, to the first definition of the variable, and then
|
// reaches the end of the module, to the first definition of the variable, and then
|
||||||
// track forwards using use-use flow to find a suitable CFG node that has flow into
|
// track forwards using use-use flow to find a suitable CFG node that has flow into
|
||||||
// it from use-use flow.
|
// it from use-use flow.
|
||||||
exists(EssaVariable lastUseVar, EssaVariable firstDef |
|
exists(SsaImpl::EssaVariable lastUseVar, SsaImpl::EssaVariable firstDef |
|
||||||
lastUseVar.getName() = name and
|
lastUseVar.getName() = name and
|
||||||
// we ignore special variable $ introduced by our analysis (not used for anything)
|
// we ignore special variable $ introduced by our analysis (not used for anything)
|
||||||
// we ignore special variable * introduced by `from <pkg> import *` -- TODO: understand why we even have this?
|
// we ignore special variable * introduced by `from <pkg> import *` -- TODO: understand why we even have this?
|
||||||
not name in ["$", "*"] and
|
not name in ["$", "*"] and
|
||||||
lastUseVar.getAUse() = m.getANormalExit() and
|
exists(Cfg::ControlFlowNode exit |
|
||||||
|
exit.isNormalExit() and exit.getScope() = m and lastUseVar.getAUse() = exit
|
||||||
|
) and
|
||||||
allowedEssaImportStep*(firstDef, lastUseVar) and
|
allowedEssaImportStep*(firstDef, lastUseVar) and
|
||||||
not allowedEssaImportStep(_, firstDef)
|
not allowedEssaImportStep(_, firstDef)
|
||||||
|
|
|
|
||||||
not LocalFlow::defToFirstUse(firstDef, _) and
|
not LocalFlow::defToFirstUse(firstDef, _) and
|
||||||
val.asCfgNode() = firstDef.getDefinition().(EssaNodeDefinition).getDefiningNode()
|
val.asCfgNode() = firstDef.getDefinition().(SsaImpl::EssaNodeDefinition).getDefiningNode()
|
||||||
or
|
or
|
||||||
exists(ControlFlowNode mid, ControlFlowNode end |
|
exists(Cfg::ControlFlowNode mid, Cfg::ControlFlowNode end |
|
||||||
LocalFlow::defToFirstUse(firstDef, mid) and
|
LocalFlow::defToFirstUse(firstDef, mid) and
|
||||||
LocalFlow::useToNextUse*(mid, end) and
|
LocalFlow::useToNextUse*(mid, end) and
|
||||||
not LocalFlow::useToNextUse(end, _) and
|
not LocalFlow::useToNextUse(end, _) and
|
||||||
@@ -155,9 +164,9 @@ module ImportResolution {
|
|||||||
* handles simple cases where we can statically tell that this is the case.
|
* handles simple cases where we can statically tell that this is the case.
|
||||||
*/
|
*/
|
||||||
private predicate all_mentions_name(Module m, string name) {
|
private predicate all_mentions_name(Module m, string name) {
|
||||||
exists(DefinitionNode def, SequenceNode n |
|
exists(Cfg::DefinitionNode def, Cfg::SequenceNode n |
|
||||||
def.getValue() = n and
|
def.getValue() = n and
|
||||||
def.(NameNode).getId() = "__all__" and
|
def.(Cfg::NameNode).getId() = "__all__" and
|
||||||
def.getScope() = m and
|
def.getScope() = m and
|
||||||
any(StringLiteral s | s.getText() = name) = n.getAnElement().getNode()
|
any(StringLiteral s | s.getText() = name) = n.getAnElement().getNode()
|
||||||
)
|
)
|
||||||
@@ -170,18 +179,20 @@ module ImportResolution {
|
|||||||
*/
|
*/
|
||||||
private predicate no_or_complicated_all(Module m) {
|
private predicate no_or_complicated_all(Module m) {
|
||||||
// No mention of `__all__` in the module
|
// No mention of `__all__` in the module
|
||||||
not exists(DefinitionNode def | def.getScope() = m and def.(NameNode).getId() = "__all__")
|
not exists(Cfg::DefinitionNode def |
|
||||||
|
def.getScope() = m and def.(Cfg::NameNode).getId() = "__all__"
|
||||||
|
)
|
||||||
or
|
or
|
||||||
// `__all__` is set to a non-sequence value
|
// `__all__` is set to a non-sequence value
|
||||||
exists(DefinitionNode def |
|
exists(Cfg::DefinitionNode def |
|
||||||
def.(NameNode).getId() = "__all__" and
|
def.(Cfg::NameNode).getId() = "__all__" and
|
||||||
def.getScope() = m and
|
def.getScope() = m and
|
||||||
not def.getValue() instanceof SequenceNode
|
not def.getValue() instanceof Cfg::SequenceNode
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
// `__all__` is used in some way that doesn't involve storing a value in it. This usually means
|
// `__all__` is used in some way that doesn't involve storing a value in it. This usually means
|
||||||
// it is being mutated through `append` or `extend`, which we don't handle.
|
// it is being mutated through `append` or `extend`, which we don't handle.
|
||||||
exists(NameNode n | n.getId() = "__all__" and n.getScope() = m and n.isLoad())
|
exists(Cfg::NameNode n | n.getId() = "__all__" and n.getScope() = m and n.isLoad())
|
||||||
}
|
}
|
||||||
|
|
||||||
private predicate potential_module_export(Module m, string name) {
|
private predicate potential_module_export(Module m, string name) {
|
||||||
@@ -189,7 +200,7 @@ module ImportResolution {
|
|||||||
or
|
or
|
||||||
no_or_complicated_all(m) and
|
no_or_complicated_all(m) and
|
||||||
(
|
(
|
||||||
exists(NameNode n | n.getId() = name and n.getScope() = m and name.charAt(0) != "_")
|
exists(Cfg::NameNode n | n.getId() = name and n.getScope() = m and name.charAt(0) != "_")
|
||||||
or
|
or
|
||||||
exists(Alias a | a.getAsname().(Name).getId() = name and a.getValue().getScope() = m)
|
exists(Alias a | a.getAsname().(Name).getId() = name and a.getValue().getScope() = m)
|
||||||
)
|
)
|
||||||
@@ -219,12 +230,12 @@ module ImportResolution {
|
|||||||
|
|
||||||
/** Gets a module that may have been added to `sys.modules`. */
|
/** Gets a module that may have been added to `sys.modules`. */
|
||||||
private Module sys_modules_module_with_name(string name) {
|
private Module sys_modules_module_with_name(string name) {
|
||||||
exists(ControlFlowNode n, DataFlow::Node mod |
|
exists(Cfg::ControlFlowNode n, DataFlow::Node mod |
|
||||||
exists(SubscriptNode sub |
|
exists(Cfg::SubscriptNode sub |
|
||||||
sub.getObject() = sys_modules_reference().asCfgNode() and
|
sub.getObject() = sys_modules_reference().asCfgNode() and
|
||||||
sub.getIndex() = n and
|
sub.getIndex() = n and
|
||||||
n.getNode().(StringLiteral).getText() = name and
|
n.getNode().(StringLiteral).getText() = name and
|
||||||
sub.(DefinitionNode).getValue() = mod.asCfgNode() and
|
sub.(Cfg::DefinitionNode).getValue() = mod.asCfgNode() and
|
||||||
mod = getModuleReference(result)
|
mod = getModuleReference(result)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -336,11 +347,11 @@ module ImportResolution {
|
|||||||
// name as a submodule, we always consider that this attribute _could_ be a
|
// name as a submodule, we always consider that this attribute _could_ be a
|
||||||
// reference to the submodule, even if we don't know that the submodule has been
|
// reference to the submodule, even if we don't know that the submodule has been
|
||||||
// imported yet.
|
// imported yet.
|
||||||
exists(string submodule, Module package, EssaVariable var |
|
exists(string submodule, Module package, SsaImpl::EssaVariable var |
|
||||||
submodule = var.getName() and
|
submodule = var.getName() and
|
||||||
initModuleSubmoduleDefn(var.getSourceVariable(), package) and
|
initModuleSubmoduleDefn(var.getSourceVariable().getVariable(), package) and
|
||||||
m = getModuleFromName(package.getPackageName() + "." + submodule) and
|
m = getModuleFromName(package.getPackageName() + "." + submodule) and
|
||||||
result.asCfgNode() = var.getDefinition().(EssaNodeDefinition).getDefiningNode()
|
result.asCfgNode() = var.getDefinition().(SsaImpl::EssaNodeDefinition).getDefiningNode()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ overlay[local]
|
|||||||
module;
|
module;
|
||||||
|
|
||||||
private import python
|
private import python
|
||||||
|
private import semmle.python.controlflow.internal.Cfg as Cfg
|
||||||
private import semmle.python.dataflow.new.internal.Builtins
|
private import semmle.python.dataflow.new.internal.Builtins
|
||||||
private import semmle.python.dataflow.new.internal.ImportResolution
|
private import semmle.python.dataflow.new.internal.ImportResolution
|
||||||
private import semmle.python.dataflow.new.DataFlow
|
private import semmle.python.dataflow.new.DataFlow
|
||||||
@@ -15,7 +16,7 @@ module ImportStar {
|
|||||||
*/
|
*/
|
||||||
overlay[local]
|
overlay[local]
|
||||||
cached
|
cached
|
||||||
predicate namePossiblyDefinedInImportStar(NameNode n, string name, Scope s) {
|
predicate namePossiblyDefinedInImportStar(Cfg::NameNode n, string name, Scope s) {
|
||||||
n.isLoad() and
|
n.isLoad() and
|
||||||
name = n.getId() and
|
name = n.getId() and
|
||||||
s = n.getScope().getEnclosingScope*() and
|
s = n.getScope().getEnclosingScope*() and
|
||||||
@@ -52,7 +53,7 @@ module ImportStar {
|
|||||||
/** Holds if a global variable called `name` is assigned a value in the module `m`. */
|
/** Holds if a global variable called `name` is assigned a value in the module `m`. */
|
||||||
cached
|
cached
|
||||||
predicate globalNameDefinedInModule(string name, Module m) {
|
predicate globalNameDefinedInModule(string name, Module m) {
|
||||||
exists(NameNode n |
|
exists(Cfg::NameNode n |
|
||||||
not exists(LocalVariable v | n.defines(v)) and
|
not exists(LocalVariable v | n.defines(v)) and
|
||||||
n.isStore() and
|
n.isStore() and
|
||||||
name = n.getId() and
|
name = n.getId() and
|
||||||
@@ -66,7 +67,7 @@ module ImportStar {
|
|||||||
*/
|
*/
|
||||||
overlay[global]
|
overlay[global]
|
||||||
cached
|
cached
|
||||||
predicate importStarResolvesTo(NameNode n, Module m) {
|
predicate importStarResolvesTo(Cfg::NameNode n, Module m) {
|
||||||
m = getStarImported+(n.getEnclosingModule()) and
|
m = getStarImported+(n.getEnclosingModule()) and
|
||||||
globalNameDefinedInModule(n.getId(), m) and
|
globalNameDefinedInModule(n.getId(), m) and
|
||||||
not isDefinedLocally(n.getNode())
|
not isDefinedLocally(n.getNode())
|
||||||
@@ -99,7 +100,7 @@ module ImportStar {
|
|||||||
*/
|
*/
|
||||||
overlay[local]
|
overlay[local]
|
||||||
cached
|
cached
|
||||||
ControlFlowNode potentialImportStarBase(Scope s) {
|
Cfg::ControlFlowNode potentialImportStarBase(Scope s) {
|
||||||
result = any(ImportStarNode n | n.getScope() = s).getModule()
|
result = any(Cfg::ImportStarNode n | n.getScope() = s).getModule()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -170,6 +170,8 @@ overlay[local]
|
|||||||
module;
|
module;
|
||||||
|
|
||||||
private import python
|
private import python
|
||||||
|
private import semmle.python.controlflow.internal.Cfg as Cfg
|
||||||
|
private import semmle.python.dataflow.new.internal.SsaImpl as SsaImpl
|
||||||
private import DataFlowPublic
|
private import DataFlowPublic
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -178,7 +180,7 @@ private import DataFlowPublic
|
|||||||
* This class abstracts away the differing representations of comprehensions and
|
* This class abstracts away the differing representations of comprehensions and
|
||||||
* for statements.
|
* for statements.
|
||||||
*/
|
*/
|
||||||
class ForTarget extends ControlFlowNode {
|
class ForTarget extends Cfg::ControlFlowNode {
|
||||||
Expr source;
|
Expr source;
|
||||||
|
|
||||||
ForTarget() {
|
ForTarget() {
|
||||||
@@ -198,7 +200,7 @@ class ForTarget extends ControlFlowNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** The LHS of an assignment, it also records the assigned value. */
|
/** The LHS of an assignment, it also records the assigned value. */
|
||||||
class AssignmentTarget extends ControlFlowNode {
|
class AssignmentTarget extends Cfg::ControlFlowNode {
|
||||||
Expr value;
|
Expr value;
|
||||||
|
|
||||||
AssignmentTarget() {
|
AssignmentTarget() {
|
||||||
@@ -209,7 +211,7 @@ class AssignmentTarget extends ControlFlowNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** A direct (or top-level) target of an unpacking assignment. */
|
/** A direct (or top-level) target of an unpacking assignment. */
|
||||||
class UnpackingAssignmentDirectTarget extends ControlFlowNode instanceof SequenceNode {
|
class UnpackingAssignmentDirectTarget extends Cfg::ControlFlowNode instanceof Cfg::SequenceNode {
|
||||||
Expr value;
|
Expr value;
|
||||||
|
|
||||||
UnpackingAssignmentDirectTarget() {
|
UnpackingAssignmentDirectTarget() {
|
||||||
@@ -222,7 +224,7 @@ class UnpackingAssignmentDirectTarget extends ControlFlowNode instanceof Sequenc
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** A (possibly recursive) target of an unpacking assignment. */
|
/** A (possibly recursive) target of an unpacking assignment. */
|
||||||
class UnpackingAssignmentTarget extends ControlFlowNode {
|
class UnpackingAssignmentTarget extends Cfg::ControlFlowNode {
|
||||||
UnpackingAssignmentTarget() {
|
UnpackingAssignmentTarget() {
|
||||||
this instanceof UnpackingAssignmentDirectTarget
|
this instanceof UnpackingAssignmentDirectTarget
|
||||||
or
|
or
|
||||||
@@ -231,10 +233,11 @@ class UnpackingAssignmentTarget extends ControlFlowNode {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** A (possibly recursive) target of an unpacking assignment which is also a sequence. */
|
/** A (possibly recursive) target of an unpacking assignment which is also a sequence. */
|
||||||
class UnpackingAssignmentSequenceTarget extends UnpackingAssignmentTarget instanceof SequenceNode {
|
class UnpackingAssignmentSequenceTarget extends UnpackingAssignmentTarget instanceof Cfg::SequenceNode
|
||||||
ControlFlowNode getElement(int i) { result = super.getElement(i) }
|
{
|
||||||
|
Cfg::ControlFlowNode getElement(int i) { result = super.getElement(i) }
|
||||||
|
|
||||||
ControlFlowNode getAnElement() { result = this.getElement(_) }
|
Cfg::ControlFlowNode getAnElement() { result = this.getElement(_) }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -255,7 +258,7 @@ predicate iterableUnpackingAssignmentFlowStep(Node nodeFrom, Node nodeTo) {
|
|||||||
predicate iterableUnpackingForReadStep(CfgNode nodeFrom, Content c, Node nodeTo) {
|
predicate iterableUnpackingForReadStep(CfgNode nodeFrom, Content c, Node nodeTo) {
|
||||||
exists(ForTarget target |
|
exists(ForTarget target |
|
||||||
nodeFrom.getNode().getNode() = target.getSource() and
|
nodeFrom.getNode().getNode() = target.getSource() and
|
||||||
target instanceof SequenceNode and
|
target instanceof Cfg::SequenceNode and
|
||||||
nodeTo = TIterableSequenceNode(target)
|
nodeTo = TIterableSequenceNode(target)
|
||||||
) and
|
) and
|
||||||
(
|
(
|
||||||
@@ -323,11 +326,11 @@ predicate iterableUnpackingConvertingStoreStep(Node nodeFrom, Content c, Node no
|
|||||||
*/
|
*/
|
||||||
predicate iterableUnpackingElementReadStep(Node nodeFrom, Content c, Node nodeTo) {
|
predicate iterableUnpackingElementReadStep(Node nodeFrom, Content c, Node nodeTo) {
|
||||||
exists(
|
exists(
|
||||||
UnpackingAssignmentSequenceTarget target, int index, ControlFlowNode element, int starIndex
|
UnpackingAssignmentSequenceTarget target, int index, Cfg::ControlFlowNode element, int starIndex
|
||||||
|
|
|
|
||||||
target.getElement(starIndex) instanceof StarredNode
|
target.getElement(starIndex) instanceof Cfg::StarredNode
|
||||||
or
|
or
|
||||||
not exists(target.getAnElement().(StarredNode)) and
|
not exists(target.getAnElement().(Cfg::StarredNode)) and
|
||||||
starIndex = -1
|
starIndex = -1
|
||||||
|
|
|
|
||||||
nodeFrom.(CfgNode).getNode() = target and
|
nodeFrom.(CfgNode).getNode() = target and
|
||||||
@@ -342,18 +345,18 @@ predicate iterableUnpackingElementReadStep(Node nodeFrom, Content c, Node nodeTo
|
|||||||
else c.(TupleElementContent).getIndex() >= index - 1
|
else c.(TupleElementContent).getIndex() >= index - 1
|
||||||
) and
|
) and
|
||||||
(
|
(
|
||||||
if element instanceof SequenceNode
|
if element instanceof Cfg::SequenceNode
|
||||||
then
|
then
|
||||||
// Step 5b
|
// Step 5b
|
||||||
nodeTo = TIterableSequenceNode(element)
|
nodeTo = TIterableSequenceNode(element)
|
||||||
else
|
else
|
||||||
if element instanceof StarredNode
|
if element instanceof Cfg::StarredNode
|
||||||
then
|
then
|
||||||
// Step 5c
|
// Step 5c
|
||||||
nodeTo = TIterableElementNode(element)
|
nodeTo = TIterableElementNode(element)
|
||||||
else
|
else
|
||||||
// Step 5a
|
// Step 5a
|
||||||
exists(MultiAssignmentDefinition mad | element = mad.getDefiningNode() |
|
exists(SsaImpl::MultiAssignmentDefinition mad | element = mad.getDefiningNode() |
|
||||||
nodeTo.(CfgNode).getNode() = element
|
nodeTo.(CfgNode).getNode() = element
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
@@ -366,7 +369,7 @@ predicate iterableUnpackingElementReadStep(Node nodeFrom, Content c, Node nodeTo
|
|||||||
* content type `ListElementContent`.
|
* content type `ListElementContent`.
|
||||||
*/
|
*/
|
||||||
predicate iterableUnpackingStarredElementStoreStep(Node nodeFrom, Content c, Node nodeTo) {
|
predicate iterableUnpackingStarredElementStoreStep(Node nodeFrom, Content c, Node nodeTo) {
|
||||||
exists(ControlFlowNode starred, MultiAssignmentDefinition mad |
|
exists(Cfg::ControlFlowNode starred, SsaImpl::MultiAssignmentDefinition mad |
|
||||||
starred.getNode() instanceof Starred and
|
starred.getNode() instanceof Starred and
|
||||||
starred = mad.getDefiningNode()
|
starred = mad.getDefiningNode()
|
||||||
|
|
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ overlay[local]
|
|||||||
module;
|
module;
|
||||||
|
|
||||||
private import python
|
private import python
|
||||||
|
private import semmle.python.controlflow.internal.Cfg as Cfg
|
||||||
import DataFlowPublic
|
import DataFlowPublic
|
||||||
private import DataFlowPrivate
|
private import DataFlowPrivate
|
||||||
private import semmle.python.internal.CachedStages
|
private import semmle.python.internal.CachedStages
|
||||||
@@ -314,7 +315,7 @@ private module Cached {
|
|||||||
*/
|
*/
|
||||||
cached
|
cached
|
||||||
predicate subscript(LocalSourceNode node, CfgNode subscript, CfgNode index) {
|
predicate subscript(LocalSourceNode node, CfgNode subscript, CfgNode index) {
|
||||||
exists(CfgNode seq, SubscriptNode subscriptNode | subscriptNode = subscript.getNode() |
|
exists(CfgNode seq, Cfg::SubscriptNode subscriptNode | subscriptNode = subscript.getNode() |
|
||||||
node.flowsTo(seq) and
|
node.flowsTo(seq) and
|
||||||
seq.getNode() = subscriptNode.getObject() and
|
seq.getNode() = subscriptNode.getObject() and
|
||||||
index.getNode() = subscriptNode.getIndex()
|
index.getNode() = subscriptNode.getIndex()
|
||||||
|
|||||||
@@ -91,9 +91,7 @@ predicate matchAsFlowStep(Node nodeFrom, Node nodeTo) {
|
|||||||
or
|
or
|
||||||
// the interior pattern flows to the alias
|
// the interior pattern flows to the alias
|
||||||
nodeFrom.(CfgNode).getNode().getNode() = subject.getPattern() and
|
nodeFrom.(CfgNode).getNode().getNode() = subject.getPattern() and
|
||||||
exists(PatternAliasDefinition pad | pad.getDefiningNode().getNode() = alias |
|
nodeTo.(CfgNode).getNode().getNode() = alias
|
||||||
nodeTo.(CfgNode).getNode() = pad.getDefiningNode()
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -124,11 +122,9 @@ predicate matchLiteralFlowStep(Node nodeFrom, Node nodeTo) {
|
|||||||
* syntax (toplevel): `case var:`
|
* syntax (toplevel): `case var:`
|
||||||
*/
|
*/
|
||||||
predicate matchCaptureFlowStep(Node nodeFrom, Node nodeTo) {
|
predicate matchCaptureFlowStep(Node nodeFrom, Node nodeTo) {
|
||||||
exists(MatchCapturePattern capture, Name var | capture.getVariable() = var |
|
exists(MatchCapturePattern capture |
|
||||||
nodeFrom.(CfgNode).getNode().getNode() = capture and
|
nodeFrom.(CfgNode).getNode().getNode() = capture and
|
||||||
exists(PatternCaptureDefinition pcd | pcd.getDefiningNode().getNode() = var |
|
nodeTo.(CfgNode).getNode().getNode() = capture.getVariable()
|
||||||
nodeTo.(CfgNode).getNode() = pcd.getDefiningNode()
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
548
python/ql/lib/semmle/python/dataflow/new/internal/SsaImpl.qll
Normal file
548
python/ql/lib/semmle/python/dataflow/new/internal/SsaImpl.qll
Normal file
@@ -0,0 +1,548 @@
|
|||||||
|
/**
|
||||||
|
* Provides the Python SSA implementation built on the new (shared) CFG.
|
||||||
|
*
|
||||||
|
* Mirrors the Java SSA adapter at
|
||||||
|
* `java/ql/lib/semmle/code/java/dataflow/internal/SsaImpl.qll`:
|
||||||
|
* an `InputSig` is defined in terms of positional `(BasicBlock, int)`
|
||||||
|
* variable references, and the shared
|
||||||
|
* `codeql.ssa.Ssa::Make<Location, Cfg, Input>` module is then
|
||||||
|
* instantiated.
|
||||||
|
*
|
||||||
|
* `SourceVariable` is the AST-level `Py::Variable`. Variable references
|
||||||
|
* are looked up via the CFG facade's `NameNode.defines`/`uses`/`deletes`
|
||||||
|
* predicates, which themselves are one-line bridges to AST-level
|
||||||
|
* `Name.defines`/`uses`/`deletes`.
|
||||||
|
*
|
||||||
|
* Implicit-entry definitions are inserted for:
|
||||||
|
* - non-local / global / builtin variables that are read in the scope
|
||||||
|
* but never assigned (no enclosing CFG node defines them),
|
||||||
|
* - captured variables (variables defined in an enclosing scope that
|
||||||
|
* are read inside the scope), and
|
||||||
|
* - parameters, but only if the corresponding parameter name is *not*
|
||||||
|
* itself a CFG node. With the C#-style parameter wiring already
|
||||||
|
* installed in `AstNodeImpl.qll`, parameter names *are* CFG nodes,
|
||||||
|
* so the regular `variableWrite` path handles them — no `i = -1`
|
||||||
|
* entry is needed for ordinary parameters.
|
||||||
|
*/
|
||||||
|
overlay[local?]
|
||||||
|
module;
|
||||||
|
|
||||||
|
private import python as Py
|
||||||
|
private import semmle.python.controlflow.internal.AstNodeImpl as CfgImpl
|
||||||
|
private import semmle.python.controlflow.internal.Cfg as Cfg
|
||||||
|
private import codeql.ssa.Ssa as SsaImplCommon
|
||||||
|
private import codeql.controlflow.BasicBlock as BB
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adapts the Python `Cfg` facade to the shared SSA library's `CfgSig`.
|
||||||
|
* All members are inherited from `Cfg::ControlFlowNode` and
|
||||||
|
* `Cfg::BasicBlock`.
|
||||||
|
*/
|
||||||
|
private module CfgForSsa implements BB::CfgSig<Py::Location> {
|
||||||
|
class ControlFlowNode = CfgImpl::ControlFlowNode;
|
||||||
|
|
||||||
|
class BasicBlock = CfgImpl::BasicBlock;
|
||||||
|
|
||||||
|
class EntryBasicBlock = CfgImpl::Cfg::EntryBasicBlock;
|
||||||
|
|
||||||
|
predicate dominatingEdge = CfgImpl::Cfg::dominatingEdge/2;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A source variable for SSA, wrapping a Python AST `Variable`.
|
||||||
|
*
|
||||||
|
* We only track variables that are read at least once in their scope —
|
||||||
|
* tracking write-only variables would be unnecessary work — *except*
|
||||||
|
* for module-scope globals, where the "read" can be external (e.g.
|
||||||
|
* `import mymodule; mymodule.x`). Such globals are tracked
|
||||||
|
* unconditionally so that import-resolution can find their defining
|
||||||
|
* write.
|
||||||
|
*/
|
||||||
|
private newtype TSsaSourceVariable =
|
||||||
|
TPyVar(Py::Variable v) {
|
||||||
|
// Has a use somewhere — read-relevant for SSA.
|
||||||
|
exists(Cfg::NameNode n | n.uses(v))
|
||||||
|
or
|
||||||
|
// Or has a deletion (treated as a write that destroys the value).
|
||||||
|
exists(Cfg::NameNode n | n.deletes(v))
|
||||||
|
or
|
||||||
|
// Or is a module-scope global written in this module — must be
|
||||||
|
// tracked even if never read locally, because importers may read
|
||||||
|
// it as an attribute on the module object.
|
||||||
|
v.getScope() instanceof Py::Module and
|
||||||
|
exists(Cfg::NameNode n | n.defines(v))
|
||||||
|
or
|
||||||
|
// Or is a parameter — parameters must always have a
|
||||||
|
// `ParameterDefinition` for dataflow argument-routing to work,
|
||||||
|
// even if the parameter is never read in its scope. Mirrors
|
||||||
|
// legacy ESSA's `ParameterDefinition` (which fired for every
|
||||||
|
// parameter binding regardless of liveness).
|
||||||
|
exists(Py::Parameter p | p.asName() = v.getAStore())
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A source variable for SSA, wrapping a Python AST `Variable`.
|
||||||
|
*/
|
||||||
|
class SsaSourceVariable extends TSsaSourceVariable {
|
||||||
|
/** Gets the underlying Python AST variable. */
|
||||||
|
Py::Variable getVariable() { this = TPyVar(result) }
|
||||||
|
|
||||||
|
/** Gets the (textual) name of this variable. */
|
||||||
|
string getName() { result = this.getVariable().getId() }
|
||||||
|
|
||||||
|
/** Gets a textual representation of this source variable. */
|
||||||
|
string toString() { result = this.getVariable().toString() }
|
||||||
|
|
||||||
|
/** Gets the location of this source variable. */
|
||||||
|
Py::Location getLocation() { result = this.getVariable().getScope().getLocation() }
|
||||||
|
|
||||||
|
/** Gets the scope in which this variable lives. */
|
||||||
|
Py::Scope getScope() { result = this.getVariable().getScope() }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a use of this variable as it appears in the source — a `NameNode`
|
||||||
|
* that loads or deletes the variable. Mirrors legacy
|
||||||
|
* `SsaSourceVariable.getASourceUse()`.
|
||||||
|
*/
|
||||||
|
Cfg::ControlFlowNode getASourceUse() {
|
||||||
|
exists(Cfg::NameNode n | result = n |
|
||||||
|
n.uses(this.getVariable()) or n.deletes(this.getVariable())
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets an implicit use of this variable. The new SSA does not have
|
||||||
|
* implicit-use refinements, but we keep this for API parity — every
|
||||||
|
* normal-exit of the variable's scope counts as a sink, ensuring
|
||||||
|
* variables stay live to scope exit for taint-tracking.
|
||||||
|
*/
|
||||||
|
Cfg::ControlFlowNode getAnImplicitUse() {
|
||||||
|
result.isNormalExit() and result.getScope() = this.getScope()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a use of this variable — either an explicit source use or an
|
||||||
|
* implicit use at scope exit. Mirrors legacy `SsaSourceVariable.getAUse()`.
|
||||||
|
*/
|
||||||
|
Cfg::ControlFlowNode getAUse() {
|
||||||
|
result = this.getASourceUse() or result = this.getAnImplicitUse()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds if `v` is a non-local read in scope `s`, in the sense that `s`
|
||||||
|
* uses `v` but does not write it within `s`. This includes globals,
|
||||||
|
* builtins, and variables captured from an enclosing function scope.
|
||||||
|
*
|
||||||
|
* The `Py::Variable` `v` lives in some defining scope (the module for
|
||||||
|
* globals, an outer function for closures, etc.); the reading scope
|
||||||
|
* `s` is the scope where the use of `v` occurs.
|
||||||
|
*/
|
||||||
|
private predicate nonLocalReadIn(Py::Variable v, Py::Scope s) {
|
||||||
|
exists(Cfg::NameNode n |
|
||||||
|
n.uses(v) and
|
||||||
|
n.getScope() = s and
|
||||||
|
not exists(Cfg::NameNode def | def.defines(v) and def.getScope() = s)
|
||||||
|
) and
|
||||||
|
// Match legacy ESSA: only create entry defs for variables that have
|
||||||
|
// at least one defining store somewhere — otherwise the entry def
|
||||||
|
// represents "nothing reaches here", which is the default anyway and
|
||||||
|
// introduces no useful flow. (Legacy's `ModuleVariable` required a
|
||||||
|
// store; this is the closure-aware generalisation.)
|
||||||
|
exists(Cfg::NameNode store | store.defines(v))
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds if `bb` is the entry basic block of a scope where `v` should
|
||||||
|
* have an implicit entry definition. This covers:
|
||||||
|
* - non-local / global / builtin variables read in `s`, and
|
||||||
|
* - captured variables (defined in an enclosing scope but read in `s`).
|
||||||
|
*
|
||||||
|
* Each reading scope gets its own entry def, so a closure variable can
|
||||||
|
* have multiple entry defs across all functions/methods that read it.
|
||||||
|
*
|
||||||
|
* Parameters are *not* included: their bound `Name` is itself a CFG
|
||||||
|
* node (per the C#-style parameter wiring), so `variableWrite` fires at
|
||||||
|
* the parameter's natural CFG index.
|
||||||
|
*/
|
||||||
|
private predicate hasEntryDefIn(SsaSourceVariable v, CfgImpl::BasicBlock bb) {
|
||||||
|
exists(Py::Scope s |
|
||||||
|
nonLocalReadIn(v.getVariable(), s) and
|
||||||
|
bb = entryBlock(s)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the entry basic block of scope `s`, where implicit entry
|
||||||
|
* definitions are placed (at synthetic index `-1`).
|
||||||
|
*/
|
||||||
|
private CfgImpl::BasicBlock entryBlock(Py::Scope s) {
|
||||||
|
exists(CfgImpl::ControlFlowNode entry |
|
||||||
|
entry instanceof CfgImpl::ControlFlow::EntryNode and
|
||||||
|
entry.getEnclosingCallable().asScope() = s and
|
||||||
|
result = entry.getBasicBlock()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The SSA `InputSig` for Python. References are positional
|
||||||
|
* `(BasicBlock, int)` pairs into the new CFG.
|
||||||
|
*/
|
||||||
|
private module SsaImplInput implements SsaImplCommon::InputSig<Py::Location, CfgImpl::BasicBlock> {
|
||||||
|
class SourceVariable = SsaSourceVariable;
|
||||||
|
|
||||||
|
predicate variableWrite(CfgImpl::BasicBlock bb, int i, SourceVariable v, boolean certain) {
|
||||||
|
// Explicit binding at a CFG node — includes assignments,
|
||||||
|
// parameter Names (wired in via the C# pattern), exception-handler
|
||||||
|
// `as`-bindings, import aliases, and match-pattern captures.
|
||||||
|
exists(Cfg::NameNode n |
|
||||||
|
bb.getNode(i) = n and
|
||||||
|
n.defines(v.getVariable()) and
|
||||||
|
certain = true
|
||||||
|
)
|
||||||
|
or
|
||||||
|
// `del x` — removes the binding. Modelled as a certain write that
|
||||||
|
// makes any subsequent read invalid.
|
||||||
|
exists(Cfg::NameNode n |
|
||||||
|
bb.getNode(i) = n and
|
||||||
|
n.deletes(v.getVariable()) and
|
||||||
|
certain = true
|
||||||
|
)
|
||||||
|
or
|
||||||
|
// Implicit entry definition for non-local / captured / global /
|
||||||
|
// builtin variables read in some scope. Each reading scope's entry
|
||||||
|
// block gets one such write, allowing closures: e.g. when `x` is a
|
||||||
|
// parameter of an outer function and read inside a nested
|
||||||
|
// function, both scopes get entry defs for `x`.
|
||||||
|
hasEntryDefIn(v, bb) and
|
||||||
|
i = -1 and
|
||||||
|
certain = true
|
||||||
|
or
|
||||||
|
// `from X import *` — possibly rebinds every name in the importing
|
||||||
|
// scope. Modelled as an uncertain write at the import-star's CFG
|
||||||
|
// position for every variable that lives in (or is referenced
|
||||||
|
// from) the same scope as the import-star. Mirrors legacy ESSA's
|
||||||
|
// `ImportStarRefinement` (see `essa/SsaDefinitions.qll`'s
|
||||||
|
// `import_star_refinement` predicate). The write is uncertain so
|
||||||
|
// that prior definitions of the variable remain available — the
|
||||||
|
// shared-SSA `SsaUncertainWrite` merges the new value with the
|
||||||
|
// immediately preceding definition.
|
||||||
|
exists(Cfg::ImportStarNode imp |
|
||||||
|
imp.injects(_) and
|
||||||
|
bb.getNode(i) = imp and
|
||||||
|
certain = false and
|
||||||
|
(
|
||||||
|
v.getVariable().getScope() = imp.getScope()
|
||||||
|
or
|
||||||
|
// Variable is defined in some other scope but referenced in
|
||||||
|
// the same scope as the import-star (matches legacy clause 2:
|
||||||
|
// `other.uses(v) and def.getScope() = other.getScope()`).
|
||||||
|
exists(Cfg::NameNode other |
|
||||||
|
other.uses(v.getVariable()) and
|
||||||
|
imp.getScope() = other.getScope()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
predicate variableRead(CfgImpl::BasicBlock bb, int i, SourceVariable v, boolean certain) {
|
||||||
|
// Explicit source use — a `Name` load or a `del x` of the variable.
|
||||||
|
exists(Cfg::NameNode n |
|
||||||
|
bb.getNode(i) = n and
|
||||||
|
n.uses(v.getVariable()) and
|
||||||
|
certain = true
|
||||||
|
)
|
||||||
|
or
|
||||||
|
// Synthetic use at the normal exit of the variable's defining scope.
|
||||||
|
// This keeps every variable live to scope exit so that callers (e.g.
|
||||||
|
// `module_export` in ImportResolution.qll, or taint-tracking pass-through
|
||||||
|
// through unread locals) can ask "which definition reaches end of
|
||||||
|
// scope?". Mirrors legacy ESSA's `SsaSourceVariable.getAUse()` which
|
||||||
|
// included `getScope().getANormalExit()`.
|
||||||
|
exists(Cfg::ControlFlowNode exit |
|
||||||
|
exit.isNormalExit() and
|
||||||
|
exit.getScope() = v.getVariable().getScope() and
|
||||||
|
bb.getNode(i) = exit and
|
||||||
|
certain = true
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The shared SSA instantiation for Python.
|
||||||
|
*
|
||||||
|
* Members:
|
||||||
|
* - `Definition` — the union of explicit, uncertain, and phi definitions
|
||||||
|
* - `WriteDefinition`, `UncertainWriteDefinition`, `PhiNode`
|
||||||
|
* - the standard SSA predicates (`getAUse`, `getAnUltimateDefinition`, ...).
|
||||||
|
*/
|
||||||
|
module Ssa = SsaImplCommon::Make<Py::Location, CfgForSsa, SsaImplInput>;
|
||||||
|
|
||||||
|
final class Definition = Ssa::Definition;
|
||||||
|
|
||||||
|
final class WriteDefinition = Ssa::WriteDefinition;
|
||||||
|
|
||||||
|
final class UncertainWriteDefinition = Ssa::UncertainWriteDefinition;
|
||||||
|
|
||||||
|
final class PhiNode = Ssa::PhiNode;
|
||||||
|
|
||||||
|
// ===========================================================================
|
||||||
|
// ESSA-shaped adapter layer
|
||||||
|
//
|
||||||
|
// The dataflow library (`python/ql/lib/semmle/python/dataflow/new/`) and
|
||||||
|
// related modules (`ApiGraphs.qll`, etc.) consume the legacy ESSA API
|
||||||
|
// (`EssaVariable`, `EssaDefinition`, `AssignmentDefinition`,
|
||||||
|
// `ScopeEntryDefinition`, `ParameterDefinition`, `WithDefinition`,
|
||||||
|
// `PhiFunction`, plus the `AdjacentUses` module). To migrate them off
|
||||||
|
// the legacy CFG, we expose the same API surface on top of the
|
||||||
|
// shared SSA built above.
|
||||||
|
//
|
||||||
|
// This adapter is intentionally narrow: it covers only the predicates
|
||||||
|
// that new dataflow consumes. The richer legacy ESSA — refinement
|
||||||
|
// nodes, attribute refinements, edge refinements — stays available
|
||||||
|
// via `semmle.python.essa.Essa` for points-to / legacy code.
|
||||||
|
// ===========================================================================
|
||||||
|
/**
|
||||||
|
* Gets the CFG node at which a write definition's binding takes place.
|
||||||
|
*
|
||||||
|
* For ordinary writes (assignment, deletion, parameter) this is the
|
||||||
|
* canonical CFG node of the bound Name. For implicit entry definitions
|
||||||
|
* (synthesised at position `-1` of a scope's entry BB) this is the
|
||||||
|
* scope's entry node.
|
||||||
|
*/
|
||||||
|
private Cfg::ControlFlowNode writeDefNode(Ssa::WriteDefinition def) {
|
||||||
|
exists(CfgImpl::BasicBlock bb, int i | def.definesAt(_, bb, i) |
|
||||||
|
i >= 0 and result = bb.getNode(i)
|
||||||
|
or
|
||||||
|
i = -1 and result = bb.getNode(0)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A write definition whose binding has a corresponding CFG node — i.e.
|
||||||
|
* everything that's not a phi node. Mirrors legacy ESSA's
|
||||||
|
* `EssaNodeDefinition`.
|
||||||
|
*/
|
||||||
|
class EssaNodeDefinition extends Ssa::WriteDefinition {
|
||||||
|
/** Gets the CFG node where this definition's binding takes place. */
|
||||||
|
Cfg::ControlFlowNode getDefiningNode() { result = writeDefNode(this) }
|
||||||
|
|
||||||
|
/** Gets the variable defined here (legacy name). */
|
||||||
|
SsaSourceVariable getVariable() { result = this.getSourceVariable() }
|
||||||
|
|
||||||
|
/** Gets the enclosing scope. */
|
||||||
|
Py::Scope getScope() {
|
||||||
|
exists(Cfg::ControlFlowNode n | n = this.getDefiningNode() | result = n.getScope())
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds if this definition defines source variable `v` at CFG node
|
||||||
|
* `defNode`. Flatter form of `getSourceVariable()` +
|
||||||
|
* `getDefiningNode()`, matching legacy ESSA's `definedBy`.
|
||||||
|
*/
|
||||||
|
predicate definedBy(SsaSourceVariable v, Cfg::ControlFlowNode defNode) {
|
||||||
|
v = this.getSourceVariable() and defNode = this.getDefiningNode()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An assignment definition: any binding where the value being assigned
|
||||||
|
* is statically known via `Cfg::DefinitionNode.getValue()`. Includes
|
||||||
|
* plain assignments, walrus, annotated assignments, augmented
|
||||||
|
* assignments, import aliases (`import x` / `from m import x [as y]`),
|
||||||
|
* `with ... as x`, and for-target bindings (where `getValue()` returns
|
||||||
|
* the iter expression's CFG node). Excludes parameter bindings —
|
||||||
|
* those are modelled by `ParameterDefinition`.
|
||||||
|
*/
|
||||||
|
class AssignmentDefinition extends EssaNodeDefinition {
|
||||||
|
AssignmentDefinition() {
|
||||||
|
exists(Cfg::NameNode n | n = this.getDefiningNode() |
|
||||||
|
exists(n.(Cfg::DefinitionNode).getValue()) and
|
||||||
|
not n.(Cfg::ControlFlowNode).isParameter()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Gets the CFG node for the value being assigned, if statically known. */
|
||||||
|
Cfg::ControlFlowNode getValue() {
|
||||||
|
result = this.getDefiningNode().(Cfg::DefinitionNode).getValue()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A parameter definition — the binding of a parameter name in a
|
||||||
|
* function's scope.
|
||||||
|
*/
|
||||||
|
class ParameterDefinition extends EssaNodeDefinition {
|
||||||
|
ParameterDefinition() { this.getDefiningNode().isParameter() }
|
||||||
|
|
||||||
|
/** Gets the AST `Parameter` (a `Py::Name` in param context). */
|
||||||
|
Py::Name getParameter() { result = this.getDefiningNode().getNode() }
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A definition introduced by a `with ... as x:` clause.
|
||||||
|
*/
|
||||||
|
class WithDefinition extends EssaNodeDefinition {
|
||||||
|
WithDefinition() {
|
||||||
|
exists(Cfg::NameNode n, Py::With w |
|
||||||
|
n = this.getDefiningNode() and
|
||||||
|
w.getOptionalVars() = n.getNode()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An assignment where the LHS is a tuple/list and the RHS is unpacked:
|
||||||
|
* `a, b = (1, 2)` or `a, *rest = xs`. The SSA def lives at the inner
|
||||||
|
* `Name` CFG node, but for IterableUnpacking integration we expose
|
||||||
|
* the enclosing `StarredNode` as the `getDefiningNode()` for `*rest`
|
||||||
|
* patterns — mirroring legacy ESSA's `multi_assignment_definition`,
|
||||||
|
* which placed the def at the StarredNode CFG node.
|
||||||
|
*/
|
||||||
|
class MultiAssignmentDefinition extends EssaNodeDefinition {
|
||||||
|
MultiAssignmentDefinition() {
|
||||||
|
exists(Cfg::NameNode n | n = super.getDefiningNode() |
|
||||||
|
exists(Py::Assign a, Py::Expr lhs |
|
||||||
|
a.getATarget() = lhs and
|
||||||
|
(lhs instanceof Py::Tuple or lhs instanceof Py::List) and
|
||||||
|
lhs.getASubExpression+() = n.getNode()
|
||||||
|
)
|
||||||
|
or
|
||||||
|
// For-loop with tuple/list target: `for a, b in xs:` —
|
||||||
|
// tuple-unpacking semantics applies to the for-target.
|
||||||
|
exists(Py::For f, Py::Expr lhs |
|
||||||
|
f.getTarget() = lhs and
|
||||||
|
(lhs instanceof Py::Tuple or lhs instanceof Py::List) and
|
||||||
|
lhs.getASubExpression+() = n.getNode()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
override Cfg::ControlFlowNode getDefiningNode() {
|
||||||
|
// Default: the underlying `Name` CFG node (where the SSA def lives).
|
||||||
|
not exists(Cfg::StarredNode s |
|
||||||
|
s.getNode().(Py::Starred).getValue() = super.getDefiningNode().getNode()
|
||||||
|
) and
|
||||||
|
result = super.getDefiningNode()
|
||||||
|
or
|
||||||
|
// Exception: for `*rest`, expose the enclosing `Starred` CFG node
|
||||||
|
// so that `IterableUnpacking::iterableUnpackingStarredElementStoreStep`
|
||||||
|
// can attach the rest-list to it.
|
||||||
|
exists(Cfg::StarredNode s |
|
||||||
|
s.getNode().(Py::Starred).getValue() = super.getDefiningNode().getNode()
|
||||||
|
|
|
||||||
|
result = s
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An implicit entry definition for a non-local / captured / global /
|
||||||
|
* builtin variable read in a scope but not defined there.
|
||||||
|
*
|
||||||
|
* Inherits from `EssaNodeDefinition` and exposes the scope's entry node
|
||||||
|
* as its defining node (matching legacy ESSA semantics).
|
||||||
|
*/
|
||||||
|
class ScopeEntryDefinition extends EssaNodeDefinition {
|
||||||
|
ScopeEntryDefinition() {
|
||||||
|
exists(CfgImpl::BasicBlock bb |
|
||||||
|
this.definesAt(_, bb, -1) and
|
||||||
|
bb instanceof CfgImpl::Cfg::EntryBasicBlock
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Gets the enclosing scope (the scope whose entry block this def is in). */
|
||||||
|
override Py::Scope getScope() {
|
||||||
|
exists(CfgImpl::BasicBlock bb |
|
||||||
|
this.definesAt(_, bb, -1) and
|
||||||
|
result = bb.getNode(0).(Cfg::ControlFlowNode).getScope()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** A phi node (alias matching legacy naming). */
|
||||||
|
class PhiFunction extends PhiNode {
|
||||||
|
/**
|
||||||
|
* Gets an input to this phi function (a definition that flows into
|
||||||
|
* the phi from one of its predecessor blocks). Mirrors legacy
|
||||||
|
* ESSA's `PhiFunction.getAnInput()`.
|
||||||
|
*/
|
||||||
|
Ssa::Definition getAnInput() { Ssa::phiHasInputFromBlock(this, result, _) }
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Base class for all ESSA definitions (legacy-shaped). */
|
||||||
|
class EssaDefinition = Ssa::Definition;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* An adapter representing a single SSA-defined "variable" — wrapping
|
||||||
|
* one `Ssa::Definition`. Mirrors legacy `EssaVariable` API.
|
||||||
|
*/
|
||||||
|
class EssaVariable extends Ssa::Definition {
|
||||||
|
/** Gets the underlying SSA definition (legacy name). */
|
||||||
|
Ssa::Definition getDefinition() { result = this }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a CFG node where this definition is used. Includes regular
|
||||||
|
* `Name` reads as well as the synthetic scope-exit "use" registered
|
||||||
|
* via `SsaImplInput::variableRead` — mirrors legacy ESSA's
|
||||||
|
* `EssaVariable.getAUse()` which inherited the synthetic exit-use
|
||||||
|
* from `SsaSourceVariable`.
|
||||||
|
*/
|
||||||
|
Cfg::ControlFlowNode getAUse() {
|
||||||
|
exists(CfgImpl::BasicBlock bb, int i |
|
||||||
|
Ssa::ssaDefReachesRead(this.getSourceVariable(), this, bb, i) and
|
||||||
|
bb.getNode(i) = result
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Gets the (textual) name of the underlying variable. */
|
||||||
|
string getName() { result = this.getSourceVariable().getVariable().getId() }
|
||||||
|
|
||||||
|
/** Gets the scope in which this variable lives. */
|
||||||
|
Py::Scope getScope() { result = this.getSourceVariable().getVariable().getScope() }
|
||||||
|
|
||||||
|
/** Gets an ultimate non-phi ancestor of this definition. */
|
||||||
|
EssaVariable getAnUltimateDefinition() {
|
||||||
|
if this instanceof PhiNode
|
||||||
|
then
|
||||||
|
exists(Ssa::Definition input |
|
||||||
|
Ssa::phiHasInputFromBlock(this, input, _) and
|
||||||
|
result = input.(EssaVariable).getAnUltimateDefinition()
|
||||||
|
)
|
||||||
|
else result = this
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adjacent use-use and def-use relations exposed by the shared SSA
|
||||||
|
* library. Provides the same interface as legacy
|
||||||
|
* `semmle.python.essa.SsaCompute::AdjacentUses`.
|
||||||
|
*/
|
||||||
|
module AdjacentUses {
|
||||||
|
/** Holds if `nodeFrom` and `nodeTo` are adjacent uses of the same SSA variable. */
|
||||||
|
predicate adjacentUseUse(Cfg::NameNode nodeFrom, Cfg::NameNode nodeTo) {
|
||||||
|
exists(SsaSourceVariable v, CfgImpl::BasicBlock bb1, int i1, CfgImpl::BasicBlock bb2, int i2 |
|
||||||
|
Ssa::adjacentUseUse(bb1, i1, bb2, i2, v, _) and
|
||||||
|
nodeFrom = bb1.getNode(i1) and
|
||||||
|
nodeTo = bb2.getNode(i2)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Holds if `use` is a first use of definition `def`. */
|
||||||
|
predicate firstUse(Ssa::Definition def, Cfg::NameNode use) {
|
||||||
|
exists(CfgImpl::BasicBlock bb, int i |
|
||||||
|
Ssa::firstUse(def, bb, i, _) and
|
||||||
|
use = bb.getNode(i)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Holds if `use` is any reachable use of definition `def`. Combines
|
||||||
|
* `firstUse` with transitive use-use adjacency.
|
||||||
|
*/
|
||||||
|
predicate useOfDef(Ssa::Definition def, Cfg::NameNode use) {
|
||||||
|
firstUse(def, use)
|
||||||
|
or
|
||||||
|
exists(Cfg::NameNode mid | useOfDef(def, mid) and adjacentUseUse(mid, use))
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,4 +1,6 @@
|
|||||||
private import python
|
private import python
|
||||||
|
private import semmle.python.controlflow.internal.Cfg as Cfg
|
||||||
|
private import semmle.python.dataflow.new.internal.SsaImpl as SsaImpl
|
||||||
private import semmle.python.dataflow.new.DataFlow
|
private import semmle.python.dataflow.new.DataFlow
|
||||||
private import semmle.python.dataflow.new.internal.DataFlowPrivate as DataFlowPrivate
|
private import semmle.python.dataflow.new.internal.DataFlowPrivate as DataFlowPrivate
|
||||||
private import FlowSummaryImpl as FlowSummaryImpl
|
private import FlowSummaryImpl as FlowSummaryImpl
|
||||||
@@ -97,7 +99,7 @@ import Cached
|
|||||||
* and isn't a big problem in practice.
|
* and isn't a big problem in practice.
|
||||||
*/
|
*/
|
||||||
predicate concatStep(DataFlow::CfgNode nodeFrom, DataFlow::CfgNode nodeTo) {
|
predicate concatStep(DataFlow::CfgNode nodeFrom, DataFlow::CfgNode nodeTo) {
|
||||||
exists(BinaryExprNode add | add = nodeTo.getNode() |
|
exists(Cfg::BinaryExprNode add | add = nodeTo.getNode() |
|
||||||
add.getOp() instanceof Add and add.getAnOperand() = nodeFrom.getNode()
|
add.getOp() instanceof Add and add.getAnOperand() = nodeFrom.getNode()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -106,7 +108,7 @@ predicate concatStep(DataFlow::CfgNode nodeFrom, DataFlow::CfgNode nodeTo) {
|
|||||||
* Holds if taint can flow from `nodeFrom` to `nodeTo` with a step related to subscripting.
|
* Holds if taint can flow from `nodeFrom` to `nodeTo` with a step related to subscripting.
|
||||||
*/
|
*/
|
||||||
predicate subscriptStep(DataFlow::CfgNode nodeFrom, DataFlow::CfgNode nodeTo) {
|
predicate subscriptStep(DataFlow::CfgNode nodeFrom, DataFlow::CfgNode nodeTo) {
|
||||||
nodeTo.getNode().(SubscriptNode).getObject() = nodeFrom.getNode()
|
nodeTo.getNode().(Cfg::SubscriptNode).getObject() = nodeFrom.getNode()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -122,15 +124,15 @@ predicate stringManipulation(DataFlow::CfgNode nodeFrom, DataFlow::CfgNode nodeT
|
|||||||
(
|
(
|
||||||
call = API::builtin(["str", "bytes", "unicode"]).getACall()
|
call = API::builtin(["str", "bytes", "unicode"]).getACall()
|
||||||
or
|
or
|
||||||
call.getFunction().asCfgNode().(NameNode).getId() in ["str", "bytes", "unicode"]
|
call.getFunction().asCfgNode().(Cfg::NameNode).getId() in ["str", "bytes", "unicode"]
|
||||||
) and
|
) and
|
||||||
nodeFrom in [call.getArg(0), call.getArgByName("object")]
|
nodeFrom in [call.getArg(0), call.getArgByName("object")]
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
// String methods. Note that this doesn't recognize `meth = "foo".upper; meth()`
|
// String methods. Note that this doesn't recognize `meth = "foo".upper; meth()`
|
||||||
exists(CallNode call, string method_name, ControlFlowNode object |
|
exists(Cfg::CallNode call, string method_name, Cfg::ControlFlowNode object |
|
||||||
call = nodeTo.getNode() and
|
call = nodeTo.getNode() and
|
||||||
object = call.getFunction().(AttrNode).getObject(method_name)
|
object = call.getFunction().(Cfg::AttrNode).getObject(method_name)
|
||||||
|
|
|
|
||||||
nodeFrom.getNode() = object and
|
nodeFrom.getNode() = object and
|
||||||
method_name in [
|
method_name in [
|
||||||
@@ -156,7 +158,7 @@ predicate stringManipulation(DataFlow::CfgNode nodeFrom, DataFlow::CfgNode nodeT
|
|||||||
)
|
)
|
||||||
or
|
or
|
||||||
// % formatting
|
// % formatting
|
||||||
exists(BinaryExprNode fmt | fmt = nodeTo.getNode() |
|
exists(Cfg::BinaryExprNode fmt | fmt = nodeTo.getNode() |
|
||||||
fmt.getOp() instanceof Mod and
|
fmt.getOp() instanceof Mod and
|
||||||
(
|
(
|
||||||
fmt.getLeft() = nodeFrom.getNode()
|
fmt.getLeft() = nodeFrom.getNode()
|
||||||
@@ -166,7 +168,7 @@ predicate stringManipulation(DataFlow::CfgNode nodeFrom, DataFlow::CfgNode nodeT
|
|||||||
)
|
)
|
||||||
or
|
or
|
||||||
// string multiplication -- `"foo" * 10`
|
// string multiplication -- `"foo" * 10`
|
||||||
exists(BinaryExprNode mult | mult = nodeTo.getNode() |
|
exists(Cfg::BinaryExprNode mult | mult = nodeTo.getNode() |
|
||||||
mult.getOp() instanceof Mult and
|
mult.getOp() instanceof Mult and
|
||||||
mult.getLeft() = nodeFrom.getNode()
|
mult.getLeft() = nodeFrom.getNode()
|
||||||
)
|
)
|
||||||
@@ -213,8 +215,8 @@ predicate awaitStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
|
|||||||
* the variable `f` is tainted if the result of `open("foo")` is tainted.
|
* the variable `f` is tainted if the result of `open("foo")` is tainted.
|
||||||
*/
|
*/
|
||||||
predicate asyncWithStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
|
predicate asyncWithStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo) {
|
||||||
exists(With with, ControlFlowNode contextManager, ControlFlowNode var |
|
exists(With with, Cfg::ControlFlowNode contextManager, Cfg::ControlFlowNode var |
|
||||||
var = any(WithDefinition wd).getDefiningNode()
|
var = any(SsaImpl::WithDefinition wd).getDefiningNode()
|
||||||
|
|
|
|
||||||
nodeFrom.(DataFlow::CfgNode).getNode() = contextManager and
|
nodeFrom.(DataFlow::CfgNode).getNode() = contextManager and
|
||||||
nodeTo.(DataFlow::CfgNode).getNode() = var and
|
nodeTo.(DataFlow::CfgNode).getNode() = var and
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ import codeql.util.Unit
|
|||||||
import codeql.typetracking.TypeTracking as Shared
|
import codeql.typetracking.TypeTracking as Shared
|
||||||
import codeql.typetracking.internal.TypeTrackingImpl as SharedImpl
|
import codeql.typetracking.internal.TypeTrackingImpl as SharedImpl
|
||||||
private import python
|
private import python
|
||||||
|
private import semmle.python.controlflow.internal.Cfg as Cfg
|
||||||
|
private import semmle.python.dataflow.new.internal.SsaImpl as SsaImpl
|
||||||
private import semmle.python.internal.CachedStages
|
private import semmle.python.internal.CachedStages
|
||||||
private import semmle.python.dataflow.new.internal.DataFlowPublic as DataFlowPublic
|
private import semmle.python.dataflow.new.internal.DataFlowPublic as DataFlowPublic
|
||||||
private import semmle.python.dataflow.new.internal.DataFlowPrivate as DataFlowPrivate
|
private import semmle.python.dataflow.new.internal.DataFlowPrivate as DataFlowPrivate
|
||||||
@@ -162,7 +164,7 @@ module TypeTrackingInput implements Shared::TypeTrackingInput<Location> {
|
|||||||
// ignore the flow steps from the synthetic sequence node to the real sequence node,
|
// ignore the flow steps from the synthetic sequence node to the real sequence node,
|
||||||
// since we only support one level of content in type-trackers, and the nested
|
// since we only support one level of content in type-trackers, and the nested
|
||||||
// structure requires two levels at least to be useful.
|
// structure requires two levels at least to be useful.
|
||||||
not exists(SequenceNode outer |
|
not exists(Cfg::SequenceNode outer |
|
||||||
outer.getAnElement() = nodeTo.asCfgNode() and
|
outer.getAnElement() = nodeTo.asCfgNode() and
|
||||||
IterableUnpacking::iterableUnpackingTupleFlowStep(nodeFrom, nodeTo)
|
IterableUnpacking::iterableUnpackingTupleFlowStep(nodeFrom, nodeTo)
|
||||||
)
|
)
|
||||||
@@ -267,7 +269,7 @@ module TypeTrackingInput implements Shared::TypeTrackingInput<Location> {
|
|||||||
// Since we only support one level of content in type-trackers we don't actually
|
// Since we only support one level of content in type-trackers we don't actually
|
||||||
// support `(aa, ab), (ba, bb) = ...`. Therefore we exclude the read-step from `(aa,
|
// support `(aa, ab), (ba, bb) = ...`. Therefore we exclude the read-step from `(aa,
|
||||||
// ab)` to `aa` (since it is not needed).
|
// ab)` to `aa` (since it is not needed).
|
||||||
not exists(SequenceNode outer |
|
not exists(Cfg::SequenceNode outer |
|
||||||
outer.getAnElement() = nodeFrom.asCfgNode() and
|
outer.getAnElement() = nodeFrom.asCfgNode() and
|
||||||
IterableUnpacking::iterableUnpackingTupleFlowStep(_, nodeFrom)
|
IterableUnpacking::iterableUnpackingTupleFlowStep(_, nodeFrom)
|
||||||
) and
|
) and
|
||||||
@@ -277,7 +279,7 @@ module TypeTrackingInput implements Shared::TypeTrackingInput<Location> {
|
|||||||
IterableUnpacking::iterableUnpackingForReadStep(_, _, seq) and
|
IterableUnpacking::iterableUnpackingForReadStep(_, _, seq) and
|
||||||
IterableUnpacking::iterableUnpackingConvertingReadStep(seq, _, elem) and
|
IterableUnpacking::iterableUnpackingConvertingReadStep(seq, _, elem) and
|
||||||
IterableUnpacking::iterableUnpackingConvertingStoreStep(elem, _, nodeFrom) and
|
IterableUnpacking::iterableUnpackingConvertingStoreStep(elem, _, nodeFrom) and
|
||||||
nodeFrom.asCfgNode() instanceof SequenceNode
|
nodeFrom.asCfgNode() instanceof Cfg::SequenceNode
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
TypeTrackerSummaryFlow::basicLoadStep(nodeFrom, nodeTo, DataFlowPublic::singleton(content))
|
TypeTrackerSummaryFlow::basicLoadStep(nodeFrom, nodeTo, DataFlowPublic::singleton(content))
|
||||||
@@ -315,13 +317,15 @@ module TypeTrackingInput implements Shared::TypeTrackingInput<Location> {
|
|||||||
//
|
//
|
||||||
// nodeFrom is `expr`
|
// nodeFrom is `expr`
|
||||||
// nodeTo is entry node for `f`
|
// nodeTo is entry node for `f`
|
||||||
exists(ScopeEntryDefinition e, SsaSourceVariable var, DefinitionNode def |
|
exists(
|
||||||
|
SsaImpl::ScopeEntryDefinition e, SsaImpl::SsaSourceVariable var, Cfg::DefinitionNode def
|
||||||
|
|
|
||||||
e.getSourceVariable() = var and
|
e.getSourceVariable() = var and
|
||||||
var.hasDefiningNode(def)
|
def.getNode() = var.getVariable().getAStore()
|
||||||
|
|
|
|
||||||
nodeTo.(DataFlowPublic::ScopeEntryDefinitionNode).getDefinition() = e and
|
nodeTo.(DataFlowPublic::ScopeEntryDefinitionNode).getDefinition() = e and
|
||||||
nodeFrom.asCfgNode() = def and
|
nodeFrom.asCfgNode() = def and
|
||||||
var.getScope().getScope*() = nodeFrom.getScope()
|
var.getVariable().getScope().getScope*() = nodeFrom.getScope()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user