From c5593d5519459dcd2c58f335c2c7be8db26a4a3c Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Tue, 20 Oct 2026 17:13:23 +0100 Subject: [PATCH 1/9] Add shared Go SSA module Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- go/ql/lib/semmle/go/dataflow/SsaImpl.qll | 28 ++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/go/ql/lib/semmle/go/dataflow/SsaImpl.qll b/go/ql/lib/semmle/go/dataflow/SsaImpl.qll index c206dccbba38..e5fb68b00ea1 100644 --- a/go/ql/lib/semmle/go/dataflow/SsaImpl.qll +++ b/go/ql/lib/semmle/go/dataflow/SsaImpl.qll @@ -129,6 +129,34 @@ private module Internal { import Internal import SsaImplCommon::Make as Impl +private module PublicSsaInput implements Impl::SsaInputSig { + private import go as G + + class Expr = G::Expr; + + class Parameter = G::Parameter; + + class VariableWrite extends IR::WriteInstruction { + Expr asExpr() { none() } + + Expr getValue() { result = this.getRhs().(IR::EvalInstruction).getExpr() } + + predicate isParameterInit(Parameter p) { this = IR::initParamInstruction(p) } + } + + predicate explicitWrite(VariableWrite w, BasicBlock bb, int i, SsaSourceVariable v) { + w = bb.getNode(i) and + defAt(bb, i, v) + } +} + +module Ssa = Impl::MakeSsa; + +/** Gets the control-flow root containing `def`. */ +ControlFlow::Root getSsaDefinitionRoot(Ssa::SsaDefinition def) { + result = def.getBasicBlock().getScope() +} + final class Definition = Impl::Definition; final class WriteDefinition = Impl::WriteDefinition; From 56a1bc5eeda5014f5542a25a537ebe001766ca9f Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Tue, 20 Oct 2026 17:14:22 +0100 Subject: [PATCH 2/9] Migrate Go to shared SSA classes Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../go/controlflow/ControlFlowGraph.qll | 6 +- go/ql/lib/semmle/go/controlflow/Guards.qll | 42 +---- go/ql/lib/semmle/go/controlflow/IR.qll | 6 +- .../go/dataflow/GlobalValueNumbering.qll | 6 +- go/ql/lib/semmle/go/dataflow/SSA.qll | 152 +++++++----------- .../go/dataflow/internal/DataFlowNodes.qll | 35 ++-- .../go/dataflow/internal/DataFlowPrivate.qll | 27 ++-- .../go/dataflow/internal/DataFlowUtil.qll | 4 +- go/ql/lib/semmle/go/frameworks/Beego.qll | 2 +- go/ql/lib/semmle/go/frameworks/Fasthttp.qll | 2 +- go/ql/lib/semmle/go/frameworks/GinCors.qll | 8 +- go/ql/lib/semmle/go/frameworks/Macaron.qll | 2 +- go/ql/lib/semmle/go/frameworks/RsCors.qll | 8 +- .../semmle/go/frameworks/stdlib/NetHttp.qll | 2 +- .../src/InconsistentCode/MissingErrorCheck.ql | 2 +- .../InconsistentCode/WrappedErrorAlwaysNil.ql | 6 +- go/ql/src/RedundantCode/DeadStoreOfField.ql | 2 +- go/ql/src/RedundantCode/DeadStoreOfLocal.ql | 6 +- .../IntegerOverflow/RangeAnalysis.qll | 103 ++++++------ .../semmle/go/dataflow/SSA/DefUse.expected | 22 ++- .../semmle/go/dataflow/SSA/DefUse.ql | 4 +- .../go/dataflow/SSA/SsaDefinition.expected | 18 +-- .../go/dataflow/SSA/SsaWithFields.expected | 24 +-- 23 files changed, 219 insertions(+), 270 deletions(-) diff --git a/go/ql/lib/semmle/go/controlflow/ControlFlowGraph.qll b/go/ql/lib/semmle/go/controlflow/ControlFlowGraph.qll index 80287d7c02b9..a92759a62b23 100644 --- a/go/ql/lib/semmle/go/controlflow/ControlFlowGraph.qll +++ b/go/ql/lib/semmle/go/controlflow/ControlFlowGraph.qll @@ -140,9 +140,9 @@ module ControlFlow { /** Holds if this node sets variable or constant `v` to `rhs`. */ predicate writes(ValueEntity v, DataFlow::Node rhs) { super.writes(v, rhs.asInstruction()) } - /** Holds if this node defines SSA variable `v` to be `rhs`. */ - predicate definesSsaVariable(SsaVariable v, DataFlow::Node rhs) { - super.getLhs().asSsaVariable() = v and + /** Holds if this node defines SSA definition `def` to be `rhs`. */ + predicate definesSsaDefinition(SsaDefinition def, DataFlow::Node rhs) { + super.getLhs().asSsaDefinition() = def and super.getRhs() = rhs.asInstruction() } diff --git a/go/ql/lib/semmle/go/controlflow/Guards.qll b/go/ql/lib/semmle/go/controlflow/Guards.qll index 5f22dd22a9e3..7f84f525ce36 100644 --- a/go/ql/lib/semmle/go/controlflow/Guards.qll +++ b/go/ql/lib/semmle/go/controlflow/Guards.qll @@ -320,9 +320,9 @@ private module GuardsInput implements } private predicate extractedCallResult(Expr use, G::CallExpr call, int resultIndex) { - exists(GoSsa::SsaDefinition def, IR::ExtractTupleElementInstruction extract | - use = def.getVariable().getAUse().(IR::EvalInstruction).getExpr() and - def.(GoSsa::SsaExplicitDefinition).getInstruction() = extract and + exists(GoSsa::Ssa::SsaDefinition def, IR::ExtractTupleElementInstruction extract | + use = def.getARead() and + def.(GoSsa::Ssa::SsaExplicitWrite).getDefinition() = extract and extract.extractsElement(IR::evalExprInstruction(call), resultIndex) ) } @@ -398,46 +398,20 @@ private module GuardsInput implements private module GuardsImpl = SharedGuards::Make; private module LogicInput implements GuardsImpl::LogicInputSig { - final private class FinalSsaDefinition = GoSsa::SsaDefinition; - - class SsaDefinition extends FinalSsaDefinition { - GuardsInput::Expr getARead() { - result = super.getVariable().getAUse().(IR::EvalInstruction).getExpr() - } - } - - class SsaExplicitWrite extends SsaDefinition instanceof GoSsa::SsaExplicitDefinition { - GuardsInput::Expr getValue() { result = super.getRhs().(IR::EvalInstruction).getExpr() } - } - - class SsaPhiDefinition extends SsaDefinition instanceof GoSsa::SsaPhiNode { - /** Holds if `inp` is an input to the phi node along the edge originating in `bb`. */ - predicate hasInputFromBlock(SsaDefinition inp, BasicBlock bb) { - SsaImpl::phiHasInputFromBlock(this, inp, bb) - } - } - - class SsaParameterInit extends SsaDefinition { - SsaParameterInit() { - this.(GoSsa::SsaExplicitDefinition).getInstruction() instanceof IR::InitParameterInstruction - } - - GuardsInput::Parameter getParameter() { - this.(GoSsa::SsaExplicitDefinition).getInstruction() = IR::initParamInstruction(result) - } - } + import GoSsa::Ssa predicate implicitReturnDefinition(GuardsInput::NonOverridableMethod method, SsaDefinition def) { - exists(IR::ReadResultInstruction read | + exists(IR::ReadResultInstruction read, BasicBlock bb, int i | method.getResultIndex() >= 0 and read.reads(method.getFunction().getResult(method.getResultIndex())) and - def.getVariable().getAUse() = read + read = bb.getNode(i) and + SsaImpl::ssaDefReachesRead(def.getSourceVariable(), def, bb, i) ) } predicate additionalSsaDefinitionValue(SsaDefinition def, GuardValue value) { exists(IR::EvalImplicitInitInstruction init | - def.(GoSsa::SsaExplicitDefinition).getInstruction() = init and + def.(SsaExplicitWrite).getDefinition() = init and value.asBooleanValue() = init.getBoolValue() ) } diff --git a/go/ql/lib/semmle/go/controlflow/IR.qll b/go/ql/lib/semmle/go/controlflow/IR.qll index aded50ecc80c..9afef72e5df5 100644 --- a/go/ql/lib/semmle/go/controlflow/IR.qll +++ b/go/ql/lib/semmle/go/controlflow/IR.qll @@ -1127,10 +1127,8 @@ module IR { /** Gets the name of the variable or field being written to, if any. */ string getName() { none() } - /** Gets the SSA variable being written to, if any. */ - SsaVariable asSsaVariable() { - this.getWrite() = result.getDefinition().(SsaExplicitDefinition).getInstruction() - } + /** Gets the SSA definition being written to, if any. */ + SsaDefinition asSsaDefinition() { this.getWrite() = result.(SsaExplicitWrite).getDefinition() } /** Holds if `e` is the variable or field being written to. */ predicate refersTo(ValueEntity e) { none() } diff --git a/go/ql/lib/semmle/go/dataflow/GlobalValueNumbering.qll b/go/ql/lib/semmle/go/dataflow/GlobalValueNumbering.qll index 38c5ff4de219..6217aacae28b 100644 --- a/go/ql/lib/semmle/go/dataflow/GlobalValueNumbering.qll +++ b/go/ql/lib/semmle/go/dataflow/GlobalValueNumbering.qll @@ -67,7 +67,7 @@ private ControlFlow::Node nodeWithPossibleSideEffect() { // If the lhs of an assignment is not analyzable by SSA, then // we need to treat the assignment as having a possible side-effect. result instanceof Write and - not exists(SsaExplicitDefinition ssa | result = ssa.getInstruction()) + not exists(SsaExplicitWrite ssa | result = ssa.getDefinition()) } private predicate isPureFn(Function f) { @@ -527,8 +527,8 @@ private predicate mkDeref(DataFlow::PointerDereferenceNode deref, GVN p, Control p = globalValueNumber(deref.getOperand()) } -private predicate ssaInit(SsaExplicitDefinition ssa, DataFlow::Node rhs) { - ssa.getRhs() = rhs.asInstruction() +private predicate ssaInit(SsaExplicitWrite ssa, DataFlow::Node rhs) { + ssa.getDefinition().getRhs() = rhs.asInstruction() } /** Gets the global value number of data-flow node `nd`. */ diff --git a/go/ql/lib/semmle/go/dataflow/SSA.qll b/go/ql/lib/semmle/go/dataflow/SSA.qll index 0b8895f43a06..80c5e8b0fef6 100644 --- a/go/ql/lib/semmle/go/dataflow/SSA.qll +++ b/go/ql/lib/semmle/go/dataflow/SSA.qll @@ -6,6 +6,8 @@ module; import go private import SsaImpl +import SsaImpl::Ssa as Ssa +import Ssa /** * A variable that can be SSA converted, that is, a local variable, but not a variable @@ -61,10 +63,12 @@ private predicate unresolvedIdentifier(Ident id, string name) { } /** + * DEPRECATED: Use `SsaDefinition` instead. + * * An SSA variable. */ -class SsaVariable extends Definition { - /** Gets the (unique) definition of this SSA variable. */ +deprecated class SsaVariable extends SsaDefinition { + /** Gets the unique definition of this SSA variable. */ SsaDefinition getDefinition() { result = this } /** Gets the type of this SSA variable. */ @@ -79,146 +83,114 @@ class SsaVariable extends Definition { ) } - /** Gets a use that refers to this SSA variable. */ - IR::Instruction getAUse() { result = this.getAUseIn(_) } - /** - * DEPRECATED: Use `getLocation()` instead. + * DEPRECATED: Use `getARead()` instead. * - * Holds if this element is at the specified location. - * The location spans column `startcolumn` of line `startline` to - * column `endcolumn` of line `endline` in file `filepath`. - * For more information, see - * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). + * Gets a use that refers to this SSA variable. */ - deprecated predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - this.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) - } -} - -/** - * An SSA definition. - */ -class SsaDefinition extends Definition { - /** Gets the SSA variable defined by this definition. */ - SsaVariable getVariable() { result = this } + deprecated IR::Instruction getAUse() { result = this.getAUseIn(_) } - /** Gets the innermost function or file to which this SSA definition belongs. */ + /** Gets the innermost function or file to which this SSA variable belongs. */ ControlFlow::Root getRoot() { result = this.getBasicBlock().getScope() } + /** + * Gets the first instruction that the value of this SSA variable can reach without passing + * through any other instructions, but possibly through phi nodes. + */ + IR::Instruction getAFirstUse() { firstUse(this, result) } + /** * INTERNAL: Do not use. * - * Gets a short string identifying the kind of this SSA definition, - * used in reference formatting (e.g., `"def"`, `"capture"`, `"phi"`). + * Gets a short string identifying the kind of this SSA variable. */ - string getKind() { none() } + string getKind() { + this instanceof SsaExplicitWrite and result = "def" + or + this instanceof SsaUncertainWrite and result = "capture" + or + this instanceof SsaPhiDefinition and result = "phi" + } /** * DEPRECATED: Use `getLocation()` instead. * * Holds if this element is at the specified location. - * The location spans column `startcolumn` of line `startline` to - * column `endcolumn` of line `endline` in file `filepath`. - * For more information, see - * [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/). */ deprecated predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn ) { this.getLocation().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) } - - /** - * Gets the first instruction that the value of this `SsaDefinition` can - * reach without passing through any other instructions, but possibly through - * phi nodes. - */ - IR::Instruction getAFirstUse() { firstUse(this, result) } } /** + * DEPRECATED: Use `SsaExplicitWrite` instead. + * * An SSA definition that corresponds to an explicit assignment or other variable definition. */ -class SsaExplicitDefinition extends SsaDefinition, WriteDefinition { - SsaExplicitDefinition() { - exists(BasicBlock bb, int i, SsaSourceVariable v | - this.definesAt(v, bb, i) and - defAt(bb, i, v) - ) - } - +deprecated class SsaExplicitDefinition extends SsaVariable instanceof SsaExplicitWrite { /** Gets the instruction where the definition happens. */ - IR::Instruction getInstruction() { - exists(BasicBlock bb, int i | this.definesAt(_, bb, i) | result = bb.getNode(i)) - } + IR::Instruction getInstruction() { result = this.(SsaExplicitWrite).getDefinition() } /** Gets the right-hand side of the definition. */ - IR::Instruction getRhs() { this.getInstruction().writes(_, result) } - - override string getKind() { result = "def" } + IR::Instruction getRhs() { result = this.getInstruction().(IR::WriteInstruction).getRhs() } } -/** Provides a helper predicate for working with explicit SSA definitions. */ -module SsaExplicitDefinition { - /** - * Gets the SSA definition corresponding to definition `def`. - */ +/** Provides a deprecated helper for working with explicit SSA definitions. */ +deprecated module SsaExplicitDefinition { + /** Gets the SSA definition corresponding to definition `def`. */ SsaExplicitDefinition of(IR::Instruction def) { result.getInstruction() = def } } /** + * DEPRECATED: Use `SsaUncertainWrite` or `SsaPhiDefinition` instead. + * * An SSA definition that does not correspond to an explicit variable definition. */ -abstract class SsaImplicitDefinition extends SsaDefinition { } +deprecated class SsaImplicitDefinition extends SsaVariable { + SsaImplicitDefinition() { this instanceof SsaUncertainWrite or this instanceof SsaPhiDefinition } +} /** - * An SSA definition representing the capturing of an SSA-convertible variable - * in the closure of a nested function. + * DEPRECATED: Use `SsaUncertainWrite` instead. * - * Capturing definitions appear at the beginning of such functions, as well as - * at any function call that may affect the value of the variable. + * An SSA definition representing the capturing of an SSA-convertible variable. */ -class SsaVariableCapture extends SsaImplicitDefinition, UncertainWriteDefinition { - override string getKind() { result = "capture" } -} +deprecated class SsaVariableCapture extends SsaImplicitDefinition instanceof SsaUncertainWrite { } /** - * An SSA definition such as a phi node that has no actual semantics, but simply serves to - * merge or filter data flow. + * DEPRECATED: Use `SsaPhiDefinition` instead. + * + * An SSA definition that merges data flow. */ -abstract class SsaPseudoDefinition extends SsaImplicitDefinition { - /** - * Gets an input of this pseudo-definition. - */ - abstract SsaVariable getAnInput(); +deprecated class SsaPseudoDefinition extends SsaImplicitDefinition instanceof SsaPhiDefinition { + /** Gets an input of this pseudo-definition. */ + SsaVariable getAnInput() { result = this.(SsaPhiDefinition).getAnInput() } } /** - * An SSA phi node, that is, a pseudo-definition for a variable at a point - * in the flow graph where otherwise two or more definitions for the variable - * would be visible. + * DEPRECATED: Use `SsaPhiDefinition` instead. + * + * An SSA phi definition. */ -class SsaPhiNode extends SsaPseudoDefinition, PhiNode { - override SsaVariable getAnInput() { phiHasInputFromBlock(this, result, _) } - - override string getKind() { result = "phi" } -} +deprecated class SsaPhiNode extends SsaPseudoDefinition { } /** * An SSA variable, possibly with a chain of field reads on it. */ private newtype TSsaWithFields = - TRoot(SsaVariable v) or + TRoot(SsaDefinition def) or TStep(SsaWithFields base, Field f) { exists(accessPathAux(base, f)) } /** * Gets a representation of `insn` as an ssa-with-fields value if there is one. */ private TSsaWithFields accessPath(IR::Instruction insn) { - exists(SsaVariable v | insn = v.getAUse() | result = TRoot(v)) + exists(SsaDefinition def | + insn.(IR::EvalInstruction).getExpr() = def.getARead() and + result = TRoot(def) + ) or exists(SsaWithFields base, Field f | insn = accessPathAux(base, f) | result = TStep(base, f)) } @@ -246,10 +218,10 @@ class SsaWithFields extends TSsaWithFields { * For example, the SSA variable corresponding to `a` for the SSA variable with fields * corresponding to `a.b`. */ - SsaVariable getBaseVariable() { + SsaDefinition getBaseDefinition() { this = TRoot(result) or - exists(SsaWithFields base | this = TStep(base, _) | result = base.getBaseVariable()) + exists(SsaWithFields base | this = TStep(base, _) | result = base.getBaseDefinition()) } /** Gets a use that refers to this SSA variable with fields. */ @@ -257,14 +229,14 @@ class SsaWithFields extends TSsaWithFields { /** Gets the type of this SSA variable with fields. */ Type getType() { - exists(SsaVariable var | this = TRoot(var) | result = var.getType()) + exists(SsaDefinition def | this = TRoot(def) | result = def.getSourceVariable().getType()) or exists(Field f | this = TStep(_, f) | result = f.getType()) } /** Gets a textual representation of this element. */ string toString() { - exists(SsaVariable var | this = TRoot(var) | result = "(" + var + ")") + exists(SsaDefinition def | this = TRoot(def) | result = "(" + def + ")") or exists(SsaWithFields base, Field f | this = TStep(base, f) | result = base + "." + f.getName()) } @@ -274,7 +246,7 @@ class SsaWithFields extends TSsaWithFields { * sense that it has the same root variable and the same sequence of field accesses. */ SsaWithFields similar() { - result.getBaseVariable().getSourceVariable() = this.getBaseVariable().getSourceVariable() and + result.getBaseDefinition().getSourceVariable() = this.getBaseDefinition().getSourceVariable() and result.getQualifiedName() = this.getQualifiedName() } @@ -285,7 +257,7 @@ class SsaWithFields extends TSsaWithFields { * `"a.b"`. */ string getQualifiedName() { - exists(SsaVariable v | this = TRoot(v) and result = v.getSourceVariable().getName()) + exists(SsaDefinition def | this = TRoot(def) and result = def.getSourceVariable().getName()) or exists(SsaWithFields base, Field f | this = TStep(base, f) | result = base.getQualifiedName() + "." + f.getName() @@ -293,7 +265,7 @@ class SsaWithFields extends TSsaWithFields { } /** Gets the location of this SSA variable with fields. */ - Location getLocation() { result = this.getBaseVariable().getLocation() } + Location getLocation() { result = this.getBaseDefinition().getLocation() } /** * DEPRECATED: Use `getLocation()` instead. diff --git a/go/ql/lib/semmle/go/dataflow/internal/DataFlowNodes.qll b/go/ql/lib/semmle/go/dataflow/internal/DataFlowNodes.qll index 1aa60c0eca46..be6ece3e411b 100644 --- a/go/ql/lib/semmle/go/dataflow/internal/DataFlowNodes.qll +++ b/go/ql/lib/semmle/go/dataflow/internal/DataFlowNodes.qll @@ -4,6 +4,7 @@ module; private import go private import semmle.go.dataflow.FunctionInputsAndOutputs private import semmle.go.dataflow.FlowSummary +private import semmle.go.dataflow.SsaImpl as SsaImpl private import DataFlowPrivate private import FlowSummaryImpl as FlowSummaryImpl private import semmle.go.dataflow.ExternalFlow @@ -286,19 +287,27 @@ module Public { SsaNode() { this = MkSsaNode(ssa) } - /** Gets the node whose value is stored in this SSA variable, if any. */ - Node getInit() { result = DataFlow::instructionNode(ssa.(SsaExplicitDefinition).getRhs()) } + /** Gets the node whose value is stored in this SSA definition, if any. */ + Node getInit() { + result = DataFlow::instructionNode(ssa.(SsaExplicitWrite).getDefinition().getRhs()) + } - /** Gets a use of this SSA variable. */ - InstructionNode getAUse() { result = DataFlow::instructionNode(ssa.getVariable().getAUse()) } + /** Gets a use of this SSA definition. */ + InstructionNode getAUse() { + exists(BasicBlock bb, int i | + result.asInstruction() = bb.getNode(i) and + SsaImpl::ssaDefReachesRead(ssa.getSourceVariable(), ssa, bb, i) and + SsaImpl::useAt(bb, i, ssa.getSourceVariable()) + ) + } - /** Gets the program variable corresponding to this SSA variable. */ + /** Gets the program variable corresponding to this SSA definition. */ SsaSourceVariable getSourceVariable() { result = ssa.getSourceVariable() } - /** Gets the unique definition of this SSA variable. */ + /** Gets this SSA definition. */ SsaDefinition getDefinition() { result = ssa } - override ControlFlow::Root getRoot() { result = ssa.getRoot() } + override ControlFlow::Root getRoot() { result = SsaImpl::getSsaDefinitionRoot(ssa) } override Type getType() { result = ssa.getSourceVariable().getType() } @@ -732,7 +741,7 @@ module Public { UnusedParameterNode() { insn = IR::initParamInstruction(parm) and - not exists(SsaExplicitDefinition ssa | ssa.getInstruction() = insn) + not exists(SsaExplicitWrite ssa | ssa.getDefinition() = insn) } /** Gets the parameter this node initializes. */ @@ -745,10 +754,10 @@ module Public { /** A representation of a parameter initialization, defined in source via an SSA node. */ class SsaParameterNode extends ParameterNode, SsaNode { - override SsaExplicitDefinition ssa; + override SsaParameterInit ssa; Parameter parm; - SsaParameterNode() { ssa.getInstruction() = IR::initParamInstruction(parm) } + SsaParameterNode() { ssa.getParameter() = parm } /** Gets the parameter this node initializes. */ override Parameter asParameter() { result = parm } @@ -976,9 +985,11 @@ module Public { predicate reads(ValueEntity v) { insn.reads(v) } /** - * Holds if this data-flow node reads the value of SSA variable `v`. + * Holds if this data-flow node reads the value of SSA definition `def`. */ - predicate readsSsaVariable(SsaVariable v) { insn = v.getAUse() } + predicate readsSsaDefinition(SsaDefinition def) { + insn.(IR::EvalInstruction).getExpr() = def.getARead() + } /** * Holds if this data-flow node reads the value of field `f` on the value of `base` or its diff --git a/go/ql/lib/semmle/go/dataflow/internal/DataFlowPrivate.qll b/go/ql/lib/semmle/go/dataflow/internal/DataFlowPrivate.qll index 056d8edd5d9f..fbbbe0172a9a 100644 --- a/go/ql/lib/semmle/go/dataflow/internal/DataFlowPrivate.qll +++ b/go/ql/lib/semmle/go/dataflow/internal/DataFlowPrivate.qll @@ -2,6 +2,7 @@ overlay[local?] module; private import go +private import semmle.go.dataflow.SsaImpl as SsaImpl private import semmle.go.controlflow.Guards private import DataFlowUtil private import DataFlowImplCommon @@ -70,19 +71,19 @@ predicate basicLocalFlowStep(Node nodeFrom, Node nodeTo) { ) or // Instruction -> SSA defn - exists(IR::Instruction pred, SsaExplicitDefinition succ | - succ.getRhs() = pred and + exists(IR::Instruction pred, SsaExplicitWrite succ | + succ.getDefinition().getRhs() = pred and ( nodeFrom = instructionNode(pred) or nodeFrom.(PostUpdateNode).getPreUpdateNode() = instructionNode(pred) ) and - nodeTo = ssaNode(succ.getVariable()) + nodeTo = ssaNode(succ) ) or // SSA defn -> first SSA use - exists(SsaDefinition pred, IR::Instruction succ | succ = pred.getAFirstUse() | - (pred instanceof SsaExplicitDefinition or pred instanceof SsaVariableCapture) and - nodeFrom = ssaNode(pred.getVariable()) and + exists(SsaDefinition pred, IR::Instruction succ | SsaImpl::firstUse(pred, succ) | + (pred instanceof SsaExplicitWrite or pred instanceof SsaUncertainWrite) and + nodeFrom = ssaNode(pred) and nodeTo = instructionNode(succ) ) or @@ -125,14 +126,16 @@ predicate jumpStep(Node n1, Node n2) { isValueEntityRead(v, n2) ) or - exists(SsaExplicitDefinition def, SsaVariableCapture succ | + exists(SsaExplicitWrite def, SsaUncertainWrite succ | succ.getSourceVariable() = def.getSourceVariable() and n2 = ssaNode(succ) | - not exists(def.getAFirstUse()) and n1 = ssaNode(def) + not SsaImpl::firstUse(def, _) and n1 = ssaNode(def) or exists(IR::Instruction lastUse | - lastUse = getAnAdjacentUse*(def.getAFirstUse()) and + exists(IR::Instruction firstUse | + SsaImpl::firstUse(def, firstUse) and lastUse = getAnAdjacentUse*(firstUse) + ) and not exists(getAnAdjacentUse(lastUse)) | n1 = instructionNode(lastUse) or @@ -375,9 +378,9 @@ class DataFlowCall extends Expr { private predicate constantBooleanExpr(Expr e, boolean val) { e.getBoolValue() = val or - exists(SsaExplicitDefinition v, Expr src | - IR::evalExprInstruction(e) = v.getVariable().getAUse() and - IR::evalExprInstruction(src) = v.getRhs() and + exists(SsaExplicitWrite def, Expr src | + e = def.getARead() and + IR::evalExprInstruction(src) = def.getDefinition().getRhs() and constantBooleanExpr(src, val) ) } diff --git a/go/ql/lib/semmle/go/dataflow/internal/DataFlowUtil.qll b/go/ql/lib/semmle/go/dataflow/internal/DataFlowUtil.qll index 62da08733110..c450244480ca 100644 --- a/go/ql/lib/semmle/go/dataflow/internal/DataFlowUtil.qll +++ b/go/ql/lib/semmle/go/dataflow/internal/DataFlowUtil.qll @@ -87,9 +87,9 @@ ParameterNode parameterNode(Parameter p) { result.asParameter() = p } ReceiverNode receiverNode(ReceiverVariable r) { result.asReceiverVariable() = r } /** - * Gets the data-flow node corresponding to SSA variable `v`. + * Gets the data-flow node corresponding to SSA definition `def`. */ -SsaNode ssaNode(SsaVariable v) { result.getDefinition() = v.getDefinition() } +SsaNode ssaNode(SsaDefinition def) { result.getDefinition() = def } /** * Gets the data-flow node corresponding to the `i`th element of tuple `t` (which is either a call diff --git a/go/ql/lib/semmle/go/frameworks/Beego.qll b/go/ql/lib/semmle/go/frameworks/Beego.qll index 5f3f2e986c28..8beab8a04cc3 100644 --- a/go/ql/lib/semmle/go/frameworks/Beego.qll +++ b/go/ql/lib/semmle/go/frameworks/Beego.qll @@ -55,7 +55,7 @@ module Beego { SsaWithFields v; BeegoOutputInstance() { - this = v.getBaseVariable().getSourceVariable() and + this = v.getBaseDefinition().getSourceVariable() and v.getType().(PointerType).getBaseType().hasQualifiedName(contextPackagePath(), "BeegoOutput") } diff --git a/go/ql/lib/semmle/go/frameworks/Fasthttp.qll b/go/ql/lib/semmle/go/frameworks/Fasthttp.qll index 2dea987ade61..75835d6a643a 100644 --- a/go/ql/lib/semmle/go/frameworks/Fasthttp.qll +++ b/go/ql/lib/semmle/go/frameworks/Fasthttp.qll @@ -63,7 +63,7 @@ module Fasthttp { SsaWithFields v; ResponseWriter() { - this = v.getBaseVariable().getSourceVariable() and + this = v.getBaseDefinition().getSourceVariable() and ( v.getType().hasQualifiedName(packagePath(), ["Response", "ResponseHeader"]) or v.getType().(PointerType).getBaseType().hasQualifiedName(packagePath(), "RequestCtx") diff --git a/go/ql/lib/semmle/go/frameworks/GinCors.qll b/go/ql/lib/semmle/go/frameworks/GinCors.qll index cd742ac9ba26..b63f9dc97879 100644 --- a/go/ql/lib/semmle/go/frameworks/GinCors.qll +++ b/go/ql/lib/semmle/go/frameworks/GinCors.qll @@ -45,7 +45,7 @@ module GinCors { override GinConfig getConfig() { exists(GinConfig gc | ( - gc.getV().getBaseVariable().getDefinition().(SsaExplicitDefinition).getRhs() = + gc.getV().getBaseDefinition().(SsaExplicitWrite).getDefinition().getRhs() = base.asInstruction() or gc.getV().getAUse() = base ) and @@ -79,7 +79,7 @@ module GinCors { override GinConfig getConfig() { exists(GinConfig gc | ( - gc.getV().getBaseVariable().getDefinition().(SsaExplicitDefinition).getRhs() = + gc.getV().getBaseDefinition().(SsaExplicitWrite).getDefinition().getRhs() = base.asInstruction() or gc.getV().getAUse() = base ) and @@ -111,7 +111,7 @@ module GinCors { * Get config variable holding header values */ override GinConfig getConfig() { - result.getV().getBaseVariable().getDefinition().(SsaExplicitDefinition).getRhs() = + result.getV().getBaseDefinition().(SsaExplicitWrite).getDefinition().getRhs() = base.asInstruction() or result.getV().getAUse() = base } @@ -124,7 +124,7 @@ module GinCors { SsaWithFields v; GinConfig() { - this = v.getBaseVariable().getSourceVariable() and + this = v.getBaseDefinition().getSourceVariable() and v.getType().hasQualifiedName(packagePath(), "Config") } diff --git a/go/ql/lib/semmle/go/frameworks/Macaron.qll b/go/ql/lib/semmle/go/frameworks/Macaron.qll index 1c0888042632..88cdca306d88 100644 --- a/go/ql/lib/semmle/go/frameworks/Macaron.qll +++ b/go/ql/lib/semmle/go/frameworks/Macaron.qll @@ -11,7 +11,7 @@ private module Macaron { SsaWithFields v; Context() { - this = v.getBaseVariable().getSourceVariable() and + this = v.getBaseDefinition().getSourceVariable() and exists(Method m | m.hasQualifiedName("gopkg.in/macaron.v1", "Context", "Redirect") | v.getType().getMethod("Redirect") = m ) diff --git a/go/ql/lib/semmle/go/frameworks/RsCors.qll b/go/ql/lib/semmle/go/frameworks/RsCors.qll index 7609b27b58a5..80d79fb2fd21 100644 --- a/go/ql/lib/semmle/go/frameworks/RsCors.qll +++ b/go/ql/lib/semmle/go/frameworks/RsCors.qll @@ -68,7 +68,7 @@ module RsCors { override RsOptions getConfig() { exists(RsOptions gc | ( - gc.getV().getBaseVariable().getDefinition().(SsaExplicitDefinition).getRhs() = + gc.getV().getBaseDefinition().(SsaExplicitWrite).getDefinition().getRhs() = base.asInstruction() or gc.getV().getAUse() = base ) and @@ -96,7 +96,7 @@ module RsCors { override RsOptions getConfig() { exists(RsOptions gc | ( - gc.getV().getBaseVariable().getDefinition().(SsaExplicitDefinition).getRhs() = + gc.getV().getBaseDefinition().(SsaExplicitWrite).getDefinition().getRhs() = base.asInstruction() or gc.getV().getAUse() = base ) and @@ -127,7 +127,7 @@ module RsCors { override RsOptions getConfig() { exists(RsOptions gc | ( - gc.getV().getBaseVariable().getDefinition().(SsaExplicitDefinition).getRhs() = + gc.getV().getBaseDefinition().(SsaExplicitWrite).getDefinition().getRhs() = base.asInstruction() or gc.getV().getAUse() = base ) and @@ -141,7 +141,7 @@ module RsCors { SsaWithFields v; RsOptions() { - this = v.getBaseVariable().getSourceVariable() and + this = v.getBaseDefinition().getSourceVariable() and v.getType().hasQualifiedName(packagePath(), "Options") } diff --git a/go/ql/lib/semmle/go/frameworks/stdlib/NetHttp.qll b/go/ql/lib/semmle/go/frameworks/stdlib/NetHttp.qll index 9bafe9721b76..662c39d6de89 100644 --- a/go/ql/lib/semmle/go/frameworks/stdlib/NetHttp.qll +++ b/go/ql/lib/semmle/go/frameworks/stdlib/NetHttp.qll @@ -15,7 +15,7 @@ module NetHttp { SsaWithFields v; StdlibResponseWriter() { - this = v.getBaseVariable().getSourceVariable() and + this = v.getBaseDefinition().getSourceVariable() and exists(Type t | t.implements("net/http", "ResponseWriter") | v.getType() = t) } diff --git a/go/ql/src/InconsistentCode/MissingErrorCheck.ql b/go/ql/src/InconsistentCode/MissingErrorCheck.ql index e16b8641a97e..132d64c68223 100644 --- a/go/ql/src/InconsistentCode/MissingErrorCheck.ql +++ b/go/ql/src/InconsistentCode/MissingErrorCheck.ql @@ -75,7 +75,7 @@ predicate checksValue(IR::Instruction instruction, DataFlow::SsaNode value) { // Now that we have use-use flow, phi nodes aren't directly involved in the flow graph. TODO: change this? DataFlow::SsaNode phiDefinedFrom(DataFlow::SsaNode node) { - result.getDefinition().(SsaPseudoDefinition).getAnInput() = node.getDefinition().getVariable() + result.getDefinition().(SsaPhiDefinition).getAnInput() = node.getDefinition() } DataFlow::SsaNode definedFrom(DataFlow::SsaNode node) { diff --git a/go/ql/src/InconsistentCode/WrappedErrorAlwaysNil.ql b/go/ql/src/InconsistentCode/WrappedErrorAlwaysNil.ql index 8c6fcab7d282..9d23143d056f 100644 --- a/go/ql/src/InconsistentCode/WrappedErrorAlwaysNil.ql +++ b/go/ql/src/InconsistentCode/WrappedErrorAlwaysNil.ql @@ -32,9 +32,9 @@ predicate nilTestGuard(DataFlow::Node g, Expr e, boolean outcome) { /** Gets a use of a local variable that has the value `nil`. */ DataFlow::ExprNode getNilFromLocalVariable() { - exists(SsaVariable ssa, Write w | - w.definesSsaVariable(ssa, Builtin::nil().getARead()) and - result.asInstruction() = ssa.getAUse() + exists(SsaDefinition def, Write w | + w.definesSsaDefinition(def, Builtin::nil().getARead()) and + result.getExpr() = def.getARead() ) } diff --git a/go/ql/src/RedundantCode/DeadStoreOfField.ql b/go/ql/src/RedundantCode/DeadStoreOfField.ql index fbe0fcf04c2e..c7603ef0029c 100644 --- a/go/ql/src/RedundantCode/DeadStoreOfField.ql +++ b/go/ql/src/RedundantCode/DeadStoreOfField.ql @@ -22,7 +22,7 @@ predicate escapes(DataFlow::Node nd) { // a global variable, a field or an array element), then it escapes exists(Write w | nd = w.getRhs() and - not w.definesSsaVariable(_, _) + not w.definesSsaDefinition(_, _) ) or // if `nd` is used as an index into an array or similar, then it escapes diff --git a/go/ql/src/RedundantCode/DeadStoreOfLocal.ql b/go/ql/src/RedundantCode/DeadStoreOfLocal.ql index 2b6886222aa4..f53f6f664b68 100644 --- a/go/ql/src/RedundantCode/DeadStoreOfLocal.ql +++ b/go/ql/src/RedundantCode/DeadStoreOfLocal.ql @@ -32,7 +32,7 @@ predicate isSimple(IR::Instruction nd) { from IR::WriteInstruction def, SsaSourceVariable target, IR::Instruction rhs, Expr lhs where def.writes(target, rhs) and - not exists(SsaExplicitDefinition ssa | ssa.getInstruction() = def) and + not exists(SsaExplicitWrite ssa | ssa.getDefinition() = def) and // exclude assignments in dead code def.getBasicBlock() instanceof ReachableBasicBlock and // exclude assignments with default values or simple expressions @@ -45,9 +45,9 @@ where // exclude variables with indirect references not target.mayHaveIndirectReferences() and // Report the assigned variable rather than the whole write instruction. A write to an - // `SsaSourceVariable` that survives the `SsaExplicitDefinition` exclusion above always has an + // `SsaSourceVariable` that survives the `SsaExplicitWrite` exclusion above always has an // explicit left-hand side expression (writes without one, such as result-variable writes at a - // `return`, are `SsaExplicitDefinition`s and so are already excluded), so this does not drop + // `return`, are `SsaExplicitWrite`s and so are already excluded), so this does not drop // any results. lhs = def.getLhs().getExpr() select lhs, "This definition of " + target + " is never used." diff --git a/go/ql/src/experimental/IntegerOverflow/RangeAnalysis.qll b/go/ql/src/experimental/IntegerOverflow/RangeAnalysis.qll index 615ea485ac42..e6dfd8a7e928 100644 --- a/go/ql/src/experimental/IntegerOverflow/RangeAnalysis.qll +++ b/go/ql/src/experimental/IntegerOverflow/RangeAnalysis.qll @@ -1,9 +1,7 @@ import go private import semmle.go.controlflow.Guards -Expr getAUse(SsaDefinition def) { - result = def.getVariable().getAUse().(IR::EvalInstruction).getExpr() -} +Expr getAUse(SsaDefinition def) { result = def.getARead() } /** * Gets the upper bound of expression `expr`. @@ -33,10 +31,10 @@ float getAnUpperBound(Expr expr) { then result = expr.getNumericValue() else ( //if this expression is an identifier - exists(SsaVariable v, Ident identifier | + exists(SsaDefinition v, Ident identifier | identifier = expr and identifier.refersTo(v.getSourceVariable()) and - v.getAUse() = IR::evalExprInstruction(identifier) and + getAUse(v) = identifier and ( if //if a condition expression exists before and one of the operand happens to be the identifier, we use this condition expression to narrow down the range. @@ -45,11 +43,11 @@ float getAnUpperBound(Expr expr) { ReachableBasicBlock bb | guardEnsuresLeq(n, branch, lesser, greater, _) and - IR::evalExprInstruction(lesser.asExpr()) = v.getAUse() and + lesser.asExpr() = getAUse(v) and n.controls(bb, branch) and bb.getANode() = IR::evalExprInstruction(identifier) and not exists(Expr e | - e = v.getAUse().(IR::EvalInstruction).getExpr() and + e = getAUse(v) and e.getParent*() = greater.asExpr() ) ) @@ -61,16 +59,16 @@ float getAnUpperBound(Expr expr) { n.controls(bb, branch) and bb.getANode() = IR::evalExprInstruction(identifier) and guardEnsuresLeq(n, branch, lesser, greater, bias) and - v.getAUse() = IR::evalExprInstruction(lesser.asExpr()) and + getAUse(v) = lesser.asExpr() and not exists(Expr e | - e = v.getAUse().(IR::EvalInstruction).getExpr() and + e = getAUse(v) and e.getParent*() = greater.asExpr() ) and result = getAnUpperBound(greater.asExpr()) + bias ) else //If not, find the corresponding `SsaDefinition`, then call `getAnSsaUpperBound` on it. - result = getAnSsaUpperBound(v.getDefinition()) + result = getAnSsaUpperBound(v) ) ) or @@ -184,10 +182,10 @@ float getALowerBound(Expr expr) { result = expr.getExactValue().toFloat() else ( //if this expression is an identifer - exists(SsaVariable v, Ident identifier | + exists(SsaDefinition v, Ident identifier | identifier = expr and identifier.refersTo(v.getSourceVariable()) and - v.getAUse() = IR::evalExprInstruction(identifier) and + getAUse(v) = identifier and ( //if exists a condition expression before this identifier if @@ -196,11 +194,11 @@ float getALowerBound(Expr expr) { ReachableBasicBlock bb | guardEnsuresLeq(n, branch, lesser, greater, _) and - IR::evalExprInstruction(greater.asExpr()) = v.getAUse() and + greater.asExpr() = getAUse(v) and n.controls(bb, branch) and bb.getANode() = IR::evalExprInstruction(identifier) and not exists(Expr e | - e = v.getAUse().(IR::EvalInstruction).getExpr() and + e = getAUse(v) and e.getParent*() = lesser.asExpr() ) ) @@ -212,9 +210,9 @@ float getALowerBound(Expr expr) { n.controls(bb, branch) and bb.getANode() = IR::evalExprInstruction(identifier) and guardEnsuresLeq(n, branch, lesser, greater, bias) and - v.getAUse() = IR::evalExprInstruction(greater.asExpr()) and + getAUse(v) = greater.asExpr() and not exists(Expr e | - e = v.getAUse().(IR::EvalInstruction).getExpr() and + e = getAUse(v) and e.getParent*() = lesser.asExpr() ) and lbs = getALowerBound(lesser.asExpr()) and @@ -222,7 +220,7 @@ float getALowerBound(Expr expr) { ) else //find corresponding SSA definition and calls `getAnSsaLowerBound` on it. - result = getAnSsaLowerBound(v.getDefinition()) + result = getAnSsaLowerBound(v) ) ) or @@ -339,20 +337,20 @@ float getALowerBound(Expr expr) { float getAnSsaUpperBound(SsaDefinition def) { not recursiveSelfDef(def) and ( - def instanceof SsaExplicitDefinition and - exists(SsaExplicitDefinition explicitDef | explicitDef = def | + def instanceof SsaExplicitWrite and + exists(SsaExplicitWrite explicitDef | explicitDef = def | //SSA definition corresponding to a `SimpleAssignStmt` - if explicitDef.getInstruction() instanceof IR::AssignInstruction + if explicitDef.getDefinition() instanceof IR::AssignInstruction then exists(IR::AssignInstruction assignInstr, SimpleAssignStmt simpleAssign | - assignInstr = explicitDef.getInstruction() and + assignInstr = explicitDef.getDefinition() and assignInstr.getRhs().(IR::EvalInstruction).getExpr() = simpleAssign.getRhs() and result = getAnUpperBound(simpleAssign.getRhs()) ) or //SSA definition corresponding to a ValueSpec(used in a variable declaration) exists(IR::AssignInstruction declInstr, ValueSpec vs, int i, Expr init | - declInstr = explicitDef.getInstruction() and + declInstr = explicitDef.getDefinition() and declInstr = IR::initInstruction(vs, i) and init = vs.getInit(i) and result = getAnUpperBound(init) @@ -360,10 +358,10 @@ float getAnSsaUpperBound(SsaDefinition def) { or //SSA definition corresponding to an `AddAssignStmt` (x += y) or `SubAssignStmt` (x -= y) exists( - IR::AssignInstruction assignInstr, SsaExplicitDefinition prevDef, + IR::AssignInstruction assignInstr, SsaExplicitWrite prevDef, CompoundAssignStmt compoundAssign, float prevBound, float delta | - assignInstr = explicitDef.getInstruction() and + assignInstr = explicitDef.getDefinition() and getAUse(prevDef) = compoundAssign.getLhs() and assignInstr = IR::assignInstruction(compoundAssign, 0) and prevBound = getAnSsaUpperBound(prevDef) and @@ -380,11 +378,11 @@ float getAnSsaUpperBound(SsaDefinition def) { else //SSA definition corresponding to an `IncDecStmt` if - explicitDef.getInstruction().(IR::EvalCompoundAssignRhsInstruction).getStmt() instanceof + explicitDef.getDefinition().(IR::EvalCompoundAssignRhsInstruction).getStmt() instanceof IncDecStmt then exists(IncDecStmt incOrDec, float exprLB | - explicitDef.getInstruction().(IR::EvalCompoundAssignRhsInstruction).getStmt() = incOrDec and + explicitDef.getDefinition().(IR::EvalCompoundAssignRhsInstruction).getStmt() = incOrDec and exprLB = getAnUpperBound(incOrDec.getOperand()) and ( //IncStmt(x++) @@ -402,9 +400,9 @@ float getAnSsaUpperBound(SsaDefinition def) { ) else ( //SSA definition coreponding to the init of the parameter - explicitDef.getInstruction() instanceof IR::InitParameterInstruction and + explicitDef.getDefinition() instanceof IR::InitParameterInstruction and exists(IR::InitParameterInstruction instr, Parameter p | - instr = explicitDef.getInstruction() and + instr = explicitDef.getDefinition() and IR::initParamInstruction(p) = instr and result = typeMaxValue(p.getType()) ) @@ -412,10 +410,10 @@ float getAnSsaUpperBound(SsaDefinition def) { ) or //this SSA definition is a phi node. - def instanceof SsaPhiNode and - exists(SsaPhiNode phi | + def instanceof SsaPhiDefinition and + exists(SsaPhiDefinition phi | phi = def and - result = getAnSsaUpperBound(phi.getAnInput().getDefinition()) + result = getAnSsaUpperBound(phi.getAnInput()) ) ) } @@ -426,20 +424,20 @@ float getAnSsaUpperBound(SsaDefinition def) { float getAnSsaLowerBound(SsaDefinition def) { not recursiveSelfDef(def) and ( - def instanceof SsaExplicitDefinition and - exists(SsaExplicitDefinition explicitDef | explicitDef = def | - if explicitDef.getInstruction() instanceof IR::AssignInstruction + def instanceof SsaExplicitWrite and + exists(SsaExplicitWrite explicitDef | explicitDef = def | + if explicitDef.getDefinition() instanceof IR::AssignInstruction then //SimpleAssignStmt exists(IR::AssignInstruction assignInstr, SimpleAssignStmt simpleAssign | - assignInstr = explicitDef.getInstruction() and + assignInstr = explicitDef.getDefinition() and assignInstr.getRhs().(IR::EvalInstruction).getExpr() = simpleAssign.getRhs() and result = getALowerBound(simpleAssign.getRhs()) ) or //ValueSpec exists(IR::AssignInstruction declInstr, ValueSpec vs, int i, Expr init | - declInstr = explicitDef.getInstruction() and + declInstr = explicitDef.getDefinition() and declInstr = IR::initInstruction(vs, i) and init = vs.getInit(i) and result = getALowerBound(init) @@ -447,10 +445,10 @@ float getAnSsaLowerBound(SsaDefinition def) { or //AddAssignStmt(x += y) exists( - IR::AssignInstruction assignInstr, SsaExplicitDefinition prevDef, + IR::AssignInstruction assignInstr, SsaExplicitWrite prevDef, CompoundAssignStmt compoundAssign, float prevBound, float delta | - assignInstr = explicitDef.getInstruction() and + assignInstr = explicitDef.getDefinition() and getAUse(prevDef) = compoundAssign.getLhs() and assignInstr = IR::assignInstruction(compoundAssign, 0) and prevBound = getAnSsaLowerBound(prevDef) and @@ -467,11 +465,11 @@ float getAnSsaLowerBound(SsaDefinition def) { else //IncDecStmt if - explicitDef.getInstruction().(IR::EvalCompoundAssignRhsInstruction).getStmt() instanceof + explicitDef.getDefinition().(IR::EvalCompoundAssignRhsInstruction).getStmt() instanceof IncDecStmt then exists(IncDecStmt incOrDec, float exprLB | - explicitDef.getInstruction().(IR::EvalCompoundAssignRhsInstruction).getStmt() = incOrDec and + explicitDef.getDefinition().(IR::EvalCompoundAssignRhsInstruction).getStmt() = incOrDec and exprLB = getALowerBound(incOrDec.getOperand()) and ( //IncStmt(x++) @@ -489,9 +487,9 @@ float getAnSsaLowerBound(SsaDefinition def) { ) else ( //init of the function parameter - explicitDef.getInstruction() instanceof IR::InitParameterInstruction and + explicitDef.getDefinition() instanceof IR::InitParameterInstruction and exists(IR::InitParameterInstruction instr, Parameter p | - instr = explicitDef.getInstruction() and + instr = explicitDef.getDefinition() and IR::initParamInstruction(p) = instr and result = typeMinValue(p.getType()) ) @@ -499,10 +497,10 @@ float getAnSsaLowerBound(SsaDefinition def) { ) or //phi node - def instanceof SsaPhiNode and - exists(SsaPhiNode phi | + def instanceof SsaPhiDefinition and + exists(SsaPhiDefinition phi | phi = def and - result = getAnSsaLowerBound(phi.getAnInput().getDefinition()) + result = getAnSsaLowerBound(phi.getAnInput()) ) ) } @@ -515,13 +513,13 @@ float getAnSsaLowerBound(SsaDefinition def) { predicate ssaDependsOnSsa(SsaDefinition nextDef, SsaDefinition prevDef) { //SSA definition corresponding to a `SimpleAssignStmt` exists(SimpleAssignStmt simpleAssign | - nextDef.(SsaExplicitDefinition).getInstruction() = IR::assignInstruction(simpleAssign, _) and + nextDef.(SsaExplicitWrite).getDefinition() = IR::assignInstruction(simpleAssign, _) and ssaDependsOnExpr(prevDef, simpleAssign.getRhs()) ) or //SSA definition corresponding to a `ValueSpec`(used in variable declaration) exists(IR::AssignInstruction declInstr, ValueSpec vs, int i, Expr init | - declInstr = nextDef.(SsaExplicitDefinition).getInstruction() and + declInstr = nextDef.(SsaExplicitWrite).getDefinition() and declInstr = IR::initInstruction(vs, i) and init = vs.getInit(i) and ssaDependsOnExpr(prevDef, init) @@ -530,7 +528,7 @@ predicate ssaDependsOnSsa(SsaDefinition nextDef, SsaDefinition prevDef) { //SSA definition corresponding to a `AddAssignStmt` or `SubAssignStmt` exists(CompoundAssignStmt compoundAssign | (compoundAssign instanceof AddAssignStmt or compoundAssign instanceof SubAssignStmt) and - nextDef.(SsaExplicitDefinition).getInstruction() = IR::assignInstruction(compoundAssign, 0) and + nextDef.(SsaExplicitWrite).getDefinition() = IR::assignInstruction(compoundAssign, 0) and ( getAUse(prevDef) = compoundAssign.getLhs() or ssaDependsOnExpr(prevDef, compoundAssign.getRhs()) @@ -539,17 +537,14 @@ predicate ssaDependsOnSsa(SsaDefinition nextDef, SsaDefinition prevDef) { or //SSA definition corresponding to a `IncDecStmt` exists(IncDecStmt incDec | - nextDef - .(SsaExplicitDefinition) - .getInstruction() - .(IR::EvalCompoundAssignRhsInstruction) - .getStmt() = incDec and + nextDef.(SsaExplicitWrite).getDefinition().(IR::EvalCompoundAssignRhsInstruction).getStmt() = + incDec and ssaDependsOnExpr(prevDef, incDec.getOperand()) ) or //if `nextDef` corresponding to the init of a parameter, there is no corresponding `prevDef` //if `nextDef` is a phi node and `prevDef` is one of the input of the phi node, then `nextDef` depends on `prevDef` directly. - exists(SsaPhiNode phi | nextDef = phi and phi.getAnInput().getDefinition() = prevDef) + exists(SsaPhiDefinition phi | nextDef = phi and phi.getAnInput() = prevDef) } /** diff --git a/go/ql/test/library-tests/semmle/go/dataflow/SSA/DefUse.expected b/go/ql/test/library-tests/semmle/go/dataflow/SSA/DefUse.expected index 17be1f70f90c..3a69c5465dd3 100644 --- a/go/ql/test/library-tests/semmle/go/dataflow/SSA/DefUse.expected +++ b/go/ql/test/library-tests/semmle/go/dataflow/SSA/DefUse.expected @@ -6,36 +6,32 @@ | main.go:21:7:21:7 | y | main.go:16:2:18:2 | SSA phi(y) | main.go:14:2:14:2 | y | | main.go:23:12:23:12 | x | main.go:20:2:22:2 | SSA phi(x) | main.go:13:6:13:6 | x | | main.go:23:15:23:15 | y | main.go:16:2:18:2 | SSA phi(y) | main.go:14:2:14:2 | y | -| main.go:27:10:27:10 | x | main.go:26:10:26:10 | SSA def(x) | main.go:26:10:26:10 | x | +| main.go:27:10:27:10 | x | main.go:26:10:26:10 | SSA param(x) | main.go:26:10:26:10 | x | | main.go:29:10:29:10 | b | main.go:27:2:27:13 | SSA def(b) | main.go:27:5:27:5 | b | | main.go:29:13:29:13 | a | main.go:27:2:27:13 | SSA def(a) | main.go:27:2:27:2 | a | | main.go:31:9:31:9 | a | main.go:28:2:30:2 | SSA phi(a) | main.go:27:2:27:2 | a | | main.go:31:12:31:12 | b | main.go:28:2:30:2 | SSA phi(b) | main.go:27:5:27:5 | b | -| main.go:35:3:35:3 | x | main.go:34:11:34:11 | SSA def(x) | main.go:34:11:34:11 | x | +| main.go:35:3:35:3 | x | main.go:34:11:34:11 | SSA param(x) | main.go:34:11:34:11 | x | | main.go:40:10:40:10 | x | main.go:39:2:39:8 | SSA def(x) | main.go:39:2:39:2 | x | | main.go:42:8:42:10 | ptr | main.go:40:2:40:10 | SSA def(ptr) | main.go:40:2:40:4 | ptr | | main.go:44:12:44:12 | x | main.go:39:2:39:8 | SSA def(x) | main.go:39:2:39:2 | x | -| main.go:47:25:50:1 | result-read:0 block statement | main.go:48:2:48:12 | SSA def(result) | main.go:47:13:47:18 | result | -| main.go:52:26:54:1 | result-read:0 block statement | main.go:52:26:54:1 | SSA def(result) | main.go:52:14:52:19 | result | | main.go:61:12:61:12 | x | main.go:58:6:58:11 | SSA phi(x) | main.go:57:6:57:6 | x | | main.go:64:16:64:16 | i | main.go:64:20:69:2 | SSA phi(i) | main.go:64:6:64:6 | i | | main.go:70:12:70:12 | y | main.go:64:20:69:2 | SSA phi(y) | main.go:63:2:63:2 | y | | main.go:73:16:73:16 | i | main.go:73:20:78:2 | SSA phi(i) | main.go:73:6:73:6 | i | | main.go:79:12:79:12 | z | main.go:74:3:74:7 | SSA def(z) | main.go:72:2:72:2 | z | -| main.go:82:36:86:1 | result-read:0 block statement | main.go:84:2:84:15 | SSA def(a) | main.go:82:18:82:18 | a | -| main.go:82:36:86:1 | result-read:1 block statement | main.go:82:36:86:1 | SSA def(b) | main.go:82:25:82:25 | b | | main.go:84:9:84:9 | x | main.go:83:2:83:8 | SSA def(x) | main.go:83:2:83:2 | x | | main.go:84:15:84:15 | x | main.go:83:2:83:8 | SSA def(x) | main.go:83:2:83:2 | x | -| main.go:97:2:97:8 | wrapper | main.go:95:22:95:28 | SSA def(wrapper) | main.go:95:22:95:28 | wrapper | -| main.go:100:9:100:9 | x | main.go:97:2:99:3 | SSA def(x) | main.go:96:2:96:2 | x | -| main.go:105:2:105:8 | wrapper | main.go:103:20:103:26 | SSA def(wrapper) | main.go:103:20:103:26 | wrapper | -| main.go:106:8:106:8 | x | main.go:105:16:108:2 | SSA def(x) | main.go:104:2:104:2 | x | +| main.go:97:2:97:8 | wrapper | main.go:95:22:95:28 | SSA param(wrapper) | main.go:95:22:95:28 | wrapper | +| main.go:100:9:100:9 | x | main.go:97:2:99:3 | SSA implicit def(x) | main.go:96:2:96:2 | x | +| main.go:105:2:105:8 | wrapper | main.go:103:20:103:26 | SSA param(wrapper) | main.go:103:20:103:26 | wrapper | +| main.go:106:8:106:8 | x | main.go:105:16:108:2 | SSA implicit def(x) | main.go:104:2:104:2 | x | | main.go:107:7:107:7 | y | main.go:106:3:106:8 | SSA def(y) | main.go:106:3:106:3 | y | | main.go:109:9:109:9 | x | main.go:104:2:104:7 | SSA def(x) | main.go:104:2:104:2 | x | -| main.go:114:2:114:8 | wrapper | main.go:112:29:112:35 | SSA def(wrapper) | main.go:112:29:112:35 | wrapper | -| main.go:115:8:115:8 | x | main.go:114:16:117:2 | SSA def(x) | main.go:113:2:113:2 | x | +| main.go:114:2:114:8 | wrapper | main.go:112:29:112:35 | SSA param(wrapper) | main.go:112:29:112:35 | wrapper | +| main.go:115:8:115:8 | x | main.go:114:16:117:2 | SSA implicit def(x) | main.go:113:2:113:2 | x | | main.go:116:7:116:7 | y | main.go:115:3:115:12 | SSA def(y) | main.go:115:3:115:3 | y | -| main.go:118:9:118:9 | x | main.go:114:2:117:3 | SSA def(x) | main.go:113:2:113:2 | x | +| main.go:118:9:118:9 | x | main.go:114:2:117:3 | SSA implicit def(x) | main.go:113:2:113:2 | x | | main.go:135:2:135:2 | p | main.go:129:2:133:2 | SSA phi(p) | main.go:128:6:128:6 | p | | main.go:137:12:137:12 | p | main.go:129:2:133:2 | SSA phi(p) | main.go:128:6:128:6 | p | | main.go:137:17:137:17 | p | main.go:129:2:133:2 | SSA phi(p) | main.go:128:6:128:6 | p | diff --git a/go/ql/test/library-tests/semmle/go/dataflow/SSA/DefUse.ql b/go/ql/test/library-tests/semmle/go/dataflow/SSA/DefUse.ql index 1ebb0c5bb090..2cf3fd406a41 100644 --- a/go/ql/test/library-tests/semmle/go/dataflow/SSA/DefUse.ql +++ b/go/ql/test/library-tests/semmle/go/dataflow/SSA/DefUse.ql @@ -1,4 +1,4 @@ import go -from SsaVariable ssa -select ssa.getAUse(), ssa.getDefinition(), ssa.getSourceVariable() +from SsaDefinition ssa +select ssa.getARead(), ssa, ssa.getSourceVariable() diff --git a/go/ql/test/library-tests/semmle/go/dataflow/SSA/SsaDefinition.expected b/go/ql/test/library-tests/semmle/go/dataflow/SSA/SsaDefinition.expected index 0345f6c5b70a..0fbf6c51908d 100644 --- a/go/ql/test/library-tests/semmle/go/dataflow/SSA/SsaDefinition.expected +++ b/go/ql/test/library-tests/semmle/go/dataflow/SSA/SsaDefinition.expected @@ -4,14 +4,14 @@ | main.go:17:3:17:9 | SSA def(y) | | main.go:20:2:22:2 | SSA phi(x) | | main.go:21:3:21:7 | SSA def(x) | -| main.go:26:10:26:10 | SSA def(x) | +| main.go:26:10:26:10 | SSA param(x) | | main.go:27:2:27:13 | SSA def(a) | | main.go:27:2:27:13 | SSA def(b) | | main.go:28:2:30:2 | SSA phi(a) | | main.go:28:2:30:2 | SSA phi(b) | | main.go:29:3:29:13 | SSA def(a) | | main.go:29:3:29:13 | SSA def(b) | -| main.go:34:11:34:11 | SSA def(x) | +| main.go:34:11:34:11 | SSA param(x) | | main.go:39:2:39:8 | SSA def(x) | | main.go:40:2:40:10 | SSA def(ptr) | | main.go:48:2:48:12 | SSA def(result) | @@ -32,18 +32,18 @@ | main.go:82:36:86:1 | SSA def(b) | | main.go:83:2:83:8 | SSA def(x) | | main.go:84:2:84:15 | SSA def(a) | -| main.go:95:22:95:28 | SSA def(wrapper) | +| main.go:95:22:95:28 | SSA param(wrapper) | | main.go:96:2:96:7 | SSA def(x) | -| main.go:97:2:99:3 | SSA def(x) | +| main.go:97:2:99:3 | SSA implicit def(x) | | main.go:98:3:98:7 | SSA def(x) | -| main.go:103:20:103:26 | SSA def(wrapper) | +| main.go:103:20:103:26 | SSA param(wrapper) | | main.go:104:2:104:7 | SSA def(x) | -| main.go:105:16:108:2 | SSA def(x) | +| main.go:105:16:108:2 | SSA implicit def(x) | | main.go:106:3:106:8 | SSA def(y) | -| main.go:112:29:112:35 | SSA def(wrapper) | +| main.go:112:29:112:35 | SSA param(wrapper) | | main.go:113:2:113:7 | SSA def(x) | -| main.go:114:2:117:3 | SSA def(x) | -| main.go:114:16:117:2 | SSA def(x) | +| main.go:114:2:117:3 | SSA implicit def(x) | +| main.go:114:16:117:2 | SSA implicit def(x) | | main.go:115:3:115:12 | SSA def(y) | | main.go:116:3:116:7 | SSA def(x) | | main.go:129:2:133:2 | SSA phi(p) | diff --git a/go/ql/test/library-tests/semmle/go/dataflow/SSA/SsaWithFields.expected b/go/ql/test/library-tests/semmle/go/dataflow/SSA/SsaWithFields.expected index f00640593538..fcd2bf9cb333 100644 --- a/go/ql/test/library-tests/semmle/go/dataflow/SSA/SsaWithFields.expected +++ b/go/ql/test/library-tests/semmle/go/dataflow/SSA/SsaWithFields.expected @@ -4,14 +4,14 @@ | main.go:17:3:17:9 | (SSA def(y)) | y | | main.go:20:2:22:2 | (SSA phi(x)) | x | | main.go:21:3:21:7 | (SSA def(x)) | x | -| main.go:26:10:26:10 | (SSA def(x)) | x | +| main.go:26:10:26:10 | (SSA param(x)) | x | | main.go:27:2:27:13 | (SSA def(a)) | a | | main.go:27:2:27:13 | (SSA def(b)) | b | | main.go:28:2:30:2 | (SSA phi(a)) | a | | main.go:28:2:30:2 | (SSA phi(b)) | b | | main.go:29:3:29:13 | (SSA def(a)) | a | | main.go:29:3:29:13 | (SSA def(b)) | b | -| main.go:34:11:34:11 | (SSA def(x)) | x | +| main.go:34:11:34:11 | (SSA param(x)) | x | | main.go:39:2:39:8 | (SSA def(x)) | x | | main.go:40:2:40:10 | (SSA def(ptr)) | ptr | | main.go:48:2:48:12 | (SSA def(result)) | result | @@ -32,21 +32,21 @@ | main.go:82:36:86:1 | (SSA def(b)) | b | | main.go:83:2:83:8 | (SSA def(x)) | x | | main.go:84:2:84:15 | (SSA def(a)) | a | -| main.go:95:22:95:28 | (SSA def(wrapper)) | wrapper | -| main.go:95:22:95:28 | (SSA def(wrapper)).s | wrapper.s | +| main.go:95:22:95:28 | (SSA param(wrapper)) | wrapper | +| main.go:95:22:95:28 | (SSA param(wrapper)).s | wrapper.s | | main.go:96:2:96:7 | (SSA def(x)) | x | -| main.go:97:2:99:3 | (SSA def(x)) | x | +| main.go:97:2:99:3 | (SSA implicit def(x)) | x | | main.go:98:3:98:7 | (SSA def(x)) | x | -| main.go:103:20:103:26 | (SSA def(wrapper)) | wrapper | -| main.go:103:20:103:26 | (SSA def(wrapper)).s | wrapper.s | +| main.go:103:20:103:26 | (SSA param(wrapper)) | wrapper | +| main.go:103:20:103:26 | (SSA param(wrapper)).s | wrapper.s | | main.go:104:2:104:7 | (SSA def(x)) | x | -| main.go:105:16:108:2 | (SSA def(x)) | x | +| main.go:105:16:108:2 | (SSA implicit def(x)) | x | | main.go:106:3:106:8 | (SSA def(y)) | y | -| main.go:112:29:112:35 | (SSA def(wrapper)) | wrapper | -| main.go:112:29:112:35 | (SSA def(wrapper)).s | wrapper.s | +| main.go:112:29:112:35 | (SSA param(wrapper)) | wrapper | +| main.go:112:29:112:35 | (SSA param(wrapper)).s | wrapper.s | | main.go:113:2:113:7 | (SSA def(x)) | x | -| main.go:114:2:117:3 | (SSA def(x)) | x | -| main.go:114:16:117:2 | (SSA def(x)) | x | +| main.go:114:2:117:3 | (SSA implicit def(x)) | x | +| main.go:114:16:117:2 | (SSA implicit def(x)) | x | | main.go:115:3:115:12 | (SSA def(y)) | y | | main.go:116:3:116:7 | (SSA def(x)) | x | | main.go:129:2:133:2 | (SSA phi(p)) | p | From b059a0aeb9078d551ad4d07d78d0ec84d2d3bae2 Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Tue, 20 Oct 2026 19:26:12 +0100 Subject: [PATCH 3/9] Accept test changes due to renamed SSA classes --- .../example-tests/snippets/typeinfo.expected | 2 +- .../DecompressionBombs.expected | 194 +++++++++--------- .../Unsafe/WrongUsageOfUnsafe.expected | 6 +- .../dataflow/ExternalTaintFlow/srcs.expected | 2 +- .../dataflow/ExternalValueFlow/srcs.expected | 2 +- .../dataflow/FlowSteps/LocalFlowStep.expected | 58 +++--- .../FunctionInput_getExitNode.expected | 26 +-- .../Beego/CleartextLogging.expected | 138 ++++++------- .../semmle/go/frameworks/GoKit/main.go | 4 +- .../frameworks/GoMicro/LogInjection.expected | 6 +- .../semmle/go/frameworks/GoMicro/main.go | 2 +- .../frameworks/Twirp/RequestForgery.expected | 26 +-- .../gqlgen/graph/schema.resolvers.go | 2 +- .../UnhandledCloseWritableHandle.expected | 20 +- .../CWE-022/UnsafeUnzipSymlink.expected | 12 +- .../Security/CWE-022/ZipSlip.expected | 8 +- .../Security/CWE-079/StoredXss.expected | 6 +- .../CWE-312/CleartextLogging.expected | 14 +- .../CWE-322/InsecureHostKeyCallback.expected | 16 +- .../CWE-326/InsufficientKeySize.expected | 20 +- .../CWE-347/MissingJwtSignatureCheck.expected | 12 +- .../BadRedirectCheck.expected | 16 +- 22 files changed, 296 insertions(+), 296 deletions(-) diff --git a/go/ql/test/example-tests/snippets/typeinfo.expected b/go/ql/test/example-tests/snippets/typeinfo.expected index 692838d50e98..c4faf6d092da 100644 --- a/go/ql/test/example-tests/snippets/typeinfo.expected +++ b/go/ql/test/example-tests/snippets/typeinfo.expected @@ -2,7 +2,7 @@ | 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 WriteProxy | -| main.go:18:12:18:14 | SSA def(req) | +| main.go:18:12:18:14 | SSA param(req) | | main.go:18:12:18:14 | req | | main.go:20:5:20:7 | req | | main.go:20:5:20:7 | req [postupdate] | diff --git a/go/ql/test/experimental/CWE-522-DecompressionBombs/DecompressionBombs.expected b/go/ql/test/experimental/CWE-522-DecompressionBombs/DecompressionBombs.expected index 2fea1cfd6d75..7e0eb4bc9bd6 100644 --- a/go/ql/test/experimental/CWE-522-DecompressionBombs/DecompressionBombs.expected +++ b/go/ql/test/experimental/CWE-522-DecompressionBombs/DecompressionBombs.expected @@ -47,27 +47,27 @@ | test.go:621:25:621:31 | tarRead | test.go:93:5:93:16 | selection of Body | test.go:621:25:621:31 | tarRead | This decompression is $@. | test.go:93:5:93:16 | selection of Body | decompressing compressed data without managing output size | | test.go:629:2:629:8 | tarRead | test.go:93:5:93:16 | selection of Body | test.go:629:2:629:8 | tarRead | This decompression is $@. | test.go:93:5:93:16 | selection of Body | decompressing compressed data without managing output size | edges -| test.go:59:16:59:44 | call to FormValue | test.go:128:20:128:27 | SSA def(filename) | provenance | Src:MaD:2 | -| test.go:60:15:60:26 | selection of Body | test.go:158:19:158:22 | SSA def(file) | provenance | Src:MaD:1 | -| test.go:61:24:61:35 | selection of Body | test.go:169:28:169:31 | SSA def(file) | provenance | Src:MaD:1 | -| test.go:62:13:62:24 | selection of Body | test.go:181:17:181:20 | SSA def(file) | provenance | Src:MaD:1 | -| test.go:64:8:64:19 | selection of Body | test.go:208:12:208:15 | SSA def(file) | provenance | Src:MaD:1 | -| test.go:66:8:66:19 | selection of Body | test.go:233:12:233:15 | SSA def(file) | provenance | Src:MaD:1 | -| test.go:68:17:68:28 | selection of Body | test.go:258:21:258:24 | SSA def(file) | provenance | Src:MaD:1 | -| test.go:70:13:70:24 | selection of Body | test.go:283:17:283:20 | SSA def(file) | provenance | Src:MaD:1 | -| test.go:72:16:72:27 | selection of Body | test.go:308:20:308:23 | SSA def(file) | provenance | Src:MaD:1 | -| test.go:74:7:74:18 | selection of Body | test.go:333:11:333:14 | SSA def(file) | provenance | Src:MaD:1 | -| test.go:76:9:76:20 | selection of Body | test.go:358:13:358:16 | SSA def(file) | provenance | Src:MaD:1 | -| test.go:78:18:78:29 | selection of Body | test.go:384:22:384:25 | SSA def(file) | provenance | Src:MaD:1 | -| test.go:80:5:80:16 | selection of Body | test.go:412:9:412:12 | SSA def(file) | provenance | Src:MaD:1 | -| test.go:82:7:82:18 | selection of Body | test.go:447:11:447:14 | SSA def(file) | provenance | Src:MaD:1 | -| test.go:84:15:84:26 | selection of Body | test.go:440:19:440:21 | SSA def(src) | provenance | Src:MaD:1 | -| test.go:85:16:85:27 | selection of Body | test.go:472:20:472:23 | SSA def(file) | provenance | Src:MaD:1 | -| test.go:87:16:87:27 | selection of Body | test.go:499:20:499:23 | SSA def(file) | provenance | Src:MaD:1 | -| test.go:89:17:89:28 | selection of Body | test.go:526:21:526:24 | SSA def(file) | provenance | Src:MaD:1 | -| test.go:91:15:91:26 | selection of Body | test.go:555:19:555:22 | SSA def(file) | provenance | Src:MaD:1 | -| test.go:93:5:93:16 | selection of Body | test.go:580:9:580:12 | SSA def(file) | provenance | Src:MaD:1 | -| test.go:128:20:128:27 | SSA def(filename) | test.go:130:33:130:40 | filename | provenance | | +| test.go:59:16:59:44 | call to FormValue | test.go:128:20:128:27 | SSA param(filename) | provenance | Src:MaD:2 | +| test.go:60:15:60:26 | selection of Body | test.go:158:19:158:22 | SSA param(file) | provenance | Src:MaD:1 | +| test.go:61:24:61:35 | selection of Body | test.go:169:28:169:31 | SSA param(file) | provenance | Src:MaD:1 | +| test.go:62:13:62:24 | selection of Body | test.go:181:17:181:20 | SSA param(file) | provenance | Src:MaD:1 | +| test.go:64:8:64:19 | selection of Body | test.go:208:12:208:15 | SSA param(file) | provenance | Src:MaD:1 | +| test.go:66:8:66:19 | selection of Body | test.go:233:12:233:15 | SSA param(file) | provenance | Src:MaD:1 | +| test.go:68:17:68:28 | selection of Body | test.go:258:21:258:24 | SSA param(file) | provenance | Src:MaD:1 | +| test.go:70:13:70:24 | selection of Body | test.go:283:17:283:20 | SSA param(file) | provenance | Src:MaD:1 | +| test.go:72:16:72:27 | selection of Body | test.go:308:20:308:23 | SSA param(file) | provenance | Src:MaD:1 | +| test.go:74:7:74:18 | selection of Body | test.go:333:11:333:14 | SSA param(file) | provenance | Src:MaD:1 | +| test.go:76:9:76:20 | selection of Body | test.go:358:13:358:16 | SSA param(file) | provenance | Src:MaD:1 | +| test.go:78:18:78:29 | selection of Body | test.go:384:22:384:25 | SSA param(file) | provenance | Src:MaD:1 | +| test.go:80:5:80:16 | selection of Body | test.go:412:9:412:12 | SSA param(file) | provenance | Src:MaD:1 | +| test.go:82:7:82:18 | selection of Body | test.go:447:11:447:14 | SSA param(file) | provenance | Src:MaD:1 | +| test.go:84:15:84:26 | selection of Body | test.go:440:19:440:21 | SSA param(src) | provenance | Src:MaD:1 | +| test.go:85:16:85:27 | selection of Body | test.go:472:20:472:23 | SSA param(file) | provenance | Src:MaD:1 | +| test.go:87:16:87:27 | selection of Body | test.go:499:20:499:23 | SSA param(file) | provenance | Src:MaD:1 | +| test.go:89:17:89:28 | selection of Body | test.go:526:21:526:24 | SSA param(file) | provenance | Src:MaD:1 | +| test.go:91:15:91:26 | selection of Body | test.go:555:19:555:22 | SSA param(file) | provenance | Src:MaD:1 | +| test.go:93:5:93:16 | selection of Body | test.go:580:9:580:12 | SSA param(file) | provenance | Src:MaD:1 | +| test.go:128:20:128:27 | SSA param(filename) | test.go:130:33:130:40 | filename | provenance | | | test.go:130:2:130:41 | extract:0 ... := ... | test.go:132:12:132:12 | f | provenance | | | test.go:130:33:130:40 | filename | test.go:130:2:130:41 | extract:0 ... := ... | provenance | Config | | test.go:130:33:130:40 | filename | test.go:143:51:143:58 | filename | provenance | | @@ -77,7 +77,7 @@ edges | test.go:143:51:143:58 | filename | test.go:143:2:143:59 | extract:0 ... := ... | provenance | Config | | test.go:145:12:145:12 | f | test.go:145:12:145:19 | call to Open | provenance | Config | | test.go:145:12:145:19 | call to Open | test.go:147:37:147:38 | rc | provenance | | -| test.go:158:19:158:22 | SSA def(file) | test.go:159:25:159:28 | file | provenance | | +| test.go:158:19:158:22 | SSA param(file) | test.go:159:25:159:28 | file | provenance | | | test.go:159:2:159:29 | extract:0 ... := ... | test.go:160:48:160:52 | file1 | provenance | | | test.go:159:25:159:28 | file | test.go:159:2:159:29 | extract:0 ... := ... | provenance | MaD:6 | | test.go:160:2:160:69 | extract:0 ... := ... | test.go:163:26:163:29 | file | provenance | | @@ -85,7 +85,7 @@ edges | test.go:160:48:160:52 | file1 | test.go:160:32:160:53 | call to NewReader | provenance | MaD:5 | | test.go:163:3:163:36 | extract:0 ... := ... | test.go:164:36:164:51 | fileReaderCloser | provenance | | | test.go:163:26:163:29 | file | test.go:163:3:163:36 | extract:0 ... := ... | provenance | MaD:4 | -| test.go:169:28:169:31 | SSA def(file) | test.go:170:25:170:28 | file | provenance | | +| test.go:169:28:169:31 | SSA param(file) | test.go:170:25:170:28 | file | provenance | | | test.go:170:2:170:29 | extract:0 ... := ... | test.go:171:57:171:61 | file2 | provenance | | | test.go:170:25:170:28 | file | test.go:170:2:170:29 | extract:0 ... := ... | provenance | MaD:6 | | test.go:171:2:171:78 | extract:0 ... := ... | test.go:175:26:175:29 | file | provenance | | @@ -93,64 +93,64 @@ edges | test.go:171:57:171:61 | file2 | test.go:171:41:171:62 | call to NewReader | provenance | MaD:5 | | test.go:175:26:175:29 | file | test.go:175:26:175:36 | call to Open | provenance | Config | | test.go:175:26:175:36 | call to Open | test.go:176:36:176:51 | fileReaderCloser | provenance | | -| test.go:181:17:181:20 | SSA def(file) | test.go:184:41:184:44 | file | provenance | | +| test.go:181:17:181:20 | SSA param(file) | test.go:184:41:184:44 | file | provenance | | | test.go:184:2:184:73 | extract:0 ... := ... | test.go:186:2:186:12 | bzip2Reader | provenance | | | test.go:184:2:184:73 | extract:0 ... := ... | test.go:187:26:187:36 | bzip2Reader | provenance | | | test.go:184:41:184:44 | file | test.go:184:2:184:73 | extract:0 ... := ... | provenance | Config | | test.go:187:12:187:37 | call to NewReader | test.go:189:18:189:24 | tarRead | provenance | | | test.go:187:26:187:36 | bzip2Reader | test.go:187:12:187:37 | call to NewReader | provenance | MaD:3 | -| test.go:189:18:189:24 | tarRead | test.go:611:22:611:28 | SSA def(tarRead) | provenance | | -| test.go:208:12:208:15 | SSA def(file) | test.go:211:33:211:36 | file | provenance | | +| test.go:189:18:189:24 | tarRead | test.go:611:22:611:28 | SSA param(tarRead) | provenance | | +| test.go:208:12:208:15 | SSA param(file) | test.go:211:33:211:36 | file | provenance | | | test.go:211:17:211:37 | call to NewReader | test.go:213:2:213:12 | bzip2Reader | provenance | | | test.go:211:17:211:37 | call to NewReader | test.go:214:26:214:36 | bzip2Reader | provenance | | | test.go:211:33:211:36 | file | test.go:211:17:211:37 | call to NewReader | provenance | Config | | test.go:214:12:214:37 | call to NewReader | test.go:216:18:216:24 | tarRead | provenance | | | test.go:214:26:214:36 | bzip2Reader | test.go:214:12:214:37 | call to NewReader | provenance | MaD:3 | -| test.go:216:18:216:24 | tarRead | test.go:611:22:611:28 | SSA def(tarRead) | provenance | | -| test.go:233:12:233:15 | SSA def(file) | test.go:236:33:236:36 | file | provenance | | +| test.go:216:18:216:24 | tarRead | test.go:611:22:611:28 | SSA param(tarRead) | provenance | | +| test.go:233:12:233:15 | SSA param(file) | test.go:236:33:236:36 | file | provenance | | | test.go:236:17:236:37 | call to NewReader | test.go:238:2:238:12 | flateReader | provenance | | | test.go:236:17:236:37 | call to NewReader | test.go:239:26:239:36 | flateReader | provenance | | | test.go:236:33:236:36 | file | test.go:236:17:236:37 | call to NewReader | provenance | Config | | test.go:239:12:239:37 | call to NewReader | test.go:241:18:241:24 | tarRead | provenance | | | test.go:239:26:239:36 | flateReader | test.go:239:12:239:37 | call to NewReader | provenance | MaD:3 | -| test.go:241:18:241:24 | tarRead | test.go:611:22:611:28 | SSA def(tarRead) | provenance | | -| test.go:258:21:258:24 | SSA def(file) | test.go:261:42:261:45 | file | provenance | | +| test.go:241:18:241:24 | tarRead | test.go:611:22:611:28 | SSA param(tarRead) | provenance | | +| test.go:258:21:258:24 | SSA param(file) | test.go:261:42:261:45 | file | provenance | | | test.go:261:17:261:46 | call to NewReader | test.go:263:2:263:12 | flateReader | provenance | | | test.go:261:17:261:46 | call to NewReader | test.go:264:26:264:36 | flateReader | provenance | | | test.go:261:42:261:45 | file | test.go:261:17:261:46 | call to NewReader | provenance | Config | | test.go:264:12:264:37 | call to NewReader | test.go:266:18:266:24 | tarRead | provenance | | | test.go:264:26:264:36 | flateReader | test.go:264:12:264:37 | call to NewReader | provenance | MaD:3 | -| test.go:266:18:266:24 | tarRead | test.go:611:22:611:28 | SSA def(tarRead) | provenance | | -| test.go:283:17:283:20 | SSA def(file) | test.go:286:41:286:44 | file | provenance | | +| test.go:266:18:266:24 | tarRead | test.go:611:22:611:28 | SSA param(tarRead) | provenance | | +| test.go:283:17:283:20 | SSA param(file) | test.go:286:41:286:44 | file | provenance | | | test.go:286:2:286:73 | extract:0 ... := ... | test.go:288:2:288:12 | flateReader | provenance | | | test.go:286:2:286:73 | extract:0 ... := ... | test.go:289:26:289:36 | flateReader | provenance | | | test.go:286:41:286:44 | file | test.go:286:2:286:73 | extract:0 ... := ... | provenance | Config | | test.go:289:12:289:37 | call to NewReader | test.go:291:18:291:24 | tarRead | provenance | | | test.go:289:26:289:36 | flateReader | test.go:289:12:289:37 | call to NewReader | provenance | MaD:3 | -| test.go:291:18:291:24 | tarRead | test.go:611:22:611:28 | SSA def(tarRead) | provenance | | -| test.go:308:20:308:23 | SSA def(file) | test.go:311:43:311:46 | file | provenance | | +| test.go:291:18:291:24 | tarRead | test.go:611:22:611:28 | SSA param(tarRead) | provenance | | +| test.go:308:20:308:23 | SSA param(file) | test.go:311:43:311:46 | file | provenance | | | test.go:311:2:311:47 | extract:0 ... := ... | test.go:313:2:313:11 | zlibReader | provenance | | | test.go:311:2:311:47 | extract:0 ... := ... | test.go:314:26:314:35 | zlibReader | provenance | | | test.go:311:43:311:46 | file | test.go:311:2:311:47 | extract:0 ... := ... | provenance | Config | | test.go:314:12:314:36 | call to NewReader | test.go:316:18:316:24 | tarRead | provenance | | | test.go:314:26:314:35 | zlibReader | test.go:314:12:314:36 | call to NewReader | provenance | MaD:3 | -| test.go:316:18:316:24 | tarRead | test.go:611:22:611:28 | SSA def(tarRead) | provenance | | -| test.go:333:11:333:14 | SSA def(file) | test.go:336:34:336:37 | file | provenance | | +| test.go:316:18:316:24 | tarRead | test.go:611:22:611:28 | SSA param(tarRead) | provenance | | +| test.go:333:11:333:14 | SSA param(file) | test.go:336:34:336:37 | file | provenance | | | test.go:336:2:336:38 | extract:0 ... := ... | test.go:338:2:338:11 | zlibReader | provenance | | | test.go:336:2:336:38 | extract:0 ... := ... | test.go:339:26:339:35 | zlibReader | provenance | | | test.go:336:34:336:37 | file | test.go:336:2:336:38 | extract:0 ... := ... | provenance | Config | | test.go:339:12:339:36 | call to NewReader | test.go:341:18:341:24 | tarRead | provenance | | | test.go:339:26:339:35 | zlibReader | test.go:339:12:339:36 | call to NewReader | provenance | MaD:3 | -| test.go:341:18:341:24 | tarRead | test.go:611:22:611:28 | SSA def(tarRead) | provenance | | -| test.go:358:13:358:16 | SSA def(file) | test.go:361:35:361:38 | file | provenance | | +| test.go:341:18:341:24 | tarRead | test.go:611:22:611:28 | SSA param(tarRead) | provenance | | +| test.go:358:13:358:16 | SSA param(file) | test.go:361:35:361:38 | file | provenance | | | test.go:361:18:361:39 | call to NewReader | test.go:363:2:363:13 | snappyReader | provenance | | | test.go:361:18:361:39 | call to NewReader | test.go:364:2:364:13 | snappyReader | provenance | | | test.go:361:18:361:39 | call to NewReader | test.go:365:26:365:37 | snappyReader | provenance | | | test.go:361:35:361:38 | file | test.go:361:18:361:39 | call to NewReader | provenance | Config | | test.go:365:12:365:38 | call to NewReader | test.go:367:18:367:24 | tarRead | provenance | | | test.go:365:26:365:37 | snappyReader | test.go:365:12:365:38 | call to NewReader | provenance | MaD:3 | -| test.go:367:18:367:24 | tarRead | test.go:611:22:611:28 | SSA def(tarRead) | provenance | | -| test.go:384:22:384:25 | SSA def(file) | test.go:387:44:387:47 | file | provenance | | +| test.go:367:18:367:24 | tarRead | test.go:611:22:611:28 | SSA param(tarRead) | provenance | | +| test.go:384:22:384:25 | SSA param(file) | test.go:387:44:387:47 | file | provenance | | | test.go:387:18:387:48 | call to NewReader | test.go:389:2:389:13 | snappyReader | provenance | | | test.go:387:18:387:48 | call to NewReader | test.go:391:2:391:13 | snappyReader | provenance | | | test.go:387:18:387:48 | call to NewReader | test.go:392:2:392:13 | snappyReader | provenance | | @@ -158,8 +158,8 @@ edges | test.go:387:44:387:47 | file | test.go:387:18:387:48 | call to NewReader | provenance | Config | | test.go:393:12:393:38 | call to NewReader | test.go:395:18:395:24 | tarRead | provenance | | | test.go:393:26:393:37 | snappyReader | test.go:393:12:393:38 | call to NewReader | provenance | MaD:3 | -| test.go:395:18:395:24 | tarRead | test.go:611:22:611:28 | SSA def(tarRead) | provenance | | -| test.go:412:9:412:12 | SSA def(file) | test.go:415:27:415:30 | file | provenance | | +| test.go:395:18:395:24 | tarRead | test.go:611:22:611:28 | SSA param(tarRead) | provenance | | +| test.go:412:9:412:12 | SSA param(file) | test.go:415:27:415:30 | file | provenance | | | test.go:415:14:415:31 | call to NewReader | test.go:417:2:417:9 | s2Reader | provenance | | | test.go:415:14:415:31 | call to NewReader | test.go:418:2:418:9 | s2Reader | provenance | | | test.go:415:14:415:31 | call to NewReader | test.go:420:2:420:9 | s2Reader | provenance | | @@ -167,35 +167,35 @@ edges | test.go:415:27:415:30 | file | test.go:415:14:415:31 | call to NewReader | provenance | Config | | test.go:421:12:421:34 | call to NewReader | test.go:423:18:423:24 | tarRead | provenance | | | test.go:421:26:421:33 | s2Reader | test.go:421:12:421:34 | call to NewReader | provenance | MaD:3 | -| test.go:423:18:423:24 | tarRead | test.go:611:22:611:28 | SSA def(tarRead) | provenance | | -| test.go:440:19:440:21 | SSA def(src) | test.go:441:34:441:36 | src | provenance | | +| test.go:423:18:423:24 | tarRead | test.go:611:22:611:28 | SSA param(tarRead) | provenance | | +| test.go:440:19:440:21 | SSA param(src) | test.go:441:34:441:36 | src | provenance | | | test.go:441:2:441:37 | extract:0 ... := ... | test.go:444:12:444:32 | type conversion | provenance | | | test.go:441:34:441:36 | src | test.go:441:2:441:37 | extract:0 ... := ... | provenance | Config | | test.go:444:12:444:32 | type conversion | test.go:445:23:445:28 | newSrc | provenance | | -| test.go:447:11:447:14 | SSA def(file) | test.go:450:34:450:37 | file | provenance | | +| test.go:447:11:447:14 | SSA param(file) | test.go:450:34:450:37 | file | provenance | | | test.go:450:2:450:38 | extract:0 ... := ... | test.go:452:2:452:11 | gzipReader | provenance | | | test.go:450:2:450:38 | extract:0 ... := ... | test.go:453:26:453:35 | gzipReader | provenance | | | test.go:450:34:450:37 | file | test.go:450:2:450:38 | extract:0 ... := ... | provenance | Config | | test.go:453:12:453:36 | call to NewReader | test.go:455:18:455:24 | tarRead | provenance | | | test.go:453:26:453:35 | gzipReader | test.go:453:12:453:36 | call to NewReader | provenance | MaD:3 | -| test.go:455:18:455:24 | tarRead | test.go:611:22:611:28 | SSA def(tarRead) | provenance | | -| test.go:472:20:472:23 | SSA def(file) | test.go:475:43:475:46 | file | provenance | | +| test.go:455:18:455:24 | tarRead | test.go:611:22:611:28 | SSA param(tarRead) | provenance | | +| test.go:472:20:472:23 | SSA param(file) | test.go:475:43:475:46 | file | provenance | | | test.go:475:2:475:47 | extract:0 ... := ... | test.go:477:2:477:11 | gzipReader | provenance | | | test.go:475:2:475:47 | extract:0 ... := ... | test.go:479:2:479:11 | gzipReader | provenance | | | test.go:475:2:475:47 | extract:0 ... := ... | test.go:480:26:480:35 | gzipReader | provenance | | | test.go:475:43:475:46 | file | test.go:475:2:475:47 | extract:0 ... := ... | provenance | Config | | test.go:480:12:480:36 | call to NewReader | test.go:482:18:482:24 | tarRead | provenance | | | test.go:480:26:480:35 | gzipReader | test.go:480:12:480:36 | call to NewReader | provenance | MaD:3 | -| test.go:482:18:482:24 | tarRead | test.go:611:22:611:28 | SSA def(tarRead) | provenance | | -| test.go:499:20:499:23 | SSA def(file) | test.go:502:45:502:48 | file | provenance | | +| test.go:482:18:482:24 | tarRead | test.go:611:22:611:28 | SSA param(tarRead) | provenance | | +| test.go:499:20:499:23 | SSA param(file) | test.go:502:45:502:48 | file | provenance | | | test.go:502:2:502:49 | extract:0 ... := ... | test.go:504:2:504:12 | pgzipReader | provenance | | | test.go:502:2:502:49 | extract:0 ... := ... | test.go:506:2:506:12 | pgzipReader | provenance | | | test.go:502:2:502:49 | extract:0 ... := ... | test.go:507:26:507:36 | pgzipReader | provenance | | | test.go:502:45:502:48 | file | test.go:502:2:502:49 | extract:0 ... := ... | provenance | Config | | test.go:507:12:507:37 | call to NewReader | test.go:509:18:509:24 | tarRead | provenance | | | test.go:507:26:507:36 | pgzipReader | test.go:507:12:507:37 | call to NewReader | provenance | MaD:3 | -| test.go:509:18:509:24 | tarRead | test.go:611:22:611:28 | SSA def(tarRead) | provenance | | -| test.go:526:21:526:24 | SSA def(file) | test.go:529:43:529:46 | file | provenance | | +| test.go:509:18:509:24 | tarRead | test.go:611:22:611:28 | SSA param(tarRead) | provenance | | +| test.go:526:21:526:24 | SSA param(file) | test.go:529:43:529:46 | file | provenance | | | test.go:529:2:529:47 | extract:0 ... := ... | test.go:531:2:531:11 | zstdReader | provenance | | | test.go:529:2:529:47 | extract:0 ... := ... | test.go:533:2:533:11 | zstdReader | provenance | | | test.go:529:2:529:47 | extract:0 ... := ... | test.go:535:2:535:11 | zstdReader | provenance | | @@ -203,33 +203,33 @@ edges | test.go:529:43:529:46 | file | test.go:529:2:529:47 | extract:0 ... := ... | provenance | Config | | test.go:536:12:536:36 | call to NewReader | test.go:538:18:538:24 | tarRead | provenance | | | test.go:536:26:536:35 | zstdReader | test.go:536:12:536:36 | call to NewReader | provenance | MaD:3 | -| test.go:538:18:538:24 | tarRead | test.go:611:22:611:28 | SSA def(tarRead) | provenance | | -| test.go:555:19:555:22 | SSA def(file) | test.go:558:38:558:41 | file | provenance | | +| test.go:538:18:538:24 | tarRead | test.go:611:22:611:28 | SSA param(tarRead) | provenance | | +| test.go:555:19:555:22 | SSA param(file) | test.go:558:38:558:41 | file | provenance | | | test.go:558:16:558:42 | call to NewReader | test.go:560:2:560:11 | zstdReader | provenance | | | test.go:558:16:558:42 | call to NewReader | test.go:561:26:561:35 | zstdReader | provenance | | | test.go:558:38:558:41 | file | test.go:558:16:558:42 | call to NewReader | provenance | Config | | test.go:561:12:561:36 | call to NewReader | test.go:563:18:563:24 | tarRead | provenance | | | test.go:561:26:561:35 | zstdReader | test.go:561:12:561:36 | call to NewReader | provenance | MaD:3 | -| test.go:563:18:563:24 | tarRead | test.go:611:22:611:28 | SSA def(tarRead) | provenance | | -| test.go:580:9:580:12 | SSA def(file) | test.go:583:30:583:33 | file | provenance | | +| test.go:563:18:563:24 | tarRead | test.go:611:22:611:28 | SSA param(tarRead) | provenance | | +| test.go:580:9:580:12 | SSA param(file) | test.go:583:30:583:33 | file | provenance | | | test.go:583:2:583:34 | extract:0 ... := ... | test.go:585:2:585:9 | xzReader | provenance | | | test.go:583:2:583:34 | extract:0 ... := ... | test.go:586:26:586:33 | xzReader | provenance | | | test.go:583:30:583:33 | file | test.go:583:2:583:34 | extract:0 ... := ... | provenance | Config | | test.go:586:12:586:34 | call to NewReader | test.go:589:18:589:24 | tarRead | provenance | | | test.go:586:12:586:34 | call to NewReader | test.go:590:19:590:25 | tarRead | provenance | | | test.go:586:26:586:33 | xzReader | test.go:586:12:586:34 | call to NewReader | provenance | MaD:3 | -| test.go:589:18:589:24 | tarRead | test.go:611:22:611:28 | SSA def(tarRead) | provenance | | -| test.go:590:19:590:25 | tarRead | test.go:627:23:627:29 | SSA def(tarRead) | provenance | | -| test.go:611:22:611:28 | SSA def(tarRead) | test.go:621:25:621:31 | tarRead | provenance | | -| test.go:611:22:611:28 | SSA def(tarRead) | test.go:621:25:621:31 | tarRead | provenance | | -| test.go:611:22:611:28 | SSA def(tarRead) | test.go:621:25:621:31 | tarRead | provenance | | -| test.go:611:22:611:28 | SSA def(tarRead) | test.go:621:25:621:31 | tarRead | provenance | | -| test.go:611:22:611:28 | SSA def(tarRead) | test.go:621:25:621:31 | tarRead | provenance | | -| test.go:611:22:611:28 | SSA def(tarRead) | test.go:621:25:621:31 | tarRead | provenance | | -| test.go:611:22:611:28 | SSA def(tarRead) | test.go:621:25:621:31 | tarRead | provenance | | -| test.go:611:22:611:28 | SSA def(tarRead) | test.go:621:25:621:31 | tarRead | provenance | | -| test.go:611:22:611:28 | SSA def(tarRead) | test.go:621:25:621:31 | tarRead | provenance | | -| test.go:627:23:627:29 | SSA def(tarRead) | test.go:629:2:629:8 | tarRead | provenance | | +| test.go:589:18:589:24 | tarRead | test.go:611:22:611:28 | SSA param(tarRead) | provenance | | +| test.go:590:19:590:25 | tarRead | test.go:627:23:627:29 | SSA param(tarRead) | provenance | | +| test.go:611:22:611:28 | SSA param(tarRead) | test.go:621:25:621:31 | tarRead | provenance | | +| test.go:611:22:611:28 | SSA param(tarRead) | test.go:621:25:621:31 | tarRead | provenance | | +| test.go:611:22:611:28 | SSA param(tarRead) | test.go:621:25:621:31 | tarRead | provenance | | +| test.go:611:22:611:28 | SSA param(tarRead) | test.go:621:25:621:31 | tarRead | provenance | | +| test.go:611:22:611:28 | SSA param(tarRead) | test.go:621:25:621:31 | tarRead | provenance | | +| test.go:611:22:611:28 | SSA param(tarRead) | test.go:621:25:621:31 | tarRead | provenance | | +| test.go:611:22:611:28 | SSA param(tarRead) | test.go:621:25:621:31 | tarRead | provenance | | +| test.go:611:22:611:28 | SSA param(tarRead) | test.go:621:25:621:31 | tarRead | provenance | | +| test.go:611:22:611:28 | SSA param(tarRead) | test.go:621:25:621:31 | tarRead | provenance | | +| test.go:627:23:627:29 | SSA param(tarRead) | test.go:629:2:629:8 | tarRead | provenance | | models | 1 | Source: net/http; Request; true; Body; ; ; ; remote; manual | | 2 | Source: net/http; Request; true; FormValue; ; ; ReturnValue; remote; manual | @@ -258,7 +258,7 @@ nodes | test.go:89:17:89:28 | selection of Body | semmle.label | selection of Body | | test.go:91:15:91:26 | selection of Body | semmle.label | selection of Body | | test.go:93:5:93:16 | selection of Body | semmle.label | selection of Body | -| test.go:128:20:128:27 | SSA def(filename) | semmle.label | SSA def(filename) | +| test.go:128:20:128:27 | SSA param(filename) | semmle.label | SSA param(filename) | | test.go:130:2:130:41 | extract:0 ... := ... | semmle.label | extract:0 ... := ... | | test.go:130:33:130:40 | filename | semmle.label | filename | | test.go:132:3:132:19 | extract:0 ... := ... | semmle.label | extract:0 ... := ... | @@ -269,7 +269,7 @@ nodes | test.go:145:12:145:12 | f | semmle.label | f | | test.go:145:12:145:19 | call to Open | semmle.label | call to Open | | test.go:147:37:147:38 | rc | semmle.label | rc | -| test.go:158:19:158:22 | SSA def(file) | semmle.label | SSA def(file) | +| test.go:158:19:158:22 | SSA param(file) | semmle.label | SSA param(file) | | test.go:159:2:159:29 | extract:0 ... := ... | semmle.label | extract:0 ... := ... | | test.go:159:25:159:28 | file | semmle.label | file | | test.go:160:2:160:69 | extract:0 ... := ... | semmle.label | extract:0 ... := ... | @@ -278,7 +278,7 @@ nodes | test.go:163:3:163:36 | extract:0 ... := ... | semmle.label | extract:0 ... := ... | | test.go:163:26:163:29 | file | semmle.label | file | | test.go:164:36:164:51 | fileReaderCloser | semmle.label | fileReaderCloser | -| test.go:169:28:169:31 | SSA def(file) | semmle.label | SSA def(file) | +| test.go:169:28:169:31 | SSA param(file) | semmle.label | SSA param(file) | | test.go:170:2:170:29 | extract:0 ... := ... | semmle.label | extract:0 ... := ... | | test.go:170:25:170:28 | file | semmle.label | file | | test.go:171:2:171:78 | extract:0 ... := ... | semmle.label | extract:0 ... := ... | @@ -287,56 +287,56 @@ nodes | test.go:175:26:175:29 | file | semmle.label | file | | test.go:175:26:175:36 | call to Open | semmle.label | call to Open | | test.go:176:36:176:51 | fileReaderCloser | semmle.label | fileReaderCloser | -| test.go:181:17:181:20 | SSA def(file) | semmle.label | SSA def(file) | +| test.go:181:17:181:20 | SSA param(file) | semmle.label | SSA param(file) | | test.go:184:2:184:73 | extract:0 ... := ... | semmle.label | extract:0 ... := ... | | test.go:184:41:184:44 | file | semmle.label | file | | test.go:186:2:186:12 | bzip2Reader | semmle.label | bzip2Reader | | test.go:187:12:187:37 | call to NewReader | semmle.label | call to NewReader | | test.go:187:26:187:36 | bzip2Reader | semmle.label | bzip2Reader | | test.go:189:18:189:24 | tarRead | semmle.label | tarRead | -| test.go:208:12:208:15 | SSA def(file) | semmle.label | SSA def(file) | +| test.go:208:12:208:15 | SSA param(file) | semmle.label | SSA param(file) | | test.go:211:17:211:37 | call to NewReader | semmle.label | call to NewReader | | test.go:211:33:211:36 | file | semmle.label | file | | test.go:213:2:213:12 | bzip2Reader | semmle.label | bzip2Reader | | test.go:214:12:214:37 | call to NewReader | semmle.label | call to NewReader | | test.go:214:26:214:36 | bzip2Reader | semmle.label | bzip2Reader | | test.go:216:18:216:24 | tarRead | semmle.label | tarRead | -| test.go:233:12:233:15 | SSA def(file) | semmle.label | SSA def(file) | +| test.go:233:12:233:15 | SSA param(file) | semmle.label | SSA param(file) | | test.go:236:17:236:37 | call to NewReader | semmle.label | call to NewReader | | test.go:236:33:236:36 | file | semmle.label | file | | test.go:238:2:238:12 | flateReader | semmle.label | flateReader | | test.go:239:12:239:37 | call to NewReader | semmle.label | call to NewReader | | test.go:239:26:239:36 | flateReader | semmle.label | flateReader | | test.go:241:18:241:24 | tarRead | semmle.label | tarRead | -| test.go:258:21:258:24 | SSA def(file) | semmle.label | SSA def(file) | +| test.go:258:21:258:24 | SSA param(file) | semmle.label | SSA param(file) | | test.go:261:17:261:46 | call to NewReader | semmle.label | call to NewReader | | test.go:261:42:261:45 | file | semmle.label | file | | test.go:263:2:263:12 | flateReader | semmle.label | flateReader | | test.go:264:12:264:37 | call to NewReader | semmle.label | call to NewReader | | test.go:264:26:264:36 | flateReader | semmle.label | flateReader | | test.go:266:18:266:24 | tarRead | semmle.label | tarRead | -| test.go:283:17:283:20 | SSA def(file) | semmle.label | SSA def(file) | +| test.go:283:17:283:20 | SSA param(file) | semmle.label | SSA param(file) | | test.go:286:2:286:73 | extract:0 ... := ... | semmle.label | extract:0 ... := ... | | test.go:286:41:286:44 | file | semmle.label | file | | test.go:288:2:288:12 | flateReader | semmle.label | flateReader | | test.go:289:12:289:37 | call to NewReader | semmle.label | call to NewReader | | test.go:289:26:289:36 | flateReader | semmle.label | flateReader | | test.go:291:18:291:24 | tarRead | semmle.label | tarRead | -| test.go:308:20:308:23 | SSA def(file) | semmle.label | SSA def(file) | +| test.go:308:20:308:23 | SSA param(file) | semmle.label | SSA param(file) | | test.go:311:2:311:47 | extract:0 ... := ... | semmle.label | extract:0 ... := ... | | test.go:311:43:311:46 | file | semmle.label | file | | test.go:313:2:313:11 | zlibReader | semmle.label | zlibReader | | test.go:314:12:314:36 | call to NewReader | semmle.label | call to NewReader | | test.go:314:26:314:35 | zlibReader | semmle.label | zlibReader | | test.go:316:18:316:24 | tarRead | semmle.label | tarRead | -| test.go:333:11:333:14 | SSA def(file) | semmle.label | SSA def(file) | +| test.go:333:11:333:14 | SSA param(file) | semmle.label | SSA param(file) | | test.go:336:2:336:38 | extract:0 ... := ... | semmle.label | extract:0 ... := ... | | test.go:336:34:336:37 | file | semmle.label | file | | test.go:338:2:338:11 | zlibReader | semmle.label | zlibReader | | test.go:339:12:339:36 | call to NewReader | semmle.label | call to NewReader | | test.go:339:26:339:35 | zlibReader | semmle.label | zlibReader | | test.go:341:18:341:24 | tarRead | semmle.label | tarRead | -| test.go:358:13:358:16 | SSA def(file) | semmle.label | SSA def(file) | +| test.go:358:13:358:16 | SSA param(file) | semmle.label | SSA param(file) | | test.go:361:18:361:39 | call to NewReader | semmle.label | call to NewReader | | test.go:361:35:361:38 | file | semmle.label | file | | test.go:363:2:363:13 | snappyReader | semmle.label | snappyReader | @@ -344,7 +344,7 @@ nodes | test.go:365:12:365:38 | call to NewReader | semmle.label | call to NewReader | | test.go:365:26:365:37 | snappyReader | semmle.label | snappyReader | | test.go:367:18:367:24 | tarRead | semmle.label | tarRead | -| test.go:384:22:384:25 | SSA def(file) | semmle.label | SSA def(file) | +| test.go:384:22:384:25 | SSA param(file) | semmle.label | SSA param(file) | | test.go:387:18:387:48 | call to NewReader | semmle.label | call to NewReader | | test.go:387:44:387:47 | file | semmle.label | file | | test.go:389:2:389:13 | snappyReader | semmle.label | snappyReader | @@ -353,7 +353,7 @@ nodes | test.go:393:12:393:38 | call to NewReader | semmle.label | call to NewReader | | test.go:393:26:393:37 | snappyReader | semmle.label | snappyReader | | test.go:395:18:395:24 | tarRead | semmle.label | tarRead | -| test.go:412:9:412:12 | SSA def(file) | semmle.label | SSA def(file) | +| test.go:412:9:412:12 | SSA param(file) | semmle.label | SSA param(file) | | test.go:415:14:415:31 | call to NewReader | semmle.label | call to NewReader | | test.go:415:27:415:30 | file | semmle.label | file | | test.go:417:2:417:9 | s2Reader | semmle.label | s2Reader | @@ -362,19 +362,19 @@ nodes | test.go:421:12:421:34 | call to NewReader | semmle.label | call to NewReader | | test.go:421:26:421:33 | s2Reader | semmle.label | s2Reader | | test.go:423:18:423:24 | tarRead | semmle.label | tarRead | -| test.go:440:19:440:21 | SSA def(src) | semmle.label | SSA def(src) | +| test.go:440:19:440:21 | SSA param(src) | semmle.label | SSA param(src) | | test.go:441:2:441:37 | extract:0 ... := ... | semmle.label | extract:0 ... := ... | | test.go:441:34:441:36 | src | semmle.label | src | | test.go:444:12:444:32 | type conversion | semmle.label | type conversion | | test.go:445:23:445:28 | newSrc | semmle.label | newSrc | -| test.go:447:11:447:14 | SSA def(file) | semmle.label | SSA def(file) | +| test.go:447:11:447:14 | SSA param(file) | semmle.label | SSA param(file) | | test.go:450:2:450:38 | extract:0 ... := ... | semmle.label | extract:0 ... := ... | | test.go:450:34:450:37 | file | semmle.label | file | | test.go:452:2:452:11 | gzipReader | semmle.label | gzipReader | | test.go:453:12:453:36 | call to NewReader | semmle.label | call to NewReader | | test.go:453:26:453:35 | gzipReader | semmle.label | gzipReader | | test.go:455:18:455:24 | tarRead | semmle.label | tarRead | -| test.go:472:20:472:23 | SSA def(file) | semmle.label | SSA def(file) | +| test.go:472:20:472:23 | SSA param(file) | semmle.label | SSA param(file) | | test.go:475:2:475:47 | extract:0 ... := ... | semmle.label | extract:0 ... := ... | | test.go:475:43:475:46 | file | semmle.label | file | | test.go:477:2:477:11 | gzipReader | semmle.label | gzipReader | @@ -382,7 +382,7 @@ nodes | test.go:480:12:480:36 | call to NewReader | semmle.label | call to NewReader | | test.go:480:26:480:35 | gzipReader | semmle.label | gzipReader | | test.go:482:18:482:24 | tarRead | semmle.label | tarRead | -| test.go:499:20:499:23 | SSA def(file) | semmle.label | SSA def(file) | +| test.go:499:20:499:23 | SSA param(file) | semmle.label | SSA param(file) | | test.go:502:2:502:49 | extract:0 ... := ... | semmle.label | extract:0 ... := ... | | test.go:502:45:502:48 | file | semmle.label | file | | test.go:504:2:504:12 | pgzipReader | semmle.label | pgzipReader | @@ -390,7 +390,7 @@ nodes | test.go:507:12:507:37 | call to NewReader | semmle.label | call to NewReader | | test.go:507:26:507:36 | pgzipReader | semmle.label | pgzipReader | | test.go:509:18:509:24 | tarRead | semmle.label | tarRead | -| test.go:526:21:526:24 | SSA def(file) | semmle.label | SSA def(file) | +| test.go:526:21:526:24 | SSA param(file) | semmle.label | SSA param(file) | | test.go:529:2:529:47 | extract:0 ... := ... | semmle.label | extract:0 ... := ... | | test.go:529:43:529:46 | file | semmle.label | file | | test.go:531:2:531:11 | zstdReader | semmle.label | zstdReader | @@ -399,14 +399,14 @@ nodes | test.go:536:12:536:36 | call to NewReader | semmle.label | call to NewReader | | test.go:536:26:536:35 | zstdReader | semmle.label | zstdReader | | test.go:538:18:538:24 | tarRead | semmle.label | tarRead | -| test.go:555:19:555:22 | SSA def(file) | semmle.label | SSA def(file) | +| test.go:555:19:555:22 | SSA param(file) | semmle.label | SSA param(file) | | test.go:558:16:558:42 | call to NewReader | semmle.label | call to NewReader | | test.go:558:38:558:41 | file | semmle.label | file | | test.go:560:2:560:11 | zstdReader | semmle.label | zstdReader | | test.go:561:12:561:36 | call to NewReader | semmle.label | call to NewReader | | test.go:561:26:561:35 | zstdReader | semmle.label | zstdReader | | test.go:563:18:563:24 | tarRead | semmle.label | tarRead | -| test.go:580:9:580:12 | SSA def(file) | semmle.label | SSA def(file) | +| test.go:580:9:580:12 | SSA param(file) | semmle.label | SSA param(file) | | test.go:583:2:583:34 | extract:0 ... := ... | semmle.label | extract:0 ... := ... | | test.go:583:30:583:33 | file | semmle.label | file | | test.go:585:2:585:9 | xzReader | semmle.label | xzReader | @@ -414,15 +414,15 @@ nodes | test.go:586:26:586:33 | xzReader | semmle.label | xzReader | | test.go:589:18:589:24 | tarRead | semmle.label | tarRead | | test.go:590:19:590:25 | tarRead | semmle.label | tarRead | -| test.go:611:22:611:28 | SSA def(tarRead) | semmle.label | SSA def(tarRead) | -| test.go:611:22:611:28 | SSA def(tarRead) | semmle.label | SSA def(tarRead) | -| test.go:611:22:611:28 | SSA def(tarRead) | semmle.label | SSA def(tarRead) | -| test.go:611:22:611:28 | SSA def(tarRead) | semmle.label | SSA def(tarRead) | -| test.go:611:22:611:28 | SSA def(tarRead) | semmle.label | SSA def(tarRead) | -| test.go:611:22:611:28 | SSA def(tarRead) | semmle.label | SSA def(tarRead) | -| test.go:611:22:611:28 | SSA def(tarRead) | semmle.label | SSA def(tarRead) | -| test.go:611:22:611:28 | SSA def(tarRead) | semmle.label | SSA def(tarRead) | -| test.go:611:22:611:28 | SSA def(tarRead) | semmle.label | SSA def(tarRead) | +| test.go:611:22:611:28 | SSA param(tarRead) | semmle.label | SSA param(tarRead) | +| test.go:611:22:611:28 | SSA param(tarRead) | semmle.label | SSA param(tarRead) | +| test.go:611:22:611:28 | SSA param(tarRead) | semmle.label | SSA param(tarRead) | +| test.go:611:22:611:28 | SSA param(tarRead) | semmle.label | SSA param(tarRead) | +| test.go:611:22:611:28 | SSA param(tarRead) | semmle.label | SSA param(tarRead) | +| test.go:611:22:611:28 | SSA param(tarRead) | semmle.label | SSA param(tarRead) | +| test.go:611:22:611:28 | SSA param(tarRead) | semmle.label | SSA param(tarRead) | +| test.go:611:22:611:28 | SSA param(tarRead) | semmle.label | SSA param(tarRead) | +| test.go:611:22:611:28 | SSA param(tarRead) | semmle.label | SSA param(tarRead) | | test.go:621:25:621:31 | tarRead | semmle.label | tarRead | | test.go:621:25:621:31 | tarRead | semmle.label | tarRead | | test.go:621:25:621:31 | tarRead | semmle.label | tarRead | @@ -432,6 +432,6 @@ nodes | test.go:621:25:621:31 | tarRead | semmle.label | tarRead | | test.go:621:25:621:31 | tarRead | semmle.label | tarRead | | test.go:621:25:621:31 | tarRead | semmle.label | tarRead | -| test.go:627:23:627:29 | SSA def(tarRead) | semmle.label | SSA def(tarRead) | +| test.go:627:23:627:29 | SSA param(tarRead) | semmle.label | SSA param(tarRead) | | test.go:629:2:629:8 | tarRead | semmle.label | tarRead | subpaths diff --git a/go/ql/test/experimental/Unsafe/WrongUsageOfUnsafe.expected b/go/ql/test/experimental/Unsafe/WrongUsageOfUnsafe.expected index 728d0b54da85..535b6364eb48 100644 --- a/go/ql/test/experimental/Unsafe/WrongUsageOfUnsafe.expected +++ b/go/ql/test/experimental/Unsafe/WrongUsageOfUnsafe.expected @@ -22,8 +22,8 @@ edges | 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: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:21:236:23 | SSA def(req) | provenance | | -| WrongUsageOfUnsafe.go:236:21:236:23 | SSA def(req) | WrongUsageOfUnsafe.go:243:9:243:27 | type conversion | provenance | | +| WrongUsageOfUnsafe.go:227:31:227:55 | type conversion | WrongUsageOfUnsafe.go:236:21:236:23 | SSA param(req) | provenance | | +| WrongUsageOfUnsafe.go:236:21:236:23 | SSA param(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: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 | | @@ -51,7 +51,7 @@ nodes | 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:227:31:227:55 | type conversion | semmle.label | type conversion | -| WrongUsageOfUnsafe.go:236:21:236:23 | SSA def(req) | semmle.label | SSA def(req) | +| WrongUsageOfUnsafe.go:236:21:236:23 | SSA param(req) | semmle.label | SSA param(req) | | 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:28:256:52 | type conversion | semmle.label | type conversion | diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalTaintFlow/srcs.expected b/go/ql/test/library-tests/semmle/go/dataflow/ExternalTaintFlow/srcs.expected index f446be1e266b..93651471379b 100644 --- a/go/ql/test/library-tests/semmle/go/dataflow/ExternalTaintFlow/srcs.expected +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalTaintFlow/srcs.expected @@ -22,4 +22,4 @@ invalidModelRow | test.go:187:24:187:31 | call to Src1 | qltest | | test.go:191:24:191:31 | call to Src1 | qltest | | test.go:201:10:201:28 | selection of SourceVariable | qltest | -| test.go:208:15:208:17 | SSA def(src) | qltest | +| test.go:208:15:208:17 | SSA param(src) | qltest | diff --git a/go/ql/test/library-tests/semmle/go/dataflow/ExternalValueFlow/srcs.expected b/go/ql/test/library-tests/semmle/go/dataflow/ExternalValueFlow/srcs.expected index 6e8870b33803..c3e400ee67b5 100644 --- a/go/ql/test/library-tests/semmle/go/dataflow/ExternalValueFlow/srcs.expected +++ b/go/ql/test/library-tests/semmle/go/dataflow/ExternalValueFlow/srcs.expected @@ -22,4 +22,4 @@ invalidModelRow | test.go:187:24:187: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:216:15:216:17 | SSA def(src) | qltest | +| test.go:216:15:216:17 | SSA param(src) | qltest | diff --git a/go/ql/test/library-tests/semmle/go/dataflow/FlowSteps/LocalFlowStep.expected b/go/ql/test/library-tests/semmle/go/dataflow/FlowSteps/LocalFlowStep.expected index 5c4bd6cfcb2f..3fc51cc6d7ea 100644 --- a/go/ql/test/library-tests/semmle/go/dataflow/FlowSteps/LocalFlowStep.expected +++ b/go/ql/test/library-tests/semmle/go/dataflow/FlowSteps/LocalFlowStep.expected @@ -1,7 +1,7 @@ -| main.go:3:12:3:12 | SSA def(x) | main.go:5:5:5:5 | x | -| main.go:3:12:3:12 | x | main.go:3:12:3:12 | SSA def(x) | -| main.go:3:19:3:20 | SSA def(fn) | main.go:10:24:10:25 | fn | -| main.go:3:19:3:20 | fn | main.go:3:19:3:20 | SSA def(fn) | +| main.go:3:12:3:12 | SSA param(x) | main.go:5:5:5:5 | x | +| main.go:3:12:3:12 | x | main.go:3:12:3:12 | SSA param(x) | +| main.go:3:19:3:20 | SSA param(fn) | main.go:10:24:10:25 | fn | +| main.go:3:19:3:20 | fn | main.go:3:19:3:20 | SSA param(fn) | | main.go:5:5:5:5 | x | main.go:6:7:6:7 | x | | main.go:5:5:5:5 | x | main.go:8:8:8:8 | x | | main.go:6:3:6:7 | SSA def(y) | main.go:10:12:10:12 | y | @@ -18,14 +18,14 @@ | main.go:10:17:10:27 | ...>=... | main.go:10:7:10:27 | After ...&&... | | main.go:11:14:11:14 | z | main.go:11:9:11:15 | type conversion | | main.go:15:9:15:9 | 0 | main.go:15:2:15:9 | SSA def(acc) | -| main.go:16:9:19:2 | SSA def(acc) | main.go:17:3:17:5 | acc | +| main.go:16:9:19:2 | SSA implicit def(acc) | main.go:17:3:17:5 | acc | | main.go:17:3:17:7 | SSA def(acc) | main.go:18:10:18:12 | acc | | main.go:17:3:17:7 | increment statement | main.go:17:3:17:7 | SSA def(acc) | -| main.go:22:12:22:12 | SSA def(b) | main.go:23:5:23:5 | b | -| main.go:22:12:22:12 | b | main.go:22:12:22:12 | SSA def(b) | -| main.go:22:20:22:20 | SSA def(x) | main.go:24:10:24:10 | x | -| main.go:22:20:22:20 | SSA def(x) | main.go:26:11:26:11 | x | -| main.go:22:20:22:20 | x | main.go:22:20:22:20 | SSA def(x) | +| main.go:22:12:22:12 | SSA param(b) | main.go:23:5:23:5 | b | +| main.go:22:12:22:12 | b | main.go:22:12:22:12 | SSA param(b) | +| main.go:22:20:22:20 | SSA param(x) | main.go:24:10:24:10 | x | +| main.go:22:20:22:20 | SSA param(x) | main.go:26:11:26:11 | x | +| main.go:22:20:22:20 | x | main.go:22:20:22:20 | SSA param(x) | | main.go:24:10:24:10 | x | main.go:24:10:24:19 | type assertion | | main.go:26:2:26:17 | SSA def(n) | main.go:27:11:27:11 | n | | main.go:26:2:26:17 | SSA def(ok) | main.go:27:5:27:6 | ok | @@ -45,8 +45,8 @@ | main.go:40:15:40:15 | s [postupdate] | main.go:42:7:42:7 | s | | main.go:41:2:41:21 | SSA def(s4) | main.go:42:10:42:11 | s4 | | main.go:41:8:41:21 | call to make | main.go:41:2:41:21 | SSA def(s4) | -| main.go:46:13:46:14 | SSA def(xs) | main.go:47:20:47:21 | xs | -| main.go:46:13:46:14 | xs | main.go:46:13:46:14 | SSA def(xs) | +| main.go:46:13:46:14 | SSA param(xs) | main.go:47:20:47:21 | xs | +| main.go:46:13:46:14 | xs | main.go:46:13:46:14 | SSA param(xs) | | main.go:46:44:52:1 | SSA def(keys) | main.go:46:44:52:1 | result-read:0 block statement | | main.go:46:44:52:1 | SSA def(keys) | main.go:49:3:49:6 | keys | | main.go:46:44:52:1 | SSA def(vals) | main.go:46:44:52:1 | result-read:1 block statement | @@ -86,8 +86,8 @@ | main.go:65:11:65:11 | x | main.go:65:7:65:18 | call to max | | main.go:65:14:65:14 | y | main.go:65:7:65:18 | call to max | | main.go:65:17:65:17 | z | main.go:65:7:65:18 | call to max | -| strings.go:8:12:8:12 | SSA def(s) | strings.go:9:24:9:24 | s | -| strings.go:8:12:8:12 | s | strings.go:8:12:8:12 | SSA def(s) | +| strings.go:8:12:8:12 | SSA param(s) | strings.go:9:24:9:24 | s | +| strings.go:8:12:8:12 | s | strings.go:8:12:8:12 | SSA param(s) | | strings.go:9:2:9:38 | SSA def(s2) | strings.go:11:20:11:21 | s2 | | strings.go:9:8:9:38 | call to Replace | strings.go:9:2:9:38 | SSA def(s2) | | strings.go:9:24:9:24 | s | strings.go:10:27:10:27 | s | @@ -95,11 +95,11 @@ | strings.go:10:8:10:42 | call to ReplaceAll | strings.go:10:2:10:42 | SSA def(s3) | | strings.go:11:20:11:21 | s2 | strings.go:11:48:11:49 | s2 | | strings.go:11:24:11:25 | s3 | strings.go:11:67:11:68 | s3 | -| url.go:8:12:8:12 | SSA def(b) | url.go:11:5:11:5 | b | -| url.go:8:12:8:12 | b | url.go:8:12:8:12 | SSA def(b) | -| url.go:8:20:8:20 | SSA def(s) | url.go:12:46:12:46 | s | -| url.go:8:20:8:20 | SSA def(s) | url.go:14:48:14:48 | s | -| url.go:8:20:8:20 | s | url.go:8:20:8:20 | SSA def(s) | +| url.go:8:12:8:12 | SSA param(b) | url.go:11:5:11:5 | b | +| url.go:8:12:8:12 | b | url.go:8:12:8:12 | SSA param(b) | +| url.go:8:20:8:20 | SSA param(s) | url.go:12:46:12:46 | s | +| url.go:8:20:8:20 | SSA param(s) | url.go:14:48:14:48 | s | +| url.go:8:20:8:20 | s | url.go:8:20:8:20 | SSA param(s) | | url.go:12:3:12:48 | SSA def(err) | url.go:16:5:16:7 | err | | url.go:12:3:12:48 | SSA def(res) | url.go:19:9:19:11 | res | | url.go:12:3:12:48 | extract:0 ... = ... | url.go:12:3:12:48 | SSA def(res) | @@ -108,10 +108,10 @@ | url.go:14:3:14:50 | SSA def(res) | url.go:19:9:19:11 | res | | url.go:14:3:14:50 | extract:0 ... = ... | url.go:14:3:14:50 | SSA def(res) | | url.go:14:3:14:50 | extract:1 ... = ... | url.go:14:3:14:50 | SSA def(err) | -| url.go:22:12:22:12 | SSA def(i) | url.go:24:5:24:5 | i | -| url.go:22:12:22:12 | i | url.go:22:12:22:12 | SSA def(i) | -| url.go:22:19:22:19 | SSA def(s) | url.go:23:20:23:20 | s | -| url.go:22:19:22:19 | s | url.go:22:19:22:19 | SSA def(s) | +| url.go:22:12:22:12 | SSA param(i) | url.go:24:5:24:5 | i | +| url.go:22:12:22:12 | i | url.go:22:12:22:12 | SSA param(i) | +| url.go:22:19:22:19 | SSA param(s) | url.go:23:20:23:20 | s | +| url.go:22:19:22:19 | s | url.go:22:19:22:19 | SSA param(s) | | url.go:23:2:23:21 | SSA def(u) | url.go:25:10:25:10 | u | | url.go:23:2:23:21 | extract:0 ... := ... | url.go:23:2:23:21 | SSA def(u) | | url.go:23:20:23:20 | s | url.go:27:29:27:29 | s | @@ -145,16 +145,16 @@ | url.go:43:11:43:12 | ui [postupdate] | url.go:45:14:45:15 | ui | | url.go:45:14:45:15 | ui | url.go:46:9:46:10 | ui | | url.go:45:14:45:15 | ui [postupdate] | url.go:46:9:46:10 | ui | -| url.go:49:12:49:12 | SSA def(q) | url.go:50:25:50:25 | q | -| url.go:49:12:49:12 | q | url.go:49:12:49:12 | SSA def(q) | +| url.go:49:12:49:12 | SSA param(q) | url.go:50:25:50:25 | q | +| url.go:49:12:49:12 | q | url.go:49:12:49:12 | SSA param(q) | | url.go:50:2:50:26 | SSA def(v) | url.go:51:14:51:14 | v | | url.go:50:2:50:26 | extract:0 ... := ... | url.go:50:2:50:26 | SSA def(v) | | url.go:51:14:51:14 | v | url.go:52:14:52:14 | v | | url.go:51:14:51:14 | v [postupdate] | url.go:52:14:52:14 | v | | url.go:52:14:52:14 | v | url.go:53:9:53:9 | v | | url.go:52:14:52:14 | v [postupdate] | url.go:53:9:53:9 | v | -| url.go:56:12:56:12 | SSA def(q) | url.go:57:29:57:29 | q | -| url.go:56:12:56:12 | q | url.go:56:12:56:12 | SSA def(q) | +| url.go:56:12:56:12 | SSA param(q) | url.go:57:29:57:29 | q | +| url.go:56:12:56:12 | q | url.go:56:12:56:12 | SSA param(q) | | url.go:57:2:57:39 | SSA def(joined1) | url.go:58:38:58:44 | joined1 | | url.go:57:2:57:39 | extract:0 ... := ... | url.go:57:2:57:39 | SSA def(joined1) | | url.go:58:2:58:45 | SSA def(joined2) | url.go:59:24:59:30 | joined2 | @@ -163,7 +163,7 @@ | url.go:59:2:59:31 | extract:0 ... := ... | url.go:59:2:59:31 | SSA def(asUrl) | | url.go:60:2:60:37 | SSA def(joinedUrl) | url.go:61:9:61:17 | joinedUrl | | url.go:60:15:60:37 | call to JoinPath | url.go:60:2:60:37 | SSA def(joinedUrl) | -| url.go:64:13:64:13 | SSA def(q) | url.go:66:27:66:27 | q | -| url.go:64:13:64:13 | q | url.go:64:13:64:13 | SSA def(q) | +| url.go:64:13:64:13 | SSA param(q) | url.go:66:27:66:27 | q | +| url.go:64:13:64:13 | q | url.go:64:13:64:13 | SSA param(q) | | url.go:65:2:65:48 | SSA def(cleanUrl) | url.go:66:9:66:16 | cleanUrl | | url.go:65:2:65:48 | extract:0 ... := ... | url.go:65:2:65:48 | SSA def(cleanUrl) | diff --git a/go/ql/test/library-tests/semmle/go/dataflow/FunctionInputsAndOutputs/FunctionInput_getExitNode.expected b/go/ql/test/library-tests/semmle/go/dataflow/FunctionInputsAndOutputs/FunctionInput_getExitNode.expected index c62d1a1fc231..3e8800501658 100644 --- a/go/ql/test/library-tests/semmle/go/dataflow/FunctionInputsAndOutputs/FunctionInput_getExitNode.expected +++ b/go/ql/test/library-tests/semmle/go/dataflow/FunctionInputsAndOutputs/FunctionInput_getExitNode.expected @@ -1,14 +1,14 @@ -| parameter 0 | main.go:5:1:11:1 | function declaration | main.go:5:9:5:10 | SSA def(op) | -| parameter 0 | main.go:13:1:20:1 | function declaration | main.go:13:10:13:11 | SSA def(op) | -| parameter 0 | main.go:40:1:48:1 | function declaration | main.go:40:12:40:12 | SSA def(b) | -| parameter 0 | reset.go:8:1:16:1 | function declaration | reset.go:8:27:8:27 | SSA def(r) | -| parameter 0 | tst2.go:8:1:12:1 | function declaration | tst2.go:8:12:8:15 | SSA def(data) | -| parameter 0 | tst.go:8:1:11:1 | function declaration | tst.go:8:12:8:17 | SSA def(reader) | +| parameter 0 | main.go:5:1:11:1 | function declaration | main.go:5:9:5:10 | SSA param(op) | +| parameter 0 | main.go:13:1:20:1 | function declaration | main.go:13:10:13:11 | SSA param(op) | +| parameter 0 | main.go:40:1:48:1 | function declaration | main.go:40:12:40:12 | SSA param(b) | +| parameter 0 | reset.go:8:1:16:1 | function declaration | reset.go:8:27:8:27 | SSA param(r) | +| parameter 0 | tst2.go:8:1:12:1 | function declaration | tst2.go:8:12:8:15 | SSA param(data) | +| parameter 0 | tst.go:8:1:11:1 | function declaration | tst.go:8:12:8:17 | SSA param(reader) | | parameter 0 | tst.go:13:1:13:25 | function declaration | tst.go:13:12:13:13 | xs | -| parameter 0 | tst.go:15:1:19:1 | function declaration | tst.go:15:12:15:12 | SSA def(x) | -| parameter 1 | main.go:5:1:11:1 | function declaration | main.go:5:20:5:20 | SSA def(x) | -| parameter 1 | main.go:13:1:20:1 | function declaration | main.go:13:21:13:21 | SSA def(x) | -| parameter 1 | tst.go:15:1:19:1 | function declaration | tst.go:15:15:15:15 | SSA def(y) | -| parameter 2 | main.go:5:1:11:1 | function declaration | main.go:5:27:5:27 | SSA def(y) | -| parameter 2 | main.go:13:1:20:1 | function declaration | main.go:13:28:13:28 | SSA def(y) | -| receiver | main.go:26:1:29:1 | function declaration | main.go:26:7:26:7 | SSA def(c) | +| parameter 0 | tst.go:15:1:19:1 | function declaration | tst.go:15:12:15:12 | SSA param(x) | +| parameter 1 | main.go:5:1:11:1 | function declaration | main.go:5:20:5:20 | SSA param(x) | +| parameter 1 | main.go:13:1:20:1 | function declaration | main.go:13:21:13:21 | SSA param(x) | +| parameter 1 | tst.go:15:1:19:1 | function declaration | tst.go:15:15:15:15 | SSA param(y) | +| parameter 2 | main.go:5:1:11:1 | function declaration | main.go:5:27:5:27 | SSA param(y) | +| parameter 2 | main.go:13:1:20:1 | function declaration | main.go:13:28:13:28 | SSA param(y) | +| receiver | main.go:26:1:29:1 | function declaration | main.go:26:7:26:7 | SSA param(c) | diff --git a/go/ql/test/library-tests/semmle/go/frameworks/Beego/CleartextLogging.expected b/go/ql/test/library-tests/semmle/go/frameworks/Beego/CleartextLogging.expected index 76c71bdea206..ac84466da936 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/Beego/CleartextLogging.expected +++ b/go/ql/test/library-tests/semmle/go/frameworks/Beego/CleartextLogging.expected @@ -1,73 +1,73 @@ #select -| test.go:154:14:154:21 | password | test.go:153:17:153:24 | SSA def(password) | test.go:154:14:154:21 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA def(password) | Sensitive data returned by an access to password | -| test.go:155:17:155:24 | password | test.go:153:17:153:24 | SSA def(password) | test.go:155:17:155:24 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA def(password) | Sensitive data returned by an access to password | -| test.go:156:14:156:21 | password | test.go:153:17:153:24 | SSA def(password) | test.go:156:14:156:21 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA def(password) | Sensitive data returned by an access to password | -| test.go:157:18:157:25 | password | test.go:153:17:153:24 | SSA def(password) | test.go:157:18:157:25 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA def(password) | Sensitive data returned by an access to password | -| test.go:158:14:158:21 | password | test.go:153:17:153:24 | SSA def(password) | test.go:158:14:158:21 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA def(password) | Sensitive data returned by an access to password | -| test.go:159:13:159:20 | password | test.go:153:17:153:24 | SSA def(password) | test.go:159:13:159:20 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA def(password) | Sensitive data returned by an access to password | -| test.go:160:22:160:29 | password | test.go:153:17:153:24 | SSA def(password) | test.go:160:22:160:29 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA def(password) | Sensitive data returned by an access to password | -| test.go:161:15:161:22 | password | test.go:153:17:153:24 | SSA def(password) | test.go:161:15:161:22 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA def(password) | Sensitive data returned by an access to password | -| test.go:162:14:162:21 | password | test.go:153:17:153:24 | SSA def(password) | test.go:162:14:162:21 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA def(password) | Sensitive data returned by an access to password | -| test.go:163:13:163:20 | password | test.go:153:17:153:24 | SSA def(password) | test.go:163:13:163:20 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA def(password) | Sensitive data returned by an access to password | -| test.go:164:16:164:23 | password | test.go:153:17:153:24 | SSA def(password) | test.go:164:16:164:23 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA def(password) | Sensitive data returned by an access to password | -| test.go:165:13:165:20 | password | test.go:153:17:153:24 | SSA def(password) | test.go:165:13:165:20 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA def(password) | Sensitive data returned by an access to password | -| test.go:166:16:166:23 | password | test.go:153:17:153:24 | SSA def(password) | test.go:166:16:166:23 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA def(password) | Sensitive data returned by an access to password | -| test.go:167:13:167:20 | password | test.go:153:17:153:24 | SSA def(password) | test.go:167:13:167:20 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA def(password) | Sensitive data returned by an access to password | -| test.go:168:17:168:24 | password | test.go:153:17:153:24 | SSA def(password) | test.go:168:17:168:24 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA def(password) | Sensitive data returned by an access to password | -| test.go:169:13:169:20 | password | test.go:153:17:153:24 | SSA def(password) | test.go:169:13:169:20 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA def(password) | Sensitive data returned by an access to password | -| test.go:170:12:170:19 | password | test.go:153:17:153:24 | SSA def(password) | test.go:170:12:170:19 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA def(password) | Sensitive data returned by an access to password | -| test.go:171:21:171:28 | password | test.go:153:17:153:24 | SSA def(password) | test.go:171:21:171:28 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA def(password) | Sensitive data returned by an access to password | -| test.go:172:14:172:21 | password | test.go:153:17:153:24 | SSA def(password) | test.go:172:14:172:21 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA def(password) | Sensitive data returned by an access to password | -| test.go:173:13:173:20 | password | test.go:153:17:153:24 | SSA def(password) | test.go:173:13:173:20 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA def(password) | Sensitive data returned by an access to password | -| test.go:174:12:174:19 | password | test.go:153:17:153:24 | SSA def(password) | test.go:174:12:174:19 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA def(password) | Sensitive data returned by an access to password | -| test.go:175:15:175:22 | password | test.go:153:17:153:24 | SSA def(password) | test.go:175:15:175:22 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA def(password) | Sensitive data returned by an access to password | -| test.go:176:15:176:22 | password | test.go:153:17:153:24 | SSA def(password) | test.go:176:15:176:22 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA def(password) | Sensitive data returned by an access to password | -| test.go:177:18:177:25 | password | test.go:153:17:153:24 | SSA def(password) | test.go:177:18:177:25 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA def(password) | Sensitive data returned by an access to password | -| test.go:178:15:178:22 | password | test.go:153:17:153:24 | SSA def(password) | test.go:178:15:178:22 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA def(password) | Sensitive data returned by an access to password | -| test.go:179:19:179:26 | password | test.go:153:17:153:24 | SSA def(password) | test.go:179:19:179:26 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA def(password) | Sensitive data returned by an access to password | -| test.go:180:15:180:22 | password | test.go:153:17:153:24 | SSA def(password) | test.go:180:15:180:22 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA def(password) | Sensitive data returned by an access to password | -| test.go:181:14:181:21 | password | test.go:153:17:153:24 | SSA def(password) | test.go:181:14:181:21 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA def(password) | Sensitive data returned by an access to password | -| test.go:182:23:182:30 | password | test.go:153:17:153:24 | SSA def(password) | test.go:182:23:182:30 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA def(password) | Sensitive data returned by an access to password | -| test.go:183:16:183:23 | password | test.go:153:17:153:24 | SSA def(password) | test.go:183:16:183:23 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA def(password) | Sensitive data returned by an access to password | -| test.go:184:15:184:22 | password | test.go:153:17:153:24 | SSA def(password) | test.go:184:15:184:22 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA def(password) | Sensitive data returned by an access to password | -| test.go:185:14:185:21 | password | test.go:153:17:153:24 | SSA def(password) | test.go:185:14:185:21 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA def(password) | Sensitive data returned by an access to password | -| test.go:186:17:186:24 | password | test.go:153:17:153:24 | SSA def(password) | test.go:186:17:186:24 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA def(password) | Sensitive data returned by an access to password | -| test.go:187:16:187:23 | password | test.go:153:17:153:24 | SSA def(password) | test.go:187:16:187:23 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA def(password) | Sensitive data returned by an access to password | +| test.go:154:14:154:21 | password | test.go:153:17:153:24 | SSA param(password) | test.go:154:14:154:21 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA param(password) | Sensitive data returned by an access to password | +| test.go:155:17:155:24 | password | test.go:153:17:153:24 | SSA param(password) | test.go:155:17:155:24 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA param(password) | Sensitive data returned by an access to password | +| test.go:156:14:156:21 | password | test.go:153:17:153:24 | SSA param(password) | test.go:156:14:156:21 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA param(password) | Sensitive data returned by an access to password | +| test.go:157:18:157:25 | password | test.go:153:17:153:24 | SSA param(password) | test.go:157:18:157:25 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA param(password) | Sensitive data returned by an access to password | +| test.go:158:14:158:21 | password | test.go:153:17:153:24 | SSA param(password) | test.go:158:14:158:21 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA param(password) | Sensitive data returned by an access to password | +| test.go:159:13:159:20 | password | test.go:153:17:153:24 | SSA param(password) | test.go:159:13:159:20 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA param(password) | Sensitive data returned by an access to password | +| test.go:160:22:160:29 | password | test.go:153:17:153:24 | SSA param(password) | test.go:160:22:160:29 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA param(password) | Sensitive data returned by an access to password | +| test.go:161:15:161:22 | password | test.go:153:17:153:24 | SSA param(password) | test.go:161:15:161:22 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA param(password) | Sensitive data returned by an access to password | +| test.go:162:14:162:21 | password | test.go:153:17:153:24 | SSA param(password) | test.go:162:14:162:21 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA param(password) | Sensitive data returned by an access to password | +| test.go:163:13:163:20 | password | test.go:153:17:153:24 | SSA param(password) | test.go:163:13:163:20 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA param(password) | Sensitive data returned by an access to password | +| test.go:164:16:164:23 | password | test.go:153:17:153:24 | SSA param(password) | test.go:164:16:164:23 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA param(password) | Sensitive data returned by an access to password | +| test.go:165:13:165:20 | password | test.go:153:17:153:24 | SSA param(password) | test.go:165:13:165:20 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA param(password) | Sensitive data returned by an access to password | +| test.go:166:16:166:23 | password | test.go:153:17:153:24 | SSA param(password) | test.go:166:16:166:23 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA param(password) | Sensitive data returned by an access to password | +| test.go:167:13:167:20 | password | test.go:153:17:153:24 | SSA param(password) | test.go:167:13:167:20 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA param(password) | Sensitive data returned by an access to password | +| test.go:168:17:168:24 | password | test.go:153:17:153:24 | SSA param(password) | test.go:168:17:168:24 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA param(password) | Sensitive data returned by an access to password | +| test.go:169:13:169:20 | password | test.go:153:17:153:24 | SSA param(password) | test.go:169:13:169:20 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA param(password) | Sensitive data returned by an access to password | +| test.go:170:12:170:19 | password | test.go:153:17:153:24 | SSA param(password) | test.go:170:12:170:19 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA param(password) | Sensitive data returned by an access to password | +| test.go:171:21:171:28 | password | test.go:153:17:153:24 | SSA param(password) | test.go:171:21:171:28 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA param(password) | Sensitive data returned by an access to password | +| test.go:172:14:172:21 | password | test.go:153:17:153:24 | SSA param(password) | test.go:172:14:172:21 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA param(password) | Sensitive data returned by an access to password | +| test.go:173:13:173:20 | password | test.go:153:17:153:24 | SSA param(password) | test.go:173:13:173:20 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA param(password) | Sensitive data returned by an access to password | +| test.go:174:12:174:19 | password | test.go:153:17:153:24 | SSA param(password) | test.go:174:12:174:19 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA param(password) | Sensitive data returned by an access to password | +| test.go:175:15:175:22 | password | test.go:153:17:153:24 | SSA param(password) | test.go:175:15:175:22 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA param(password) | Sensitive data returned by an access to password | +| test.go:176:15:176:22 | password | test.go:153:17:153:24 | SSA param(password) | test.go:176:15:176:22 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA param(password) | Sensitive data returned by an access to password | +| test.go:177:18:177:25 | password | test.go:153:17:153:24 | SSA param(password) | test.go:177:18:177:25 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA param(password) | Sensitive data returned by an access to password | +| test.go:178:15:178:22 | password | test.go:153:17:153:24 | SSA param(password) | test.go:178:15:178:22 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA param(password) | Sensitive data returned by an access to password | +| test.go:179:19:179:26 | password | test.go:153:17:153:24 | SSA param(password) | test.go:179:19:179:26 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA param(password) | Sensitive data returned by an access to password | +| test.go:180:15:180:22 | password | test.go:153:17:153:24 | SSA param(password) | test.go:180:15:180:22 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA param(password) | Sensitive data returned by an access to password | +| test.go:181:14:181:21 | password | test.go:153:17:153:24 | SSA param(password) | test.go:181:14:181:21 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA param(password) | Sensitive data returned by an access to password | +| test.go:182:23:182:30 | password | test.go:153:17:153:24 | SSA param(password) | test.go:182:23:182:30 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA param(password) | Sensitive data returned by an access to password | +| test.go:183:16:183:23 | password | test.go:153:17:153:24 | SSA param(password) | test.go:183:16:183:23 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA param(password) | Sensitive data returned by an access to password | +| test.go:184:15:184:22 | password | test.go:153:17:153:24 | SSA param(password) | test.go:184:15:184:22 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA param(password) | Sensitive data returned by an access to password | +| test.go:185:14:185:21 | password | test.go:153:17:153:24 | SSA param(password) | test.go:185:14:185:21 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA param(password) | Sensitive data returned by an access to password | +| test.go:186:17:186:24 | password | test.go:153:17:153:24 | SSA param(password) | test.go:186:17:186:24 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA param(password) | Sensitive data returned by an access to password | +| test.go:187:16:187:23 | password | test.go:153:17:153:24 | SSA param(password) | test.go:187:16:187:23 | password | $@ flows to a logging call. | test.go:153:17:153:24 | SSA param(password) | Sensitive data returned by an access to password | edges -| test.go:153:17:153:24 | SSA def(password) | test.go:154:14:154:21 | password | provenance | | -| test.go:153:17:153:24 | SSA def(password) | test.go:155:17:155:24 | password | provenance | | -| test.go:153:17:153:24 | SSA def(password) | test.go:156:14:156:21 | password | provenance | | -| test.go:153:17:153:24 | SSA def(password) | test.go:157:18:157:25 | password | provenance | | -| test.go:153:17:153:24 | SSA def(password) | test.go:158:14:158:21 | password | provenance | | -| test.go:153:17:153:24 | SSA def(password) | test.go:159:13:159:20 | password | provenance | | -| test.go:153:17:153:24 | SSA def(password) | test.go:160:22:160:29 | password | provenance | | -| test.go:153:17:153:24 | SSA def(password) | test.go:161:15:161:22 | password | provenance | | -| test.go:153:17:153:24 | SSA def(password) | test.go:162:14:162:21 | password | provenance | | -| test.go:153:17:153:24 | SSA def(password) | test.go:163:13:163:20 | password | provenance | | -| test.go:153:17:153:24 | SSA def(password) | test.go:164:16:164:23 | password | provenance | | -| test.go:153:17:153:24 | SSA def(password) | test.go:165:13:165:20 | password | provenance | Sink:MaD:1 | -| test.go:153:17:153:24 | SSA def(password) | test.go:166:16:166:23 | password | provenance | Sink:MaD:2 | -| test.go:153:17:153:24 | SSA def(password) | test.go:167:13:167:20 | password | provenance | Sink:MaD:3 | -| test.go:153:17:153:24 | SSA def(password) | test.go:168:17:168:24 | password | provenance | Sink:MaD:4 | -| test.go:153:17:153:24 | SSA def(password) | test.go:169:13:169:20 | password | provenance | Sink:MaD:5 | -| test.go:153:17:153:24 | SSA def(password) | test.go:170:12:170:19 | password | provenance | Sink:MaD:6 | -| test.go:153:17:153:24 | SSA def(password) | test.go:171:21:171:28 | password | provenance | Sink:MaD:7 | -| test.go:153:17:153:24 | SSA def(password) | test.go:172:14:172:21 | password | provenance | Sink:MaD:8 | -| test.go:153:17:153:24 | SSA def(password) | test.go:173:13:173:20 | password | provenance | Sink:MaD:9 | -| test.go:153:17:153:24 | SSA def(password) | test.go:174:12:174:19 | password | provenance | Sink:MaD:10 | -| test.go:153:17:153:24 | SSA def(password) | test.go:175:15:175:22 | password | provenance | Sink:MaD:11 | -| test.go:153:17:153:24 | SSA def(password) | test.go:176:15:176:22 | password | provenance | Sink:MaD:12 | -| test.go:153:17:153:24 | SSA def(password) | test.go:177:18:177:25 | password | provenance | Sink:MaD:13 | -| test.go:153:17:153:24 | SSA def(password) | test.go:178:15:178:22 | password | provenance | Sink:MaD:14 | -| test.go:153:17:153:24 | SSA def(password) | test.go:179:19:179:26 | password | provenance | Sink:MaD:15 | -| test.go:153:17:153:24 | SSA def(password) | test.go:180:15:180:22 | password | provenance | Sink:MaD:16 | -| test.go:153:17:153:24 | SSA def(password) | test.go:181:14:181:21 | password | provenance | Sink:MaD:17 | -| test.go:153:17:153:24 | SSA def(password) | test.go:182:23:182:30 | password | provenance | Sink:MaD:18 | -| test.go:153:17:153:24 | SSA def(password) | test.go:183:16:183:23 | password | provenance | Sink:MaD:19 | -| test.go:153:17:153:24 | SSA def(password) | test.go:184:15:184:22 | password | provenance | Sink:MaD:20 | -| test.go:153:17:153:24 | SSA def(password) | test.go:185:14:185:21 | password | provenance | Sink:MaD:21 | -| test.go:153:17:153:24 | SSA def(password) | test.go:186:17:186:24 | password | provenance | Sink:MaD:22 | -| test.go:153:17:153:24 | SSA def(password) | test.go:187:16:187:23 | password | provenance | | +| test.go:153:17:153:24 | SSA param(password) | test.go:154:14:154:21 | password | provenance | | +| test.go:153:17:153:24 | SSA param(password) | test.go:155:17:155:24 | password | provenance | | +| test.go:153:17:153:24 | SSA param(password) | test.go:156:14:156:21 | password | provenance | | +| test.go:153:17:153:24 | SSA param(password) | test.go:157:18:157:25 | password | provenance | | +| test.go:153:17:153:24 | SSA param(password) | test.go:158:14:158:21 | password | provenance | | +| test.go:153:17:153:24 | SSA param(password) | test.go:159:13:159:20 | password | provenance | | +| test.go:153:17:153:24 | SSA param(password) | test.go:160:22:160:29 | password | provenance | | +| test.go:153:17:153:24 | SSA param(password) | test.go:161:15:161:22 | password | provenance | | +| test.go:153:17:153:24 | SSA param(password) | test.go:162:14:162:21 | password | provenance | | +| test.go:153:17:153:24 | SSA param(password) | test.go:163:13:163:20 | password | provenance | | +| test.go:153:17:153:24 | SSA param(password) | test.go:164:16:164:23 | password | provenance | | +| test.go:153:17:153:24 | SSA param(password) | test.go:165:13:165:20 | password | provenance | Sink:MaD:1 | +| test.go:153:17:153:24 | SSA param(password) | test.go:166:16:166:23 | password | provenance | Sink:MaD:2 | +| test.go:153:17:153:24 | SSA param(password) | test.go:167:13:167:20 | password | provenance | Sink:MaD:3 | +| test.go:153:17:153:24 | SSA param(password) | test.go:168:17:168:24 | password | provenance | Sink:MaD:4 | +| test.go:153:17:153:24 | SSA param(password) | test.go:169:13:169:20 | password | provenance | Sink:MaD:5 | +| test.go:153:17:153:24 | SSA param(password) | test.go:170:12:170:19 | password | provenance | Sink:MaD:6 | +| test.go:153:17:153:24 | SSA param(password) | test.go:171:21:171:28 | password | provenance | Sink:MaD:7 | +| test.go:153:17:153:24 | SSA param(password) | test.go:172:14:172:21 | password | provenance | Sink:MaD:8 | +| test.go:153:17:153:24 | SSA param(password) | test.go:173:13:173:20 | password | provenance | Sink:MaD:9 | +| test.go:153:17:153:24 | SSA param(password) | test.go:174:12:174:19 | password | provenance | Sink:MaD:10 | +| test.go:153:17:153:24 | SSA param(password) | test.go:175:15:175:22 | password | provenance | Sink:MaD:11 | +| test.go:153:17:153:24 | SSA param(password) | test.go:176:15:176:22 | password | provenance | Sink:MaD:12 | +| test.go:153:17:153:24 | SSA param(password) | test.go:177:18:177:25 | password | provenance | Sink:MaD:13 | +| test.go:153:17:153:24 | SSA param(password) | test.go:178:15:178:22 | password | provenance | Sink:MaD:14 | +| test.go:153:17:153:24 | SSA param(password) | test.go:179:19:179:26 | password | provenance | Sink:MaD:15 | +| test.go:153:17:153:24 | SSA param(password) | test.go:180:15:180:22 | password | provenance | Sink:MaD:16 | +| test.go:153:17:153:24 | SSA param(password) | test.go:181:14:181:21 | password | provenance | Sink:MaD:17 | +| test.go:153:17:153:24 | SSA param(password) | test.go:182:23:182:30 | password | provenance | Sink:MaD:18 | +| test.go:153:17:153:24 | SSA param(password) | test.go:183:16:183:23 | password | provenance | Sink:MaD:19 | +| test.go:153:17:153:24 | SSA param(password) | test.go:184:15:184:22 | password | provenance | Sink:MaD:20 | +| test.go:153:17:153:24 | SSA param(password) | test.go:185:14:185:21 | password | provenance | Sink:MaD:21 | +| test.go:153:17:153:24 | SSA param(password) | test.go:186:17:186:24 | password | provenance | Sink:MaD:22 | +| test.go:153:17:153:24 | SSA param(password) | test.go:187:16:187:23 | password | provenance | | models | 1 | Sink: group:beego-logs; ; false; Alert; ; ; Argument[0..1]; log-injection; manual | | 2 | Sink: group:beego-logs; ; false; Critical; ; ; Argument[0..1]; log-injection; manual | @@ -92,7 +92,7 @@ models | 21 | Sink: group:beego-logs; BeeLogger; true; Warn; ; ; Argument[0..1]; log-injection; manual | | 22 | Sink: group:beego-logs; BeeLogger; true; Warning; ; ; Argument[0..1]; log-injection; manual | nodes -| test.go:153:17:153:24 | SSA def(password) | semmle.label | SSA def(password) | +| test.go:153:17:153:24 | SSA param(password) | semmle.label | SSA param(password) | | test.go:154:14:154:21 | password | semmle.label | password | | test.go:155:17:155:24 | password | semmle.label | password | | test.go:156:14:156:21 | password | semmle.label | password | diff --git a/go/ql/test/library-tests/semmle/go/frameworks/GoKit/main.go b/go/ql/test/library-tests/semmle/go/frameworks/GoKit/main.go index cfd62e0de3a2..64df0ad2980a 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/GoKit/main.go +++ b/go/ql/test/library-tests/semmle/go/frameworks/GoKit/main.go @@ -12,12 +12,12 @@ type MyService interface { } func makeEndpointLit(svc MyService) endpoint.Endpoint { - return func(_ context.Context, request interface{}) (interface{}, error) { // $ source="SSA def(request)" + return func(_ context.Context, request interface{}) (interface{}, error) { // $ source="SSA param(request)" return request, nil } } -func endpointfn(_ context.Context, request interface{}) (interface{}, error) { // $ source="SSA def(request)" +func endpointfn(_ context.Context, request interface{}) (interface{}, error) { // $ source="SSA param(request)" return request, nil } diff --git a/go/ql/test/library-tests/semmle/go/frameworks/GoMicro/LogInjection.expected b/go/ql/test/library-tests/semmle/go/frameworks/GoMicro/LogInjection.expected index 44c5b85039c5..9b07169a0f36 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/GoMicro/LogInjection.expected +++ b/go/ql/test/library-tests/semmle/go/frameworks/GoMicro/LogInjection.expected @@ -1,8 +1,8 @@ #select -| main.go:21:28:21:31 | name | main.go:18:46:18:48 | SSA def(req) | main.go:21:28:21:31 | name | This log entry depends on a $@. | main.go:18:46:18:48 | SSA def(req) | user-provided value | +| main.go:21:28:21:31 | name | main.go:18:46:18:48 | SSA param(req) | main.go:21:28:21:31 | name | This log entry depends on a $@. | main.go:18:46:18:48 | SSA param(req) | user-provided value | edges -| main.go:18:46:18:48 | SSA def(req) | main.go:21:28:21:31 | name | provenance | | +| main.go:18:46:18:48 | SSA param(req) | main.go:21:28:21:31 | name | provenance | | nodes -| main.go:18:46:18:48 | SSA def(req) | semmle.label | SSA def(req) | +| main.go:18:46:18:48 | SSA param(req) | semmle.label | SSA param(req) | | main.go:21:28:21:31 | name | semmle.label | name | subpaths diff --git a/go/ql/test/library-tests/semmle/go/frameworks/GoMicro/main.go b/go/ql/test/library-tests/semmle/go/frameworks/GoMicro/main.go index 17e554ee4b12..5ba28d464f26 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/GoMicro/main.go +++ b/go/ql/test/library-tests/semmle/go/frameworks/GoMicro/main.go @@ -15,7 +15,7 @@ import ( type Greeter struct{} -func (g *Greeter) Hello(ctx context.Context, req *pb.Request, rsp *pb.Response) error { // $ serverRequest="SSA def(req)" Source +func (g *Greeter) Hello(ctx context.Context, req *pb.Request, rsp *pb.Response) error { // $ serverRequest="SSA param(req)" Source // var access name := req.Name fmt.Println("Name :: %s", name) // $ Alert diff --git a/go/ql/test/library-tests/semmle/go/frameworks/Twirp/RequestForgery.expected b/go/ql/test/library-tests/semmle/go/frameworks/Twirp/RequestForgery.expected index 483cd2702ca6..922e92e56860 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/Twirp/RequestForgery.expected +++ b/go/ql/test/library-tests/semmle/go/frameworks/Twirp/RequestForgery.expected @@ -1,19 +1,19 @@ #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 | 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 | +| server/main.go:30:38:30:48 | selection of Text | server/main.go:19:56:19:61 | SSA param(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 param(params) | user-provided value | edges -| 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 | &... | server/main.go:19:56:19:61 | SSA param(params) | 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: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: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: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:56:19:61 | SSA def(params) | 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:56:19:61 | 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:56:19:61 | SSA def(params) [Return] | client/main.go:16:35:16:78 | &... [postupdate] | provenance | | +| rpc/notes/service.twirp.go:544:32:544:41 | reqContent [postupdate] | rpc/notes/service.twirp.go:574:2:577:2 | SSA implicit def(reqContent) | provenance | | +| rpc/notes/service.twirp.go:574:2:577:2 | SSA implicit 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:56:19:61 | SSA param(params) | provenance | | +| server/main.go:19:56:19:61 | SSA param(params) | server/main.go:19:56:19:61 | SSA param(params) [Return] | provenance | | +| server/main.go:19:56:19:61 | SSA param(params) | server/main.go:30:38:30:48 | selection of Text | provenance | | +| server/main.go:19:56:19:61 | SSA param(params) | server/main.go:30:38:30:48 | selection of Text | provenance | | +| server/main.go:19:56:19:61 | SSA param(params) [Return] | client/main.go:16:35:16:78 | &... [postupdate] | provenance | | models | 1 | Source: net/http; Request; true; Body; ; ; ; remote; manual | | 2 | Summary: google.golang.org/protobuf/proto; ; false; Unmarshal; ; ; Argument[0]; Argument[1]; taint; manual | @@ -25,10 +25,10 @@ nodes | 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: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 implicit def(reqContent) | semmle.label | SSA implicit def(reqContent) | | rpc/notes/service.twirp.go:576:35:576:44 | reqContent | semmle.label | reqContent | -| server/main.go:19:56:19:61 | 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:56:19:61 | SSA def(params) [Return] | semmle.label | SSA def(params) [Return] | +| server/main.go:19:56:19:61 | SSA param(params) | semmle.label | SSA param(params) | +| server/main.go:19:56:19:61 | SSA param(params) | semmle.label | SSA param(params) | +| server/main.go:19:56:19:61 | SSA param(params) [Return] | semmle.label | SSA param(params) [Return] | | server/main.go:30:38:30:48 | selection of Text | semmle.label | selection of Text | subpaths diff --git a/go/ql/test/library-tests/semmle/go/frameworks/gqlgen/graph/schema.resolvers.go b/go/ql/test/library-tests/semmle/go/frameworks/gqlgen/graph/schema.resolvers.go index 92d73f09364c..880b4733e884 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/gqlgen/graph/schema.resolvers.go +++ b/go/ql/test/library-tests/semmle/go/frameworks/gqlgen/graph/schema.resolvers.go @@ -11,7 +11,7 @@ import ( ) // CreateTodo is the resolver for the createTodo field. -func (r *mutationResolver) CreateTodo(ctx context.Context, input model.NewTodo) (*model.Todo, error) { // $ resolverParameter="SSA def(input)" +func (r *mutationResolver) CreateTodo(ctx context.Context, input model.NewTodo) (*model.Todo, error) { // $ resolverParameter="SSA param(input)" panic(fmt.Errorf("not implemented: CreateTodo - createTodo %v", input)) } diff --git a/go/ql/test/query-tests/InconsistentCode/UnhandledCloseWritableHandle/UnhandledCloseWritableHandle.expected b/go/ql/test/query-tests/InconsistentCode/UnhandledCloseWritableHandle/UnhandledCloseWritableHandle.expected index 4fe3c754a5a5..e51c2db4e8bb 100644 --- a/go/ql/test/query-tests/InconsistentCode/UnhandledCloseWritableHandle/UnhandledCloseWritableHandle.expected +++ b/go/ql/test/query-tests/InconsistentCode/UnhandledCloseWritableHandle/UnhandledCloseWritableHandle.expected @@ -9,17 +9,17 @@ | 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: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 | edges -| tests.go:9:24:9:24 | SSA def(f) | tests.go:10:8:10:8 | 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:9:24:9:24 | SSA param(f) | tests.go:10:8:10:8 | f | provenance | | +| tests.go:13:32:13:32 | SSA param(f) | tests.go:14:13:16:2 | SSA implicit def(f) | provenance | | +| tests.go:14:13:16:2 | SSA implicit 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 | extract:0 ... := ... | tests.go:34:29:34:29 | f | provenance | Src:MaD:1 | -| 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:32:13:32 | SSA def(f) | provenance | | +| tests.go:33:21:33:21 | f | tests.go:9:24:9:24 | SSA param(f) | provenance | | +| tests.go:34:29:34:29 | f | tests.go:13:32:13:32 | SSA param(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 | extract:0 ... := ... | tests.go:48:29:48:29 | f | provenance | Src:MaD:1 | -| 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:32:13:32 | SSA def(f) | provenance | | +| tests.go:47:21:47:21 | f | tests.go:9:24:9:24 | SSA param(f) | provenance | | +| tests.go:48:29:48:29 | f | tests.go:13:32:13:32 | SSA param(f) | provenance | | | tests.go:55:5:55:78 | extract: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:124:5:124:78 | extract:0 ... := ... | tests.go:126:9:126:9 | f | provenance | Src:MaD:1 | @@ -28,10 +28,10 @@ edges models | 1 | Source: os; ; false; OpenFile; ; ; ReturnValue[0]; file; manual | nodes -| tests.go:9:24:9:24 | SSA def(f) | semmle.label | SSA def(f) | +| tests.go:9:24:9:24 | SSA param(f) | semmle.label | SSA param(f) | | tests.go:10:8:10:8 | f | semmle.label | 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:13:32:13:32 | SSA param(f) | semmle.label | SSA param(f) | +| tests.go:14:13:16:2 | SSA implicit def(f) | semmle.label | SSA implicit def(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:33:21:33:21 | f | semmle.label | f | diff --git a/go/ql/test/query-tests/Security/CWE-022/UnsafeUnzipSymlink.expected b/go/ql/test/query-tests/Security/CWE-022/UnsafeUnzipSymlink.expected index 73e5f0aa503d..9a3a222add38 100644 --- a/go/ql/test/query-tests/Security/CWE-022/UnsafeUnzipSymlink.expected +++ b/go/ql/test/query-tests/Security/CWE-022/UnsafeUnzipSymlink.expected @@ -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: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 -| UnsafeUnzipSymlink.go:111:19:111:26 | 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:19:111:26 | SSA def(linkName) | provenance | | -| UnsafeUnzipSymlink.go:126:34:126:44 | selection of Name | UnsafeUnzipSymlink.go:111:29:111:36 | SSA def(fileName) | provenance | | +| UnsafeUnzipSymlink.go:111:19:111:26 | SSA param(linkName) | UnsafeUnzipSymlink.go:112:13:112:20 | linkName | provenance | Sink:MaD:1 | +| UnsafeUnzipSymlink.go:111:29:111:36 | SSA param(fileName) | UnsafeUnzipSymlink.go:112:23:112:30 | fileName | provenance | Sink:MaD:1 | +| UnsafeUnzipSymlink.go:126:17:126:31 | selection of Linkname | UnsafeUnzipSymlink.go:111:19:111:26 | SSA param(linkName) | provenance | | +| UnsafeUnzipSymlink.go:126:34:126:44 | selection of Name | UnsafeUnzipSymlink.go:111:29:111:36 | SSA param(fileName) | provenance | | models | 1 | Sink: os; ; false; Symlink; ; ; Argument[0..1]; path-injection; manual | nodes | 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:43:25:43:35 | selection of Name | semmle.label | selection of Name | -| UnsafeUnzipSymlink.go:111:19:111:26 | SSA def(linkName) | semmle.label | SSA def(linkName) | -| UnsafeUnzipSymlink.go:111:29:111:36 | SSA def(fileName) | semmle.label | SSA def(fileName) | +| UnsafeUnzipSymlink.go:111:19:111:26 | SSA param(linkName) | semmle.label | SSA param(linkName) | +| UnsafeUnzipSymlink.go:111:29:111:36 | SSA param(fileName) | semmle.label | SSA param(fileName) | | UnsafeUnzipSymlink.go:112:13:112:20 | linkName | semmle.label | linkName | | UnsafeUnzipSymlink.go:112:23:112:30 | fileName | semmle.label | fileName | | UnsafeUnzipSymlink.go:126:17:126:31 | selection of Linkname | semmle.label | selection of Linkname | diff --git a/go/ql/test/query-tests/Security/CWE-022/ZipSlip.expected b/go/ql/test/query-tests/Security/CWE-022/ZipSlip.expected index 6ed511869f75..406af0474609 100644 --- a/go/ql/test/query-tests/Security/CWE-022/ZipSlip.expected +++ b/go/ql/test/query-tests/Security/CWE-022/ZipSlip.expected @@ -6,12 +6,12 @@ | tst.go:23:2:43:2 | extract:1 range element | tst.go:23:2:43:2 | extract:1 range element | 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 | extract:1 range element | tst.go:23:2:43:2 | extract:1 range element | tst.go:31:21:31:24 | path | Unsanitized archive entry, which may contain '..', is used in a $@. | tst.go:31:21:31:24 | path | file system operation | edges -| UnsafeUnzipSymlinkGood.go:52:24:52:32 | SSA def(candidate) | UnsafeUnzipSymlinkGood.go:61:53:61:61 | candidate | provenance | | +| UnsafeUnzipSymlinkGood.go:52:24:52:32 | SSA param(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:72:3:72:25 | extract: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: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:24:52:32 | SSA def(candidate) | provenance | | +| UnsafeUnzipSymlinkGood.go:76:24:76:38 | selection of Linkname | UnsafeUnzipSymlinkGood.go:52:24:52:32 | SSA param(candidate) | provenance | | +| UnsafeUnzipSymlinkGood.go:76:70:76:80 | selection of Name | UnsafeUnzipSymlinkGood.go:52:24:52:32 | SSA param(candidate) | provenance | | | ZipSlip.go:11:2:15:2 | extract:1 range element | 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:24:12:29 | selection of Name | ZipSlip.go:12:3:12:30 | extract:0 ... := ... | provenance | MaD:4 | @@ -31,7 +31,7 @@ models | 5 | Summary: path/filepath; ; false; Rel; ; ; Argument[0..1]; ReturnValue[0]; taint; manual | | 6 | Summary: path; ; false; Dir; ; ; Argument[0]; ReturnValue; taint; manual | nodes -| UnsafeUnzipSymlinkGood.go:52:24:52:32 | SSA def(candidate) | semmle.label | SSA def(candidate) | +| UnsafeUnzipSymlinkGood.go:52:24:52:32 | SSA param(candidate) | semmle.label | SSA param(candidate) | | 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:72:3:72:25 | extract:0 ... := ... | semmle.label | extract:0 ... := ... | diff --git a/go/ql/test/query-tests/Security/CWE-079/StoredXss.expected b/go/ql/test/query-tests/Security/CWE-079/StoredXss.expected index 50284f8e6d4d..18d1788cd6d0 100644 --- a/go/ql/test/query-tests/Security/CWE-079/StoredXss.expected +++ b/go/ql/test/query-tests/Security/CWE-079/StoredXss.expected @@ -1,13 +1,13 @@ #select | StoredXss.go:13:21:13:36 | ...+... | StoredXss.go:13:21:13:31 | call to Name | StoredXss.go:13:21:13:36 | ...+... | Stored cross-site scripting vulnerability due to $@. | StoredXss.go:13:21:13:31 | call to Name | stored value | | stored.go:30:22:30:25 | name | stored.go:18:3:18:28 | extract:0 ... := ... | stored.go:30:22:30:25 | name | Stored cross-site scripting vulnerability due to $@. | stored.go:18:3:18:28 | extract:0 ... := ... | stored value | -| stored.go:61:22:61:25 | path | stored.go:59:30:59:33 | SSA def(path) | stored.go:61:22:61:25 | path | Stored cross-site scripting vulnerability due to $@. | stored.go:59:30:59:33 | SSA def(path) | stored value | +| stored.go:61:22:61:25 | path | stored.go:59:30:59:33 | SSA param(path) | stored.go:61:22:61:25 | path | Stored cross-site scripting vulnerability due to $@. | stored.go:59:30:59:33 | SSA param(path) | stored value | edges | StoredXss.go:13:21:13:31 | call to Name | StoredXss.go:13:21:13:36 | ...+... | provenance | | | stored.go:18:3:18:28 | extract:0 ... := ... | stored.go:25:14:25:17 | rows | provenance | Src:MaD:1 | | stored.go:25:14:25:17 | rows | stored.go:25:29:25:33 | &... [postupdate] | provenance | FunctionModel | | stored.go:25:29:25:33 | &... [postupdate] | stored.go:30:22:30:25 | name | provenance | | -| stored.go:59:30:59:33 | SSA def(path) | stored.go:61:22:61:25 | path | provenance | | +| stored.go:59:30:59:33 | SSA param(path) | stored.go:61:22:61:25 | path | provenance | | models | 1 | Source: database/sql; DB; true; Query; ; ; ReturnValue[0]; database; manual | nodes @@ -17,6 +17,6 @@ nodes | stored.go:25:14:25:17 | rows | semmle.label | rows | | stored.go:25:29:25:33 | &... [postupdate] | semmle.label | &... [postupdate] | | stored.go:30:22:30:25 | name | semmle.label | name | -| stored.go:59:30:59:33 | SSA def(path) | semmle.label | SSA def(path) | +| stored.go:59:30:59:33 | SSA param(path) | semmle.label | SSA param(path) | | stored.go:61:22:61:25 | path | semmle.label | path | subpaths diff --git a/go/ql/test/query-tests/Security/CWE-312/CleartextLogging.expected b/go/ql/test/query-tests/Security/CWE-312/CleartextLogging.expected index c81e0ed61412..0114d36462c8 100644 --- a/go/ql/test/query-tests/Security/CWE-312/CleartextLogging.expected +++ b/go/ql/test/query-tests/Security/CWE-312/CleartextLogging.expected @@ -99,12 +99,12 @@ edges | 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:9:9:9:16 | password | overrides.go:13:14:13:23 | call to String | provenance | | -| passwords.go:8:12:8:12 | SSA def(x) | passwords.go:9:14:9:14 | x | provenance | | +| passwords.go:8:12:8:12 | SSA param(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:23 | 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:23 | SSA def(password) | passwords.go:36:28:36:35 | password | provenance | | -| passwords.go:30:8:30:15 | password | passwords.go:8:12:8:12 | SSA def(x) | provenance | | +| passwords.go:30:8:30:15 | password | passwords.go:8:12:8:12 | SSA param(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:44:6:44:13 | password | provenance | | | passwords.go:38:10:40:2 | struct literal | passwords.go:41:14:41:17 | obj1 | provenance | | @@ -147,8 +147,8 @@ edges | 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: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:7:117:7 | SSA def(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 | | +| protobuf.go:14:14:14:18 | query [pointer, Description] | protos/query/query.pb.go:117:7:117:7 | SSA param(x) [pointer, Description] | provenance | | +| protos/query/query.pb.go:117:7:117:7 | SSA param(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 | x [pointer, Description] | protos/query/query.pb.go:119:10:119:10 | implicit-deref x [Description] | provenance | | models @@ -212,7 +212,7 @@ nodes | overrides.go:8:2:8:40 | SSA def(password) | semmle.label | SSA def(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 | -| passwords.go:8:12:8:12 | SSA def(x) | semmle.label | SSA def(x) | +| passwords.go:8:12:8:12 | SSA param(x) | semmle.label | SSA param(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:25:14:25:21 | password | semmle.label | password | @@ -263,9 +263,9 @@ nodes | 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:35 | call to GetDescription | semmle.label | call to GetDescription | -| 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:117:7:117:7 | SSA param(x) [pointer, Description] | semmle.label | SSA param(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 | 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 | subpaths -| 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 | +| protobuf.go:14:14:14:18 | query [pointer, Description] | protos/query/query.pb.go:117:7:117:7 | SSA param(x) [pointer, Description] | protos/query/query.pb.go:119:10:119:22 | selection of Description | protobuf.go:14:14:14:35 | call to GetDescription | diff --git a/go/ql/test/query-tests/Security/CWE-322/InsecureHostKeyCallback.expected b/go/ql/test/query-tests/Security/CWE-322/InsecureHostKeyCallback.expected index 130e2a6781f3..1396427faa0b 100644 --- a/go/ql/test/query-tests/Security/CWE-322/InsecureHostKeyCallback.expected +++ b/go/ql/test/query-tests/Security/CWE-322/InsecureHostKeyCallback.expected @@ -8,18 +8,18 @@ edges | 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:45:3:47:3 | function literal | InsecureHostKeyCallbackExample.go:52:20:52:48 | type conversion | provenance | | -| InsecureHostKeyCallbackExample.go:58:39:58:46 | SSA def(callback) | InsecureHostKeyCallbackExample.go:62:20:62:27 | callback | provenance | | -| InsecureHostKeyCallbackExample.go:68:48:68:55 | SSA def(callback) | InsecureHostKeyCallbackExample.go:78:28:78:35 | callback | provenance | | +| InsecureHostKeyCallbackExample.go:58:39:58:46 | SSA param(callback) | InsecureHostKeyCallbackExample.go:62:20:62:27 | callback | provenance | | +| InsecureHostKeyCallbackExample.go:68:48:68:55 | SSA param(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: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:107:35:107:50 | insecureCallback | InsecureHostKeyCallbackExample.go:58:39:58:46 | SSA def(callback) | provenance | | +| InsecureHostKeyCallbackExample.go:107:35:107:50 | insecureCallback | InsecureHostKeyCallbackExample.go:58:39:58:46 | SSA param(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: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: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:39:58:46 | SSA def(callback) | provenance | | -| InsecureHostKeyCallbackExample.go:120:44:120:68 | potentiallySecureCallback | InsecureHostKeyCallbackExample.go:68:48:68:55 | SSA def(callback) | provenance | | +| InsecureHostKeyCallbackExample.go:117:35:117:59 | potentiallySecureCallback | InsecureHostKeyCallbackExample.go:58:39:58:46 | SSA param(callback) | provenance | | +| InsecureHostKeyCallbackExample.go:118:35:118:61 | call to InsecureIgnoreHostKey | InsecureHostKeyCallbackExample.go:58:39:58:46 | SSA param(callback) | provenance | | +| InsecureHostKeyCallbackExample.go:120:44:120:68 | potentiallySecureCallback | InsecureHostKeyCallbackExample.go:68:48:68:55 | SSA param(callback) | provenance | | nodes | InsecureHostKeyCallbackExample.go:15:20:18:5 | type conversion | semmle.label | type conversion | | InsecureHostKeyCallbackExample.go:16:4:18:4 | function literal | semmle.label | function literal | @@ -29,9 +29,9 @@ nodes | InsecureHostKeyCallbackExample.go:39:20:39:27 | callback | semmle.label | callback | | 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:58:39:58:46 | SSA def(callback) | semmle.label | SSA def(callback) | +| InsecureHostKeyCallbackExample.go:58:39:58:46 | SSA param(callback) | semmle.label | SSA param(callback) | | InsecureHostKeyCallbackExample.go:62:20:62:27 | callback | semmle.label | callback | -| InsecureHostKeyCallbackExample.go:68:48:68:55 | SSA def(callback) | semmle.label | SSA def(callback) | +| InsecureHostKeyCallbackExample.go:68:48:68:55 | SSA param(callback) | semmle.label | SSA param(callback) | | 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:92:28:92:54 | call to InsecureIgnoreHostKey | semmle.label | call to InsecureIgnoreHostKey | diff --git a/go/ql/test/query-tests/Security/CWE-326/InsufficientKeySize.expected b/go/ql/test/query-tests/Security/CWE-326/InsufficientKeySize.expected index b37e3395a866..6ab8df627811 100644 --- a/go/ql/test/query-tests/Security/CWE-326/InsufficientKeySize.expected +++ b/go/ql/test/query-tests/Security/CWE-326/InsufficientKeySize.expected @@ -1,7 +1,14 @@ +#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 | 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:11:25:14 | SSA def(size) | provenance | | -| InsufficientKeySize.go:25:11:25:14 | SSA def(size) | InsufficientKeySize.go:26:31:26:34 | size | provenance | | +| InsufficientKeySize.go:18:7:18:10 | 1024 | InsufficientKeySize.go:25:11:25:14 | SSA param(size) | provenance | | +| InsufficientKeySize.go:25:11:25:14 | SSA param(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: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 | | @@ -10,7 +17,7 @@ nodes | InsufficientKeySize.go:13:10:13:13 | 1024 | semmle.label | 1024 | | InsufficientKeySize.go:14:31:14:34 | size | semmle.label | size | | InsufficientKeySize.go:18:7:18:10 | 1024 | semmle.label | 1024 | -| InsufficientKeySize.go:25:11:25:14 | SSA def(size) | semmle.label | SSA def(size) | +| InsufficientKeySize.go:25:11:25:14 | SSA param(size) | semmle.label | SSA param(size) | | InsufficientKeySize.go:26:31:26:34 | size | semmle.label | size | | InsufficientKeySize.go:30:13:30:16 | 1024 | semmle.label | 1024 | | InsufficientKeySize.go:32:32:32:38 | keyBits | semmle.label | keyBits | @@ -19,10 +26,3 @@ nodes | InsufficientKeySize.go:61:21:61:24 | 1024 | semmle.label | 1024 | | InsufficientKeySize.go:67:31:67:37 | keyBits | semmle.label | keyBits | 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. | diff --git a/go/ql/test/query-tests/Security/CWE-347/MissingJwtSignatureCheck.expected b/go/ql/test/query-tests/Security/CWE-347/MissingJwtSignatureCheck.expected index 7eafa2b87aa2..95512bf9dee7 100644 --- a/go/ql/test/query-tests/Security/CWE-347/MissingJwtSignatureCheck.expected +++ b/go/ql/test/query-tests/Security/CWE-347/MissingJwtSignatureCheck.expected @@ -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: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:26:15:26:25 | signedToken | go-jose.v3.go:29:19:29:29 | SSA def(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:26:15:26:25 | signedToken | go-jose.v3.go:29:19:29:29 | SSA param(signedToken) | provenance | | +| go-jose.v3.go:29:19:29:29 | SSA param(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:37:31:47 | signedToken | go-jose.v3.go:31:2:31:48 | extract: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: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:29:25:29:35 | signedToken | golang-jwt-v5.go:32:29:32:39 | SSA def(signedToken) | provenance | | -| golang-jwt-v5.go:32:29:32:39 | SSA def(signedToken) | golang-jwt-v5.go:34:58:34:68 | signedToken | provenance | Sink:MaD:1 | +| golang-jwt-v5.go:29:25:29:35 | signedToken | golang-jwt-v5.go:32:29:32:39 | SSA param(signedToken) | provenance | | +| golang-jwt-v5.go:32:29:32:39 | SSA param(signedToken) | golang-jwt-v5.go:34:58:34:68 | signedToken | provenance | Sink:MaD:1 | models | 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 | @@ -26,7 +26,7 @@ nodes | 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:26:15:26:25 | signedToken | semmle.label | signedToken | -| go-jose.v3.go:29:19:29:29 | SSA def(signedToken) | semmle.label | SSA def(signedToken) | +| go-jose.v3.go:29:19:29:29 | SSA param(signedToken) | semmle.label | SSA param(signedToken) | | go-jose.v3.go:31:2:31:48 | extract:0 ... := ... | semmle.label | extract:0 ... := ... | | go-jose.v3.go:31:37:31:47 | signedToken | semmle.label | signedToken | | go-jose.v3.go:33:12:33:23 | DecodedToken | semmle.label | DecodedToken | @@ -34,6 +34,6 @@ nodes | 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:29:25:29:35 | signedToken | semmle.label | signedToken | -| golang-jwt-v5.go:32:29:32:39 | SSA def(signedToken) | semmle.label | SSA def(signedToken) | +| golang-jwt-v5.go:32:29:32:39 | SSA param(signedToken) | semmle.label | SSA param(signedToken) | | golang-jwt-v5.go:34:58:34:68 | signedToken | semmle.label | signedToken | subpaths diff --git a/go/ql/test/query-tests/Security/CWE-601/BadRedirectCheck/BadRedirectCheck.expected b/go/ql/test/query-tests/Security/CWE-601/BadRedirectCheck/BadRedirectCheck.expected index 8fb1a305e550..ab4b308f8848 100644 --- a/go/ql/test/query-tests/Security/CWE-601/BadRedirectCheck/BadRedirectCheck.expected +++ b/go/ql/test/query-tests/Security/CWE-601/BadRedirectCheck/BadRedirectCheck.expected @@ -9,30 +9,30 @@ | main.go:69:5:69:22 | ...!=... | main.go:76:19:76:21 | 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 | 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 | edges -| BadRedirectCheck.go:3:18:3:22 | SSA def(redir) | BadRedirectCheck.go:5:10:5:14 | redir | provenance | | +| BadRedirectCheck.go:3:18:3:22 | SSA param(redir) | BadRedirectCheck.go:5:10:5:14 | redir | provenance | | | BadRedirectCheck.go:3:18:3:22 | 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 | | cves.go:14:23:14:25 | 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:41:14:41:34 | call to Get | cves.go:45:25:45:32 | redirect | provenance | Sink:MaD:1 | | main.go:10:18:10:25 | redirect | main.go:11:37:11:44 | redirect | 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 | BadRedirectCheck.go:3:18:3:22 | SSA param(redir) | provenance | | | main.go:11:37:11:44 | redirect | main.go:11:25:11:45 | call to sanitizeUrl | provenance | Sink:MaD:1 | | main.go:32:24:32:26 | url | main.go:34:26:34:28 | url | provenance | Sink:MaD:1 | -| main.go:68:17:68:24 | SSA def(redirect) | main.go:73:20:73:27 | redirect | provenance | | +| main.go:68:17:68:24 | SSA param(redirect) | main.go:73:20:73:27 | redirect | provenance | | | main.go:68:17:68:24 | 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: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:19:76:21 | url | main.go:77:36:77:38 | url | 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:68:17:68:24 | SSA param(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:87:9:87:14 | selection of Path | main.go:91:25:91:39 | call to getTarget2 | provenance | Sink:MaD:1 | models | 1 | Sink: net/http; ; false; Redirect; ; ; Argument[2]; url-redirection[0]; manual | | 2 | Summary: path; ; false; Clean; ; ; Argument[0]; ReturnValue; taint; manual | nodes -| BadRedirectCheck.go:3:18:3:22 | SSA def(redir) | semmle.label | SSA def(redir) | +| BadRedirectCheck.go:3:18:3:22 | SSA param(redir) | semmle.label | SSA param(redir) | | BadRedirectCheck.go:3:18:3:22 | redir | semmle.label | redir | | BadRedirectCheck.go:5:10:5:14 | redir | semmle.label | redir | | BadRedirectCheck.go:5:10:5:14 | redir | semmle.label | redir | @@ -47,7 +47,7 @@ nodes | main.go:11:37:11:44 | redirect | semmle.label | redirect | | main.go:32:24:32:26 | url | semmle.label | url | | main.go:34:26:34:28 | url | semmle.label | url | -| main.go:68:17:68:24 | SSA def(redirect) | semmle.label | SSA def(redirect) | +| main.go:68:17:68:24 | SSA param(redirect) | semmle.label | SSA param(redirect) | | main.go:68:17:68:24 | redirect | semmle.label | 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 | @@ -59,5 +59,5 @@ nodes | 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 | subpaths -| 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:17:68:24 | SSA def(redirect) | main.go:73:9:73:28 | call to Clean | main.go:77:25:77:39 | call to getTarget1 | +| main.go:11:37:11:44 | redirect | BadRedirectCheck.go:3:18:3:22 | SSA param(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:17:68:24 | SSA param(redirect) | main.go:73:9:73:28 | call to Clean | main.go:77:25:77:39 | call to getTarget1 | From fb0f33d962c3807e6846cf275cdd9644f1158a4f Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Tue, 20 Oct 2026 21:57:40 +0100 Subject: [PATCH 4/9] Add expected failures for type-switch SSA writes These tests fail until type-switch implicit variable assignments are modeled as write instructions in the next commit. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../semmle/go/dataflow/Switch/DataFlow.expected | 3 +++ .../Security/CWE-681/IncorrectIntegerConversion.expected | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/go/ql/test/library-tests/semmle/go/dataflow/Switch/DataFlow.expected b/go/ql/test/library-tests/semmle/go/dataflow/Switch/DataFlow.expected index 42831abaf155..51635b429982 100644 --- a/go/ql/test/library-tests/semmle/go/dataflow/Switch/DataFlow.expected +++ b/go/ql/test/library-tests/semmle/go/dataflow/Switch/DataFlow.expected @@ -1,2 +1,5 @@ invalidModelRow testFailures +| switch.go:83:49:83:87 | comment | Missing result: hasValueFlow="call to typeSwitch1" | +| switch.go:84:49:84:87 | comment | Missing result: hasValueFlow="call to typeSwitch1" | +| switch.go:85:49:85:87 | comment | Missing result: hasValueFlow="call to typeSwitch1" | diff --git a/go/ql/test/query-tests/Security/CWE-681/IncorrectIntegerConversion.expected b/go/ql/test/query-tests/Security/CWE-681/IncorrectIntegerConversion.expected index e69de29bb2d1..fd1cb6a1be07 100644 --- a/go/ql/test/query-tests/Security/CWE-681/IncorrectIntegerConversion.expected +++ b/go/ql/test/query-tests/Security/CWE-681/IncorrectIntegerConversion.expected @@ -0,0 +1,5 @@ +| IncorrectIntegerConversion.go:493:40:493:50 | comment | Missing result: Source | +| IncorrectIntegerConversion.go:501:23:501:32 | comment | Missing result: Alert | +| IncorrectIntegerConversion.go:504:15:504:24 | comment | Missing result: Alert | +| IncorrectIntegerConversion.go:506:15:506:24 | comment | Missing result: Alert | +| IncorrectIntegerConversion.go:508:23:508:32 | comment | Missing result: Alert | From 786995d3b58aa5dad4823559c5e10745f8aab486 Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Tue, 20 Oct 2026 21:58:56 +0100 Subject: [PATCH 5/9] Fix type-switch SSA writes --- go/ql/lib/semmle/go/controlflow/IR.qll | 37 ++++++++++++++++--- .../go/dataflow/Switch/DataFlow.expected | 3 -- .../IncorrectIntegerConversion.expected | 5 --- 3 files changed, 32 insertions(+), 13 deletions(-) diff --git a/go/ql/lib/semmle/go/controlflow/IR.qll b/go/ql/lib/semmle/go/controlflow/IR.qll index 9afef72e5df5..4deadc3b5af9 100644 --- a/go/ql/lib/semmle/go/controlflow/IR.qll +++ b/go/ql/lib/semmle/go/controlflow/IR.qll @@ -491,6 +491,8 @@ module IR { lhs = MkLhs(this, _) or lhs = MkResultWriteTarget(this) + or + lhs = MkTypeSwitchImplicitVariableTarget(this, _) ) and initialization = false or @@ -1012,14 +1014,13 @@ module IR { * An instruction corresponding to the implicit declaration and assignment of a variable * in a type switch case clause. */ - class TypeSwitchImplicitVariableInstruction extends Instruction { + class TypeSwitchImplicitVariableInstruction extends WriteInstruction { CaseClause cc; TypeSwitchImplicitVariableInstruction() { typeSwitchCaseMatch(this, cc) } - override predicate writes(ValueEntity v, Instruction rhs) { - v = cc.getImplicitlyDeclaredVariable() and - exists(TypeSwitchStmt ts | cc = ts.getACase() | rhs = evalExprInstruction(ts.getExpr())) + override Instruction getRhs() { + exists(TypeSwitchStmt ts | cc = ts.getACase() and result = evalExprInstruction(ts.getExpr())) } } @@ -1108,6 +1109,10 @@ module IR { exists(ret.getEnclosingFunction().getResultVar(idx)) and exists(ret.getAnExpr()) ) + } or + /** An implicitly declared variable in a type-switch case. */ + MkTypeSwitchImplicitVariableTarget(ControlFlow::Node w, LocalVariable v) { + exists(CaseClause cc | typeSwitchCaseMatch(w, cc) and v = cc.getImplicitlyDeclaredVariable()) } /** A representation of the target of a write instruction. */ @@ -1115,7 +1120,13 @@ module IR { ControlFlow::Node w; WriteTarget() { - this = MkLhs(w, _) or this = MkLiteralElementTarget(w) or this = MkResultWriteTarget(w) + this = MkLhs(w, _) + or + this = MkLiteralElementTarget(w) + or + this = MkResultWriteTarget(w) + or + this = MkTypeSwitchImplicitVariableTarget(w, _) } /** Gets the write instruction of which this is the target. */ @@ -1158,6 +1169,22 @@ module IR { } } + /** An implicitly declared variable used as the target of a type-switch case write. */ + class ImplicitVariableTarget extends WriteTarget { + LocalVariable variable; + + ImplicitVariableTarget() { this = MkTypeSwitchImplicitVariableTarget(_, variable) } + + override predicate refersTo(ValueEntity e) { e = variable } + + override string getName() { result = variable.getName() } + + /** Gets the variable this target refers to. */ + Variable getVariable() { result = variable } + + override Location getLocation() { result = variable.getLocation() } + } + /** A reference to a variable or constant, used as the target of a write. */ class VarOrConstTarget extends WriteTarget { Expr loc; diff --git a/go/ql/test/library-tests/semmle/go/dataflow/Switch/DataFlow.expected b/go/ql/test/library-tests/semmle/go/dataflow/Switch/DataFlow.expected index 51635b429982..42831abaf155 100644 --- a/go/ql/test/library-tests/semmle/go/dataflow/Switch/DataFlow.expected +++ b/go/ql/test/library-tests/semmle/go/dataflow/Switch/DataFlow.expected @@ -1,5 +1,2 @@ invalidModelRow testFailures -| switch.go:83:49:83:87 | comment | Missing result: hasValueFlow="call to typeSwitch1" | -| switch.go:84:49:84:87 | comment | Missing result: hasValueFlow="call to typeSwitch1" | -| switch.go:85:49:85:87 | comment | Missing result: hasValueFlow="call to typeSwitch1" | diff --git a/go/ql/test/query-tests/Security/CWE-681/IncorrectIntegerConversion.expected b/go/ql/test/query-tests/Security/CWE-681/IncorrectIntegerConversion.expected index fd1cb6a1be07..e69de29bb2d1 100644 --- a/go/ql/test/query-tests/Security/CWE-681/IncorrectIntegerConversion.expected +++ b/go/ql/test/query-tests/Security/CWE-681/IncorrectIntegerConversion.expected @@ -1,5 +0,0 @@ -| IncorrectIntegerConversion.go:493:40:493:50 | comment | Missing result: Source | -| IncorrectIntegerConversion.go:501:23:501:32 | comment | Missing result: Alert | -| IncorrectIntegerConversion.go:504:15:504:24 | comment | Missing result: Alert | -| IncorrectIntegerConversion.go:506:15:506:24 | comment | Missing result: Alert | -| IncorrectIntegerConversion.go:508:23:508:32 | comment | Missing result: Alert | From 7d8b19ec9a98298916a0a4930c315ebe7e0c4e33 Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Tue, 20 Oct 2026 17:14:45 +0100 Subject: [PATCH 6/9] Document shared Go SSA migration Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- go/ql/lib/change-notes/2026-10-20-shared-ssa.md | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 go/ql/lib/change-notes/2026-10-20-shared-ssa.md diff --git a/go/ql/lib/change-notes/2026-10-20-shared-ssa.md b/go/ql/lib/change-notes/2026-10-20-shared-ssa.md new file mode 100644 index 000000000000..3e79a993c297 --- /dev/null +++ b/go/ql/lib/change-notes/2026-10-20-shared-ssa.md @@ -0,0 +1,4 @@ +--- +category: breaking +--- +* The Go SSA API now uses the shared SSA classes. `SsaVariable`, `SsaExplicitDefinition`, `SsaVariableCapture`, and `SsaPhiNode` have been replaced by `SsaDefinition`, `SsaExplicitWrite`, `SsaUncertainWrite`, and `SsaPhiDefinition`, respectively. Deprecated compatibility classes are available for the old names. From b759d3fcd3e2be866bd01dfd8703a2eeda86c6f2 Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Wed, 21 Oct 2026 12:02:24 +0100 Subject: [PATCH 7/9] Implement variable capture library --- .../VariableCaptureConsistency.ql | 1 + .../2026-10-21-variable-capture.md | 4 + .../go/dataflow/internal/DataFlowDispatch.qll | 2 +- .../go/dataflow/internal/DataFlowNodes.qll | 80 ++++++++- .../go/dataflow/internal/DataFlowPrivate.qll | 61 ++++--- .../go/dataflow/internal/DataFlowUtil.qll | 18 +- .../go/dataflow/internal/VariableCapture.qll | 111 ++++++++++++ .../dataflow/FlowSteps/LocalFlowStep.expected | 10 +- .../go/dataflow/PostUpdateNodes/test.expected | 4 + .../dataflow/VariableCapture/Flows.expected | 0 .../go/dataflow/VariableCapture/Flows.ql | 2 + .../go/dataflow/VariableCapture/test.go | 165 ++++++++++++++++++ .../frameworks/Twirp/RequestForgery.expected | 12 +- .../UnhandledCloseWritableHandle.expected | 12 +- 14 files changed, 437 insertions(+), 45 deletions(-) create mode 100644 go/ql/consistency-queries/VariableCaptureConsistency.ql create mode 100644 go/ql/lib/change-notes/2026-10-21-variable-capture.md create mode 100644 go/ql/lib/semmle/go/dataflow/internal/VariableCapture.qll create mode 100644 go/ql/test/library-tests/semmle/go/dataflow/VariableCapture/Flows.expected create mode 100644 go/ql/test/library-tests/semmle/go/dataflow/VariableCapture/Flows.ql create mode 100644 go/ql/test/library-tests/semmle/go/dataflow/VariableCapture/test.go diff --git a/go/ql/consistency-queries/VariableCaptureConsistency.ql b/go/ql/consistency-queries/VariableCaptureConsistency.ql new file mode 100644 index 000000000000..412474627cf2 --- /dev/null +++ b/go/ql/consistency-queries/VariableCaptureConsistency.ql @@ -0,0 +1 @@ +import semmle.go.dataflow.internal.VariableCapture::Flow::ConsistencyChecks diff --git a/go/ql/lib/change-notes/2026-10-21-variable-capture.md b/go/ql/lib/change-notes/2026-10-21-variable-capture.md new file mode 100644 index 000000000000..21def3d1ca9a --- /dev/null +++ b/go/ql/lib/change-notes/2026-10-21-variable-capture.md @@ -0,0 +1,4 @@ +--- +category: minorAnalysis +--- +* Data flow through captured variables now uses the shared variable capture library, keeping captures associated with their closure objects rather than using context-insensitive jumps. diff --git a/go/ql/lib/semmle/go/dataflow/internal/DataFlowDispatch.qll b/go/ql/lib/semmle/go/dataflow/internal/DataFlowDispatch.qll index 10455f84edba..9f802cff673e 100644 --- a/go/ql/lib/semmle/go/dataflow/internal/DataFlowDispatch.qll +++ b/go/ql/lib/semmle/go/dataflow/internal/DataFlowDispatch.qll @@ -108,7 +108,7 @@ DataFlowCallable viableCallable(DataFlowCall ma) { } private int parameterPosition() { - result = [-1 .. any(DataFlowCallable c).getType().getNumParameter()] + result = [-2 .. any(DataFlowCallable c).getType().getNumParameter()] } /** A parameter position represented by an integer. */ diff --git a/go/ql/lib/semmle/go/dataflow/internal/DataFlowNodes.qll b/go/ql/lib/semmle/go/dataflow/internal/DataFlowNodes.qll index be6ece3e411b..a5b0f76d8560 100644 --- a/go/ql/lib/semmle/go/dataflow/internal/DataFlowNodes.qll +++ b/go/ql/lib/semmle/go/dataflow/internal/DataFlowNodes.qll @@ -8,6 +8,7 @@ private import semmle.go.dataflow.SsaImpl as SsaImpl private import DataFlowPrivate private import FlowSummaryImpl as FlowSummaryImpl private import semmle.go.dataflow.ExternalFlow +private import VariableCapture as VariableCapture cached private newtype TNode = @@ -20,7 +21,9 @@ private newtype TNode = } or MkSliceElementNode(SliceExpr se) or MkFlowSummaryNode(FlowSummaryImpl::Private::SummaryNode sn) or - MkDefaultPostUpdateNode(IR::Instruction insn) { insnHasPostUpdateNode(insn) } + MkDefaultPostUpdateNode(IR::Instruction insn) { insnHasPostUpdateNode(insn) } or + MkCaptureNode(VariableCapture::Flow::SynthesizedCaptureNode capture) or + MkCapturedVariablesParameterNode(FuncLit function) /** Nodes intended for only use inside the data-flow libraries. */ module Private { @@ -107,6 +110,63 @@ module Private { none() } } + + /** A synthesized access to captured storage. */ + class CaptureNode extends Node, MkCaptureNode { + VariableCapture::Flow::SynthesizedCaptureNode getSynthesizedCaptureNode() { + this = MkCaptureNode(result) + } + + override ControlFlow::Root getRoot() { + result = this.getSynthesizedCaptureNode().getEnclosingCallable() + } + + override Type getType() { + exists(VariableCapture::CapturedVariable v | + this.getSynthesizedCaptureNode().isVariableAccess(v) and + result = v.getType() + ) + or + this.getSynthesizedCaptureNode().isInstanceAccess() and + result = this.getRoot().(FuncLit).getType() + } + + override string getNodeKind() { result = "captured variable" } + + override string toString() { result = this.getSynthesizedCaptureNode().toString() } + + override Location getLocation() { result = this.getSynthesizedCaptureNode().getLocation() } + } + + /** The closure object passed implicitly when invoking a function literal. */ + class CapturedVariablesParameterNode extends ParameterNode, MkCapturedVariablesParameterNode { + FuncLit getFunction() { this = MkCapturedVariablesParameterNode(result) } + + override predicate isParameterOf(DataFlowCallable c, int i) { + c.asCallable().getFuncDef() = this.getFunction() and i = -2 + } + + override ControlFlow::Root getRoot() { result = this.getFunction() } + + override Type getType() { result = this.getFunction().getType() } + + override string getNodeKind() { result = "captured variables parameter" } + + override string toString() { result = "captured variables" } + + override Location getLocation() { result = this.getFunction().getLocation() } + } + + private class CapturePostUpdateNode extends CaptureNode, PostUpdateNode { + CaptureNode pre; + + CapturePostUpdateNode() { + VariableCapture::Flow::capturePostUpdateNode(this.getSynthesizedCaptureNode(), + pre.getSynthesizedCaptureNode()) + } + + override Node getPreUpdateNode() { result = pre } + } } /** Nodes intended for use outside the data-flow libraries. */ @@ -472,9 +532,19 @@ module Public { * pointless recomputation of `getACallee()` each recursive iteration. */ private DataFlow::Node getACalleeSource(DataFlow::CallNode cn) { - result = cn.getCalleeNode() or - basicLocalFlowStep(result, getACalleeSource(cn)) or - jumpStep(result, getACalleeSource(cn)) or + result = cn.getCalleeNode() + or + basicLocalFlowStep(result, getACalleeSource(cn)) + or + jumpStep(result, getACalleeSource(cn)) + or + // every write to a captured function variable + exists(SsaSourceVariable v, IR::WriteInstruction write | + v.isCaptured() and + getACalleeSource(cn).asInstruction().reads(v) and + write.writes(v, result.asInstruction()) + ) + or result.asExpr() = getACalleeSource(cn).asExpr().(GenericFunctionInstantiationExpr).getBase() } @@ -854,6 +924,8 @@ module Public { /** Holds if the node corresponding to `insn` has a post-update node. */ predicate insnHasPostUpdateNode(IR::Instruction insn) { + insn = IR::evalExprInstruction(any(CallExpr call).getCalleeExpr()) + or exists(Expr e | insn.(IR::EvalInstruction).getExpr() = e | e instanceof AddressExpr or e = any(AddressExpr ae).getOperand() or diff --git a/go/ql/lib/semmle/go/dataflow/internal/DataFlowPrivate.qll b/go/ql/lib/semmle/go/dataflow/internal/DataFlowPrivate.qll index fbbbe0172a9a..d15a36c780f7 100644 --- a/go/ql/lib/semmle/go/dataflow/internal/DataFlowPrivate.qll +++ b/go/ql/lib/semmle/go/dataflow/internal/DataFlowPrivate.qll @@ -11,6 +11,7 @@ private import FlowSummaryImpl as FlowSummaryImpl private import semmle.go.dataflow.FlowSummary as FlowSummary private import semmle.go.dataflow.ExternalFlow private import codeql.util.Unit +private import VariableCapture as VariableCapture import DataFlowNodes::Private private newtype TReturnKind = @@ -72,6 +73,7 @@ predicate basicLocalFlowStep(Node nodeFrom, Node nodeTo) { or // Instruction -> SSA defn exists(IR::Instruction pred, SsaExplicitWrite succ | + not succ.getSourceVariable() instanceof VariableCapture::CapturedVariable and succ.getDefinition().getRhs() = pred and ( nodeFrom = instructionNode(pred) or @@ -82,6 +84,7 @@ predicate basicLocalFlowStep(Node nodeFrom, Node nodeTo) { or // SSA defn -> first SSA use exists(SsaDefinition pred, IR::Instruction succ | SsaImpl::firstUse(pred, succ) | + not pred.getSourceVariable() instanceof VariableCapture::CapturedVariable and (pred instanceof SsaExplicitWrite or pred instanceof SsaUncertainWrite) and nodeFrom = ssaNode(pred) and nodeTo = instructionNode(succ) @@ -90,6 +93,7 @@ predicate basicLocalFlowStep(Node nodeFrom, Node nodeTo) { // SSA use -> successive SSA use // Note this case includes Phi node traversal exists(IR::Instruction pred, IR::Instruction succ | succ = getAnAdjacentUse(pred) | + not exists(VariableCapture::CapturedVariable v | pred.reads(v)) and ( nodeFrom = instructionNode(pred) or nodeFrom.(PostUpdateNode).getPreUpdateNode() = instructionNode(pred) @@ -97,6 +101,8 @@ predicate basicLocalFlowStep(Node nodeFrom, Node nodeTo) { nodeTo = instructionNode(succ) and nodeTo != nodeFrom ) + or + VariableCapture::localFlowStep(nodeFrom, nodeTo) } pragma[noinline] @@ -126,23 +132,6 @@ predicate jumpStep(Node n1, Node n2) { isValueEntityRead(v, n2) ) or - exists(SsaExplicitWrite def, SsaUncertainWrite succ | - succ.getSourceVariable() = def.getSourceVariable() and - n2 = ssaNode(succ) - | - not SsaImpl::firstUse(def, _) and n1 = ssaNode(def) - or - exists(IR::Instruction lastUse | - exists(IR::Instruction firstUse | - SsaImpl::firstUse(def, firstUse) and lastUse = getAnAdjacentUse*(firstUse) - ) and - not exists(getAnAdjacentUse(lastUse)) - | - n1 = instructionNode(lastUse) or - n1.(DataFlow::PostUpdateNode).getPreUpdateNode() = instructionNode(lastUse) - ) - ) - or // If a channel-typed field is referenced exactly once in the context of // a send statement and once in a receive expression, assume the two are linked. exists( @@ -185,6 +174,8 @@ predicate storeStep(Node node1, ContentSet cs, Node node2) { c = any(DataFlow::PointerContent pc | pc.getPointerType() = node2.getType()) or containerStoreStep(node1, node2, c) + or + VariableCapture::storeStep(node1, c, node2) ) or FlowSummaryImpl::Private::Steps::summaryStoreStep(node1.(FlowSummaryNode).getSummaryNode(), cs, @@ -208,6 +199,8 @@ predicate readStep(Node node1, ContentSet cs, Node node2) { ) or containerReadStep(node1, node2, c) + or + VariableCapture::readStep(node1, c, node2) ) or FlowSummaryImpl::Private::Steps::summaryReadStep(node1.(FlowSummaryNode).getSummaryNode(), cs, @@ -222,14 +215,11 @@ predicate readStep(Node node1, ContentSet cs, Node node2) { * Holds if values stored inside content `c` are cleared at node `n`. */ predicate clearsContent(Node n, ContentSet c) { - // Because our post-update nodes are shared between multiple pre-update - // nodes, attempting to clear content causes summary stores into arg in - // particular to malfunction. - none() - // c instanceof FieldContent and - // FlowSummaryImpl::Private::Steps::summaryStoresIntoArg(c, n) - // or - // FlowSummaryImpl::Private::Steps::summaryClearsContent(n, c) + // TODO: Add summaryClearsContent for FlowSummaryNodes and clearing for definite field + // overwrites. First establish with regression tests that use-use flow cannot bypass + // summary clearing via pre-update nodes, and that overwrite rules only clear content + // that is definitely replaced, rather than merely stored into. + VariableCapture::clearsContent(n, c.asOneContent()) } /** @@ -357,7 +347,7 @@ class DataFlowCall extends Expr { /** * Gets the nth argument for this call. */ - Node getArgument(int n) { result = call.getArgument(n) } + ArgumentNode getArgument(int n) { result.argumentOf(this, n) } /** Gets the data flow node corresponding to this call. */ ExprNode getNode() { result = call } @@ -438,13 +428,16 @@ predicate forceHighPrecision(Content c) { /** * Gets the `i`th argument of call `c`, where the receiver of a method call - * counts as argument -1. + * counts as argument -1 and the closure object counts as argument -2. */ Node getArgument(CallNode c, int i) { result = c.getArgument(i) or result = c.(MethodCallNode).getReceiver() and i = -1 + or + result = exprNode(c.asExpr().(CallExpr).getCalleeExpr()) and + i = -2 } /** Holds if `n` should be hidden from path explanations. */ @@ -453,10 +446,17 @@ predicate nodeIsHidden(Node n) { n instanceof FlowSummaryNode } class LambdaCallKind = Unit; /** Holds if `creation` is an expression that creates a lambda of kind `kind` for `c`. */ -predicate lambdaCreation(Node creation, LambdaCallKind kind, DataFlowCallable c) { none() } +predicate lambdaCreation(Node creation, LambdaCallKind kind, DataFlowCallable c) { + creation.asExpr() = c.asCallable().asFuncLit() and + exists(kind) +} /** Holds if `call` is a lambda call of kind `kind` where `receiver` is the lambda expression. */ -predicate lambdaCall(DataFlowCall call, LambdaCallKind kind, Node receiver) { none() } +predicate lambdaCall(DataFlowCall call, LambdaCallKind kind, Node receiver) { + not exists(call.(CallExpr).getTarget()) and + receiver = call.getNode().(CallNode).getCalleeNode() and + exists(kind) +} /** Extra data-flow steps needed for lambda flow analysis. */ predicate additionalLambdaFlowStep(Node nodeFrom, Node nodeTo, boolean preservesValue) { none() } @@ -475,6 +475,9 @@ class DataFlowSecondLevelScope = Unit; * by default as a heuristic. */ predicate allowParameterReturnInSelf(ParameterNode p) { + VariableCapture::Flow::heuristicAllowInstanceParameterReturnInSelf(p.(CapturedVariablesParameterNode) + .getFunction()) + or exists(DataFlowCallable c, int pos | p.isParameterOf(c, pos) and FlowSummaryImpl::Private::summaryAllowParameterReturnInSelf(c.asSummarizedCallable(), pos) diff --git a/go/ql/lib/semmle/go/dataflow/internal/DataFlowUtil.qll b/go/ql/lib/semmle/go/dataflow/internal/DataFlowUtil.qll index c450244480ca..42d0ee2cc077 100644 --- a/go/ql/lib/semmle/go/dataflow/internal/DataFlowUtil.qll +++ b/go/ql/lib/semmle/go/dataflow/internal/DataFlowUtil.qll @@ -11,6 +11,7 @@ private import semmle.go.dataflow.ExternalFlow private import DataFlowPrivate private import FlowSummaryImpl as FlowSummaryImpl private import codeql.util.Unit +private import VariableCapture as VariableCapture import DataFlowNodes::Public /** @@ -160,7 +161,8 @@ private newtype TContent = TPointerContent(PointerType p) or TMapKeyContent() or TMapValueContent() or - TSyntheticFieldContent(SyntheticField s) + TSyntheticFieldContent(SyntheticField s) or + TCapturedVariableContent(VariableCapture::CapturedVariable v) /** * A reference contained in an object. Examples include instance fields, the @@ -267,6 +269,20 @@ class SyntheticFieldContent extends Content, TSyntheticFieldContent { override string toString() { result = s.toString() } } +/** A variable stored in a closure object. */ +class CapturedVariableContent extends Content, TCapturedVariableContent { + VariableCapture::CapturedVariable v; + + CapturedVariableContent() { this = TCapturedVariableContent(v) } + + /** Gets the captured variable. */ + VariableCapture::CapturedVariable getVariable() { result = v } + + override string toString() { result = "captured " + v.getName() } + + override Location getLocation() { result = v.getLocation() } +} + private newtype TContentSet = TOneContent(Content c) or TAllContent() diff --git a/go/ql/lib/semmle/go/dataflow/internal/VariableCapture.qll b/go/ql/lib/semmle/go/dataflow/internal/VariableCapture.qll new file mode 100644 index 000000000000..b65585cf6319 --- /dev/null +++ b/go/ql/lib/semmle/go/dataflow/internal/VariableCapture.qll @@ -0,0 +1,111 @@ +/** Provides flow through variables captured by Go function literals. */ +overlay[local?] +module; + +private import go +private import semmle.go.controlflow.ControlFlowGraphImpl +private import codeql.dataflow.VariableCapture as Shared +private import DataFlowPrivate +private import DataFlowUtil + +private module CaptureInput implements Shared::InputSig { + private import go as G + + class Callable extends ControlFlow::Root { + predicate isConstructor() { none() } + } + + Callable basicBlockGetEnclosingCallable(BasicBlock bb) { result = bb.getScope() } + + class CapturedVariable extends SsaSourceVariable { + CapturedVariable() { this.isCaptured() } + + Callable getCallable() { result = this.getDeclaringFunction() } + } + + class CapturedParameter extends CapturedVariable instanceof Parameter { } + + class Expr extends IR::Instruction { + predicate hasCfgNode(BasicBlock bb, int i) { this = bb.getNode(i) } + } + + class VariableWrite extends IR::WriteInstruction { + CapturedVariable v; + + VariableWrite() { + this.writes(v, _) and + not this instanceof IR::InitParameterInstruction + } + + CapturedVariable getVariable() { result = v } + + predicate hasCfgNode(BasicBlock bb, int i) { this = bb.getNode(i) } + } + + class VariableRead extends Expr { + CapturedVariable v; + + VariableRead() { this.reads(v) } + + CapturedVariable getVariable() { result = v } + } + + private predicate closureFlowStep(IR::Instruction nodeFrom, IR::Instruction nodeTo) { + exists(SsaDefinition def, SsaExplicitWrite write | + write = def.getAnUltimateDefinition() and + nodeFrom = write.getDefinition().getRhs() and + nodeTo = IR::evalExprInstruction(def.getARead()) + ) + or + exists(G::Expr e | + nodeTo = IR::evalExprInstruction(e) and + nodeFrom = IR::evalExprInstruction(e.(ConversionExpr).getOperand()) + ) + } + + class ClosureExpr extends Expr { + ClosureExpr() { this.(IR::EvalInstruction).getExpr() instanceof FuncLit } + + predicate hasBody(Callable body) { body = this.(IR::EvalInstruction).getExpr() } + + predicate hasAliasedAccess(Expr e) { + closureFlowStep*(this, e) and + not closureFlowStep(e, _) + } + } +} + +class CapturedVariable = CaptureInput::CapturedVariable; + +module Flow = Shared::Flow; + +private Flow::ClosureNode asClosureNode(Node n) { + result = n.(CaptureNode).getSynthesizedCaptureNode() + or + result.(Flow::ExprNode).getExpr() = n.asInstruction() + or + result.(Flow::ExprPostUpdateNode).getExpr() = + n.(PostUpdateNode).getPreUpdateNode().asInstruction() + or + result.(Flow::ParameterNode).getParameter() = n.asParameter() + or + result.(Flow::ThisParameterNode).getCallable() = n.(CapturedVariablesParameterNode).getFunction() + or + result.(Flow::VariableWriteSourceNode).getVariableWrite().getRhs() = n.asInstruction() +} + +predicate storeStep(Node nodeFrom, CapturedVariableContent c, Node nodeTo) { + Flow::storeStep(asClosureNode(nodeFrom), c.getVariable(), asClosureNode(nodeTo)) +} + +predicate readStep(Node nodeFrom, CapturedVariableContent c, Node nodeTo) { + Flow::readStep(asClosureNode(nodeFrom), c.getVariable(), asClosureNode(nodeTo)) +} + +predicate clearsContent(Node n, CapturedVariableContent c) { + Flow::clearsContent(asClosureNode(n), c.getVariable()) +} + +predicate localFlowStep(Node nodeFrom, Node nodeTo) { + Flow::localFlowStep(asClosureNode(nodeFrom), asClosureNode(nodeTo)) +} diff --git a/go/ql/test/library-tests/semmle/go/dataflow/FlowSteps/LocalFlowStep.expected b/go/ql/test/library-tests/semmle/go/dataflow/FlowSteps/LocalFlowStep.expected index 3fc51cc6d7ea..3cdc02273fe2 100644 --- a/go/ql/test/library-tests/semmle/go/dataflow/FlowSteps/LocalFlowStep.expected +++ b/go/ql/test/library-tests/semmle/go/dataflow/FlowSteps/LocalFlowStep.expected @@ -17,10 +17,12 @@ | main.go:10:12:10:12 | y | main.go:10:17:10:17 | y | | main.go:10:17:10:27 | ...>=... | main.go:10:7:10:27 | After ...&&... | | main.go:11:14:11:14 | z | main.go:11:9:11:15 | type conversion | -| main.go:15:9:15:9 | 0 | main.go:15:2:15:9 | SSA def(acc) | -| main.go:16:9:19:2 | SSA implicit def(acc) | main.go:17:3:17:5 | acc | -| main.go:17:3:17:7 | SSA def(acc) | main.go:18:10:18:12 | acc | -| main.go:17:3:17:7 | increment statement | main.go:17:3:17:7 | SSA def(acc) | +| main.go:15:9:15:9 | 0 | main.go:16:9:19:2 | acc | +| main.go:16:9:19:2 | captured variables | main.go:17:3:17:5 | this | +| main.go:17:3:17:5 | this | main.go:17:3:17:7 | this | +| main.go:17:3:17:5 | this | main.go:17:3:17:7 | this | +| main.go:17:3:17:7 | this | main.go:18:10:18:12 | this | +| main.go:17:3:17:7 | this | main.go:18:10:18:12 | this | | main.go:22:12:22:12 | SSA param(b) | main.go:23:5:23:5 | b | | main.go:22:12:22:12 | b | main.go:22:12:22:12 | SSA param(b) | | main.go:22:20:22:20 | SSA param(x) | main.go:24:10:24:10 | x | diff --git a/go/ql/test/library-tests/semmle/go/dataflow/PostUpdateNodes/test.expected b/go/ql/test/library-tests/semmle/go/dataflow/PostUpdateNodes/test.expected index f0d15090e67f..bd52dc71ca70 100644 --- a/go/ql/test/library-tests/semmle/go/dataflow/PostUpdateNodes/test.expected +++ b/go/ql/test/library-tests/semmle/go/dataflow/PostUpdateNodes/test.expected @@ -19,8 +19,12 @@ | test.go:26:2:26:12 | selection of cptr | test.go:26:2:26:12 | selection of cptr [postupdate] | | test.go:28:7:28:10 | struct literal | test.go:28:7:28:10 | struct literal [postupdate] | | test.go:29:2:29:2 | c | test.go:29:2:29:2 | c [postupdate] | +| test.go:29:2:29:4 | selection of m | test.go:29:2:29:4 | selection of m [postupdate] | | test.go:29:6:29:6 | a | test.go:29:6:29:6 | a [postupdate] | | test.go:30:2:30:2 | c | test.go:30:2:30:2 | c [postupdate] | +| test.go:30:2:30:5 | selection of mp | test.go:30:2:30:5 | selection of mp [postupdate] | | test.go:30:7:30:7 | a | test.go:30:7:30:7 | a [postupdate] | +| test.go:35:2:35:2 | f | test.go:35:2:35:2 | f [postupdate] | | test.go:35:4:35:4 | a | test.go:35:4:35:4 | a [postupdate] | +| test.go:36:2:36:3 | fp | test.go:36:2:36:3 | fp [postupdate] | | test.go:36:5:36:5 | a | test.go:36:5:36:5 | a [postupdate] | diff --git a/go/ql/test/library-tests/semmle/go/dataflow/VariableCapture/Flows.expected b/go/ql/test/library-tests/semmle/go/dataflow/VariableCapture/Flows.expected new file mode 100644 index 000000000000..e69de29bb2d1 diff --git a/go/ql/test/library-tests/semmle/go/dataflow/VariableCapture/Flows.ql b/go/ql/test/library-tests/semmle/go/dataflow/VariableCapture/Flows.ql new file mode 100644 index 000000000000..7c893f59e87b --- /dev/null +++ b/go/ql/test/library-tests/semmle/go/dataflow/VariableCapture/Flows.ql @@ -0,0 +1,2 @@ +import utils.test.InlineFlowTest +import ValueFlowTest diff --git a/go/ql/test/library-tests/semmle/go/dataflow/VariableCapture/test.go b/go/ql/test/library-tests/semmle/go/dataflow/VariableCapture/test.go new file mode 100644 index 000000000000..3e442a905186 --- /dev/null +++ b/go/ql/test/library-tests/semmle/go/dataflow/VariableCapture/test.go @@ -0,0 +1,165 @@ +package capture + +func source() string { return "" } +func sink(string) {} + +var packageClosure = func() {} + +func direct() { + x := source() + f := func() { sink(x) } // $ hasValueFlow="x" + f() +} + +func overwritten() { + x := source() + f := func() { sink(x) } + x = "safe" + f() +} + +func assignedAfterCreation() { + x := "safe" + f := func() { sink(x) } // $ hasValueFlow="x" + x = source() + f() +} + +func writeBack() { + x := "safe" + f := func() { x = source() } + f() + sink(x) // $ hasValueFlow="x" +} + +func siblingClosures() { + x := "safe" + set := func() { x = source() } + get := func() { sink(x) } // $ hasValueFlow="x" + set() + get() +} + +func nested() { + x := source() + f := func() func() { + return func() { sink(x) } // $ hasValueFlow="x" + } + f()() +} + +func captureParameter(x string) func() string { + return func() string { return x } +} + +func separateInvocations() { + bad := captureParameter(source()) + good := captureParameter("safe") + sink(bad()) // $ hasValueFlow="call to bad" + sink(good()) +} + +func copyBetweenCaptures() { + x := source() + y := "safe" + f := func() { y = x } + f() + sink(y) // $ hasValueFlow="y" +} + +func multipleWrites() { + x := source() + x = "safe" + sink(x) + f := func() { sink(x) } + f() +} + +func tuple() (string, bool) { return source(), true } + +func tupleWrite() { + x, _ := tuple() + f := func() { sink(x) } // $ hasValueFlow="x" + f() +} + +func rangeWrite() { + for _, x := range []string{source()} { + f := func() { sink(x) } // $ hasValueFlow="x" + f() + } +} + +type receiver struct{ value string } + +func (r receiver) closure() func() string { + return func() string { return r.value } +} + +func capturedReceiver() { + r := receiver{source()} + sink(r.closure()()) // $ hasValueFlow="function call" +} + +func aliasedClosure(branch bool) { + x := "safe" + f := func() { sink(x) } // $ hasValueFlow="x" + g := func() {} + if branch { + g = f + } + x = source() + g() +} + +func nestedWriteBack() { + x := "safe" + f := func() { + g := func() { x = source() } + g() + } + f() + sink(x) // $ hasValueFlow="x" +} + +func capturedResult() (x string) { + f := func() { x = source() } + f() + return +} + +func namedResult() { + sink(capturedResult()) // $ hasValueFlow="call to capturedResult" +} + +func mutateCapturedPointer() { + x := &receiver{} + f := func() { x.value = source() } + f() + sink(x.value) // $ hasValueFlow="selection of value" +} + +func callback(f func()) { f() } + +func passedClosure() { + x := source() + callback(func() { sink(x) }) // $ hasValueFlow="x" +} + +func capturedCallee() { + handler := sink + func() { + handler(source()) // $ hasValueFlow="call to source" + }() +} + +func returnedWriter() (func(string), func() string) { + x := "safe" + return func(s string) { x = s }, func() string { return x } +} + +func sharedEscapedStorage() { + set, get := returnedWriter() + set(source()) + sink(get()) // $ MISSING: hasValueFlow="call to get" +} diff --git a/go/ql/test/library-tests/semmle/go/frameworks/Twirp/RequestForgery.expected b/go/ql/test/library-tests/semmle/go/frameworks/Twirp/RequestForgery.expected index 922e92e56860..e718d0517c84 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/Twirp/RequestForgery.expected +++ b/go/ql/test/library-tests/semmle/go/frameworks/Twirp/RequestForgery.expected @@ -7,9 +7,12 @@ edges | 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: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: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 implicit def(reqContent) | provenance | | -| rpc/notes/service.twirp.go:574:2:577:2 | SSA implicit def(reqContent) | rpc/notes/service.twirp.go:576:35:576:44 | reqContent | provenance | | +| rpc/notes/service.twirp.go:544:32:544:41 | reqContent [postupdate] | rpc/notes/service.twirp.go:574:2:577:2 | reqContent | provenance | | +| rpc/notes/service.twirp.go:574:2:577:2 | captured variables [captured reqContent] | rpc/notes/service.twirp.go:576:35:576:44 | this [captured reqContent] | provenance | | +| rpc/notes/service.twirp.go:574:2:577:2 | function literal [captured reqContent] | rpc/notes/service.twirp.go:574:2:577:2 | captured variables [captured reqContent] | provenance | | +| rpc/notes/service.twirp.go:574:2:577:2 | reqContent | rpc/notes/service.twirp.go:574:2:577:2 | function literal [captured reqContent] | provenance | | | rpc/notes/service.twirp.go:576:35:576:44 | reqContent | server/main.go:19:56:19:61 | SSA param(params) | provenance | | +| rpc/notes/service.twirp.go:576:35:576:44 | this [captured reqContent] | rpc/notes/service.twirp.go:576:35:576:44 | reqContent | provenance | | | server/main.go:19:56:19:61 | SSA param(params) | server/main.go:19:56:19:61 | SSA param(params) [Return] | provenance | | | server/main.go:19:56:19:61 | SSA param(params) | server/main.go:30:38:30:48 | selection of Text | provenance | | | server/main.go:19:56:19:61 | SSA param(params) | server/main.go:30:38:30:48 | selection of Text | provenance | | @@ -25,8 +28,11 @@ nodes | 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:32:544:41 | reqContent [postupdate] | semmle.label | reqContent [postupdate] | -| rpc/notes/service.twirp.go:574:2:577:2 | SSA implicit def(reqContent) | semmle.label | SSA implicit def(reqContent) | +| rpc/notes/service.twirp.go:574:2:577:2 | captured variables [captured reqContent] | semmle.label | captured variables [captured reqContent] | +| rpc/notes/service.twirp.go:574:2:577:2 | function literal [captured reqContent] | semmle.label | function literal [captured reqContent] | +| rpc/notes/service.twirp.go:574:2:577:2 | reqContent | semmle.label | reqContent | | rpc/notes/service.twirp.go:576:35:576:44 | reqContent | semmle.label | reqContent | +| rpc/notes/service.twirp.go:576:35:576:44 | this [captured reqContent] | semmle.label | this [captured reqContent] | | server/main.go:19:56:19:61 | SSA param(params) | semmle.label | SSA param(params) | | server/main.go:19:56:19:61 | SSA param(params) | semmle.label | SSA param(params) | | server/main.go:19:56:19:61 | SSA param(params) [Return] | semmle.label | SSA param(params) [Return] | diff --git a/go/ql/test/query-tests/InconsistentCode/UnhandledCloseWritableHandle/UnhandledCloseWritableHandle.expected b/go/ql/test/query-tests/InconsistentCode/UnhandledCloseWritableHandle/UnhandledCloseWritableHandle.expected index e51c2db4e8bb..1d36fe36aa88 100644 --- a/go/ql/test/query-tests/InconsistentCode/UnhandledCloseWritableHandle/UnhandledCloseWritableHandle.expected +++ b/go/ql/test/query-tests/InconsistentCode/UnhandledCloseWritableHandle/UnhandledCloseWritableHandle.expected @@ -10,8 +10,11 @@ | 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 | edges | tests.go:9:24:9:24 | SSA param(f) | tests.go:10:8:10:8 | f | provenance | | -| tests.go:13:32:13:32 | SSA param(f) | tests.go:14:13:16:2 | SSA implicit def(f) | provenance | | -| tests.go:14:13:16:2 | SSA implicit def(f) | tests.go:15:3:15:3 | f | provenance | | +| tests.go:13:32:13:32 | SSA param(f) | tests.go:18:8:18:11 | f | provenance | | +| tests.go:14:13:16:2 | captured variables [captured f] | tests.go:15:3:15:3 | this [captured f] | provenance | | +| tests.go:15:3:15:3 | this [captured f] | tests.go:15:3:15:3 | f | provenance | | +| tests.go:18:8:18:11 | cont [captured f] | tests.go:14:13:16:2 | captured variables [captured f] | provenance | | +| tests.go:18:8:18:11 | f | tests.go:18:8:18:11 | cont [captured 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 | extract:0 ... := ... | tests.go:34:29:34:29 | f | provenance | Src:MaD:1 | | tests.go:33:21:33:21 | f | tests.go:9:24:9:24 | SSA param(f) | provenance | | @@ -31,8 +34,11 @@ nodes | tests.go:9:24:9:24 | SSA param(f) | semmle.label | SSA param(f) | | tests.go:10:8:10:8 | f | semmle.label | f | | tests.go:13:32:13:32 | SSA param(f) | semmle.label | SSA param(f) | -| tests.go:14:13:16:2 | SSA implicit def(f) | semmle.label | SSA implicit def(f) | +| tests.go:14:13:16:2 | captured variables [captured f] | semmle.label | captured variables [captured f] | | tests.go:15:3:15:3 | f | semmle.label | f | +| tests.go:15:3:15:3 | this [captured f] | semmle.label | this [captured f] | +| tests.go:18:8:18:11 | cont [captured f] | semmle.label | cont [captured f] | +| tests.go:18:8:18:11 | f | semmle.label | f | | tests.go:32:5:32:78 | extract:0 ... := ... | semmle.label | extract:0 ... := ... | | tests.go:33:21:33:21 | f | semmle.label | f | | tests.go:34:29:34:29 | f | semmle.label | f | From b1bae78f4a2ce973c61d7c4f20bed9b850131524 Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Wed, 21 Oct 2026 13:26:46 +0100 Subject: [PATCH 8/9] Update data flow consistency test outputs --- .../CONSISTENCY/DataFlowConsistency.expected | 1 + .../CONSISTENCY/DataFlowConsistency.expected | 4 ++++ .../CONSISTENCY/DataFlowConsistency.expected | 1 + .../CONSISTENCY/DataFlowConsistency.expected | 17 +++++++++++++++++ .../CONSISTENCY/DataFlowConsistency.expected | 1 + 5 files changed, 24 insertions(+) create mode 100644 go/ql/test/library-tests/semmle/go/controlflow/ControlFlowGraph/CONSISTENCY/DataFlowConsistency.expected diff --git a/go/ql/test/library-tests/semmle/go/concepts/HTTP/CONSISTENCY/DataFlowConsistency.expected b/go/ql/test/library-tests/semmle/go/concepts/HTTP/CONSISTENCY/DataFlowConsistency.expected index 56f4c17d2240..e587a8c1d642 100644 --- a/go/ql/test/library-tests/semmle/go/concepts/HTTP/CONSISTENCY/DataFlowConsistency.expected +++ b/go/ql/test/library-tests/semmle/go/concepts/HTTP/CONSISTENCY/DataFlowConsistency.expected @@ -7,3 +7,4 @@ reverseRead | server.go:9:6:9:6 | implicit-deref r | Origin of readStep is missing a PostUpdateNode. | | server.go:10:6:10:6 | implicit-deref r | Origin of readStep is missing a PostUpdateNode. | | server.go:13:6:13:6 | implicit-deref r | Origin of readStep is missing a PostUpdateNode. | +| server.go:14:15:14:15 | implicit-deref r | Origin of readStep is missing a PostUpdateNode. | diff --git a/go/ql/test/library-tests/semmle/go/controlflow/ControlFlowGraph/CONSISTENCY/DataFlowConsistency.expected b/go/ql/test/library-tests/semmle/go/controlflow/ControlFlowGraph/CONSISTENCY/DataFlowConsistency.expected new file mode 100644 index 000000000000..cfa9f9a7a758 --- /dev/null +++ b/go/ql/test/library-tests/semmle/go/controlflow/ControlFlowGraph/CONSISTENCY/DataFlowConsistency.expected @@ -0,0 +1,4 @@ +reverseRead +| stmts7.go:23:2:23:8 | implicit-deref methods | Origin of readStep is missing a PostUpdateNode. | +| stmts7.go:27:8:27:15 | callback | Origin of readStep is missing a PostUpdateNode. | +| stmts7.go:28:9:28:17 | implicit-deref &... | Origin of readStep is missing a PostUpdateNode. | diff --git a/go/ql/test/library-tests/semmle/go/frameworks/Revel/CONSISTENCY/DataFlowConsistency.expected b/go/ql/test/library-tests/semmle/go/frameworks/Revel/CONSISTENCY/DataFlowConsistency.expected index c6c4611752d8..d51549a2c595 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/Revel/CONSISTENCY/DataFlowConsistency.expected +++ b/go/ql/test/library-tests/semmle/go/frameworks/Revel/CONSISTENCY/DataFlowConsistency.expected @@ -109,6 +109,7 @@ reverseRead | examples/booking/app/init.go:53:2:53:11 | implicit-deref selection of Response | Origin of readStep is missing a PostUpdateNode. | | examples/booking/app/init.go:54:2:54:2 | implicit-deref c | Origin of readStep is missing a PostUpdateNode. | | examples/booking/app/init.go:54:2:54:11 | implicit-deref selection of Response | Origin of readStep is missing a PostUpdateNode. | +| examples/booking/app/init.go:56:2:56:3 | fc | Origin of readStep is missing a PostUpdateNode. | | examples/booking/app/models/booking.go:33:13:33:19 | booking | Origin of readStep is missing a PostUpdateNode. | | examples/booking/app/models/booking.go:34:13:34:19 | booking | Origin of readStep is missing a PostUpdateNode. | | examples/booking/app/models/booking.go:35:13:35:19 | booking | Origin of readStep is missing a PostUpdateNode. | diff --git a/go/ql/test/library-tests/semmle/go/frameworks/Twirp/CONSISTENCY/DataFlowConsistency.expected b/go/ql/test/library-tests/semmle/go/frameworks/Twirp/CONSISTENCY/DataFlowConsistency.expected index 71165fc94b07..3ea0c1767269 100644 --- a/go/ql/test/library-tests/semmle/go/frameworks/Twirp/CONSISTENCY/DataFlowConsistency.expected +++ b/go/ql/test/library-tests/semmle/go/frameworks/Twirp/CONSISTENCY/DataFlowConsistency.expected @@ -20,19 +20,23 @@ reverseRead | rpc/notes/service.pb.go:335:13:335:13 | implicit-deref v | Origin of readStep is missing a PostUpdateNode. | | rpc/notes/service.pb.go:337:13:337:13 | implicit-deref v | Origin of readStep is missing a PostUpdateNode. | | rpc/notes/service.twirp.go:82:40:82:49 | clientOpts | Origin of readStep is missing a PostUpdateNode. | +| rpc/notes/service.twirp.go:94:17:94:17 | implicit-deref c | Origin of readStep is missing a PostUpdateNode. | | rpc/notes/service.twirp.go:118:37:118:37 | implicit-deref c | Origin of readStep is missing a PostUpdateNode. | | rpc/notes/service.twirp.go:118:47:118:52 | selection of opts | Origin of readStep is missing a PostUpdateNode. | | rpc/notes/service.twirp.go:124:24:124:29 | selection of opts | Origin of readStep is missing a PostUpdateNode. | | rpc/notes/service.twirp.go:128:34:128:39 | selection of opts | Origin of readStep is missing a PostUpdateNode. | +| rpc/notes/service.twirp.go:140:17:140:17 | implicit-deref c | Origin of readStep is missing a PostUpdateNode. | | rpc/notes/service.twirp.go:164:37:164:37 | implicit-deref c | Origin of readStep is missing a PostUpdateNode. | | rpc/notes/service.twirp.go:164:47:164:52 | selection of opts | Origin of readStep is missing a PostUpdateNode. | | rpc/notes/service.twirp.go:170:24:170:29 | selection of opts | Origin of readStep is missing a PostUpdateNode. | | rpc/notes/service.twirp.go:174:34:174:39 | selection of opts | Origin of readStep is missing a PostUpdateNode. | | rpc/notes/service.twirp.go:221:40:221:49 | clientOpts | Origin of readStep is missing a PostUpdateNode. | +| rpc/notes/service.twirp.go:233:17:233:17 | implicit-deref c | Origin of readStep is missing a PostUpdateNode. | | rpc/notes/service.twirp.go:257:33:257:33 | implicit-deref c | Origin of readStep is missing a PostUpdateNode. | | rpc/notes/service.twirp.go:257:43:257:48 | selection of opts | Origin of readStep is missing a PostUpdateNode. | | rpc/notes/service.twirp.go:263:24:263:29 | selection of opts | Origin of readStep is missing a PostUpdateNode. | | rpc/notes/service.twirp.go:267:34:267:39 | selection of opts | Origin of readStep is missing a PostUpdateNode. | +| rpc/notes/service.twirp.go:279:17:279:17 | implicit-deref c | Origin of readStep is missing a PostUpdateNode. | | rpc/notes/service.twirp.go:303:33:303:33 | implicit-deref c | Origin of readStep is missing a PostUpdateNode. | | rpc/notes/service.twirp.go:303:43:303:48 | selection of opts | Origin of readStep is missing a PostUpdateNode. | | rpc/notes/service.twirp.go:309:24:309:29 | selection of opts | Origin of readStep is missing a PostUpdateNode. | @@ -53,6 +57,7 @@ reverseRead | rpc/notes/service.twirp.go:441:43:441:45 | implicit-deref req | Origin of readStep is missing a PostUpdateNode. | | rpc/notes/service.twirp.go:449:36:449:36 | implicit-deref s | Origin of readStep is missing a PostUpdateNode. | | rpc/notes/service.twirp.go:455:23:455:25 | implicit-deref req | Origin of readStep is missing a PostUpdateNode. | +| rpc/notes/service.twirp.go:471:17:471:17 | implicit-deref s | Origin of readStep is missing a PostUpdateNode. | | rpc/notes/service.twirp.go:477:13:477:13 | implicit-deref s | Origin of readStep is missing a PostUpdateNode. | | rpc/notes/service.twirp.go:494:41:494:41 | implicit-deref s | Origin of readStep is missing a PostUpdateNode. | | rpc/notes/service.twirp.go:507:34:507:34 | implicit-deref s | Origin of readStep is missing a PostUpdateNode. | @@ -60,6 +65,7 @@ reverseRead | rpc/notes/service.twirp.go:526:24:526:24 | implicit-deref s | Origin of readStep is missing a PostUpdateNode. | | rpc/notes/service.twirp.go:532:36:532:36 | implicit-deref s | Origin of readStep is missing a PostUpdateNode. | | rpc/notes/service.twirp.go:538:25:538:27 | implicit-deref req | Origin of readStep is missing a PostUpdateNode. | +| rpc/notes/service.twirp.go:552:17:552:17 | implicit-deref s | Origin of readStep is missing a PostUpdateNode. | | rpc/notes/service.twirp.go:558:13:558:13 | implicit-deref s | Origin of readStep is missing a PostUpdateNode. | | rpc/notes/service.twirp.go:575:41:575:41 | implicit-deref s | Origin of readStep is missing a PostUpdateNode. | | rpc/notes/service.twirp.go:588:34:588:34 | implicit-deref s | Origin of readStep is missing a PostUpdateNode. | @@ -70,6 +76,7 @@ reverseRead | rpc/notes/service.twirp.go:621:43:621:45 | implicit-deref req | Origin of readStep is missing a PostUpdateNode. | | rpc/notes/service.twirp.go:629:36:629:36 | implicit-deref s | Origin of readStep is missing a PostUpdateNode. | | rpc/notes/service.twirp.go:635:23:635:25 | implicit-deref req | Origin of readStep is missing a PostUpdateNode. | +| rpc/notes/service.twirp.go:651:17:651:17 | implicit-deref s | Origin of readStep is missing a PostUpdateNode. | | rpc/notes/service.twirp.go:657:13:657:13 | implicit-deref s | Origin of readStep is missing a PostUpdateNode. | | rpc/notes/service.twirp.go:674:41:674:41 | implicit-deref s | Origin of readStep is missing a PostUpdateNode. | | rpc/notes/service.twirp.go:687:34:687:34 | implicit-deref s | Origin of readStep is missing a PostUpdateNode. | @@ -77,6 +84,7 @@ reverseRead | rpc/notes/service.twirp.go:706:24:706:24 | implicit-deref s | Origin of readStep is missing a PostUpdateNode. | | rpc/notes/service.twirp.go:712:36:712:36 | implicit-deref s | Origin of readStep is missing a PostUpdateNode. | | rpc/notes/service.twirp.go:718:25:718:27 | implicit-deref req | Origin of readStep is missing a PostUpdateNode. | +| rpc/notes/service.twirp.go:732:17:732:17 | implicit-deref s | Origin of readStep is missing a PostUpdateNode. | | rpc/notes/service.twirp.go:738:13:738:13 | implicit-deref s | Origin of readStep is missing a PostUpdateNode. | | rpc/notes/service.twirp.go:755:41:755:41 | implicit-deref s | Origin of readStep is missing a PostUpdateNode. | | rpc/notes/service.twirp.go:768:34:768:34 | implicit-deref s | Origin of readStep is missing a PostUpdateNode. | @@ -90,8 +98,17 @@ reverseRead | rpc/notes/service.twirp.go:1037:35:1037:38 | implicit-deref resp | Origin of readStep is missing a PostUpdateNode. | | rpc/notes/service.twirp.go:1116:66:1116:66 | implicit-deref e | Origin of readStep is missing a PostUpdateNode. | | rpc/notes/service.twirp.go:1159:98:1159:98 | implicit-deref e | Origin of readStep is missing a PostUpdateNode. | +| rpc/notes/service.twirp.go:1194:11:1194:12 | implicit-deref in | Origin of readStep is missing a PostUpdateNode. | | rpc/notes/service.twirp.go:1227:21:1227:24 | implicit-deref resp | Origin of readStep is missing a PostUpdateNode. | | rpc/notes/service.twirp.go:1237:35:1237:38 | implicit-deref resp | Origin of readStep is missing a PostUpdateNode. | | rpc/notes/service.twirp.go:1278:11:1278:14 | implicit-deref resp | Origin of readStep is missing a PostUpdateNode. | | rpc/notes/service.twirp.go:1292:23:1292:26 | implicit-deref resp | Origin of readStep is missing a PostUpdateNode. | +| rpc/notes/service.twirp.go:1312:9:1312:9 | implicit-deref h | Origin of readStep is missing a PostUpdateNode. | +| rpc/notes/service.twirp.go:1320:9:1320:9 | implicit-deref h | Origin of readStep is missing a PostUpdateNode. | +| rpc/notes/service.twirp.go:1328:9:1328:9 | implicit-deref h | Origin of readStep is missing a PostUpdateNode. | +| rpc/notes/service.twirp.go:1336:2:1336:2 | implicit-deref h | Origin of readStep is missing a PostUpdateNode. | +| rpc/notes/service.twirp.go:1344:9:1344:9 | implicit-deref h | Origin of readStep is missing a PostUpdateNode. | +| rpc/notes/service.twirp.go:1351:2:1351:2 | implicit-deref h | Origin of readStep is missing a PostUpdateNode. | +| rpc/notes/service.twirp.go:1358:9:1358:9 | implicit-deref h | Origin of readStep is missing a PostUpdateNode. | +| rpc/notes/service.twirp.go:1365:2:1365:2 | implicit-deref h | Origin of readStep is missing a PostUpdateNode. | | server/main.go:33:19:33:19 | implicit-deref s | Origin of readStep is missing a PostUpdateNode. | diff --git a/go/ql/test/query-tests/Security/CWE-601/OpenUrlRedirect/CONSISTENCY/DataFlowConsistency.expected b/go/ql/test/query-tests/Security/CWE-601/OpenUrlRedirect/CONSISTENCY/DataFlowConsistency.expected index fda76dcac5af..dcddf6139325 100644 --- a/go/ql/test/query-tests/Security/CWE-601/OpenUrlRedirect/CONSISTENCY/DataFlowConsistency.expected +++ b/go/ql/test/query-tests/Security/CWE-601/OpenUrlRedirect/CONSISTENCY/DataFlowConsistency.expected @@ -20,6 +20,7 @@ reverseRead | stdlib.go:176:6:176:6 | implicit-deref r | Origin of readStep is missing a PostUpdateNode. | | stdlib.go:177:35:177:35 | implicit-deref r | Origin of readStep is missing a PostUpdateNode. | | stdlib.go:220:3:220:3 | implicit-deref r | Origin of readStep is missing a PostUpdateNode. | +| stdlib.go:222:20:222:20 | implicit-deref r | Origin of readStep is missing a PostUpdateNode. | | stdlib.go:226:23:226:23 | implicit-deref r | Origin of readStep is missing a PostUpdateNode. | | stdlib.go:227:23:227:23 | implicit-deref r | Origin of readStep is missing a PostUpdateNode. | | stdlib.go:228:23:228:23 | implicit-deref r | Origin of readStep is missing a PostUpdateNode. | From e7131eba498065268a1e62136655f87df9721bb5 Mon Sep 17 00:00:00 2001 From: Owen Mansel-Chan Date: Wed, 21 Oct 2026 12:07:29 +0100 Subject: [PATCH 9/9] Add missing QLDoc in library --- .../codeql/dataflow/VariableCapture.qll | 66 +++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/shared/dataflow/codeql/dataflow/VariableCapture.qll b/shared/dataflow/codeql/dataflow/VariableCapture.qll index 4b07725cd681..b53db9159916 100644 --- a/shared/dataflow/codeql/dataflow/VariableCapture.qll +++ b/shared/dataflow/codeql/dataflow/VariableCapture.qll @@ -214,9 +214,11 @@ module Flow< final private class CfgBb = Cfg::BasicBlock; private class BasicBlock extends CfgBb { + /** Gets the callable enclosing this basic block. */ Callable getEnclosingCallable() { result = basicBlockGetEnclosingCallable(this) } } + /** Provides consistency checks for an instantiation of the variable capture library. */ additional module ConsistencyChecks { final private class FinalExpr = Expr; @@ -250,6 +252,10 @@ module Flow< } } + /** + * Holds if `n` relevant elements have either no textual representation or multiple textual + * representations, as described by `msg`. + */ query predicate uniqueToString(string msg, int n) { exists(string elem | n = strictcount(RelevantBasicBlock bb | not exists(bb.toString())) and @@ -282,6 +288,9 @@ module Flow< ) } + /** + * Holds if `bb` does not have exactly one enclosing callable, as described by `msg`. + */ query predicate uniqueEnclosingCallable(RelevantBasicBlock bb, string msg) { msg = "BasicBlock has no enclosing callable" and not exists(bb.getEnclosingCallable()) or @@ -289,38 +298,62 @@ module Flow< 2 <= strictcount(bb.getEnclosingCallable()) } + /** + * Holds if `bb` has multiple immediate dominators, as described by `msg`. + */ query predicate uniqueDominator(RelevantBasicBlock bb, string msg) { msg = "BasicBlock has multiple immediate dominators" and 2 <= strictcount(bb.getImmediateDominator()) } + /** + * Holds if an immediate dominator of `bb` belongs to a different callable, as described by + * `msg`. + */ query predicate localDominator(RelevantBasicBlock bb, string msg) { msg = "BasicBlock has non-local dominator" and bb.getEnclosingCallable() != bb.getImmediateDominator().(BasicBlock).getEnclosingCallable() } + /** + * Holds if a successor of `bb` belongs to a different callable, as described by `msg`. + */ query predicate localSuccessor(RelevantBasicBlock bb, string msg) { msg = "BasicBlock has non-local successor" and bb.getEnclosingCallable() != bb.getASuccessor().(BasicBlock).getEnclosingCallable() } + /** + * Holds if captured variable `v` does not have exactly one defining callable, as described by + * `msg`. + */ query predicate uniqueDefiningScope(CapturedVariable v, string msg) { msg = "CapturedVariable has no defining callable" and not exists(v.getCallable()) or msg = "CapturedVariable has multiple defining callables" and 2 <= strictcount(v.getCallable()) } + /** + * Holds if `v` is classified as a captured variable but has no access from a capturing + * callable, as described by `msg`. + */ query predicate variableIsCaptured(CapturedVariable v, string msg) { msg = "CapturedVariable is not captured" and not captureAccess(v, _) } + /** + * Holds if relevant expression `e` does not have exactly one location, as described by `msg`. + */ query predicate uniqueLocation(RelevantExpr e, string msg) { msg = "Expr has no location" and not exists(e.getLocation()) or msg = "Expr has multiple locations" and 2 <= strictcount(e.getLocation()) } + /** + * Holds if relevant expression `e` does not have exactly one CFG node, as described by `msg`. + */ query predicate uniqueCfgNode(RelevantExpr e, string msg) { msg = "Expr has no cfg node" and not e.hasCfgNode(_, _) or @@ -334,6 +367,10 @@ module Flow< msg = "VariableWrite has multiple target variables" and 2 <= strictcount(vw.getVariable()) } + /** + * Holds if a captured-variable write does not have exactly one target variable, as described + * by `msg`. + */ query predicate uniqueWriteTarget(string msg) { uniqueWriteTarget(_, msg) } private predicate uniqueWriteCfgNode(VariableWrite vw, string msg) { @@ -343,18 +380,33 @@ module Flow< 2 <= strictcount(BasicBlock bb, int i | vw.hasCfgNode(bb, i)) } + /** + * Holds if a captured-variable write does not have exactly one CFG node, as described by + * `msg`. + */ query predicate uniqueWriteCfgNode(string msg) { uniqueWriteCfgNode(_, msg) } + /** + * Holds if variable read `vr` does not have exactly one source variable, as described by + * `msg`. + */ query predicate uniqueReadVariable(VariableRead vr, string msg) { msg = "VariableRead has no source variable" and not exists(vr.getVariable()) or msg = "VariableRead has multiple source variables" and 2 <= strictcount(vr.getVariable()) } + /** + * Holds if closure expression `ce` has no callable body, as described by `msg`. + */ query predicate closureMustHaveBody(ClosureExpr ce, string msg) { msg = "ClosureExpr has no body" and not ce.hasBody(_) } + /** + * Holds if `access` is an alias of closure expression `ce` outside the lexical scope of `ce`, + * as described by `msg`. + */ query predicate closureAliasMustBeInSameScope(ClosureExpr ce, Expr access, string msg) { exists(BasicBlock bb1, BasicBlock bb2 | ce.hasAliasedAccess(access) and @@ -372,6 +424,10 @@ module Flow< ) } + /** + * Holds if callable `c` accesses captured variable `v` but is not lexically nested in the + * callable that defines `v`, as described by `msg`. + */ query predicate variableAccessAstNesting(CapturedVariable v, Callable c, string msg) { exists(BasicBlock bb, Callable parent | captureRead(v, bb, _, false, _) or captureWrite(v, bb, _, false, _) @@ -383,6 +439,9 @@ module Flow< ) } + /** + * Holds if relevant callable `c` does not have exactly one location, as described by `msg`. + */ query predicate uniqueCallableLocation(RelevantCallable c, string msg) { msg = "Callable has no location" and not exists(c.getLocation()) or @@ -391,6 +450,9 @@ module Flow< import SsaFlow::DfConsistency + /** + * Holds if `n` elements violate a variable capture consistency check, as described by `msg`. + */ query predicate consistencyOverview(string msg, int n) { uniqueToString(msg, n) or n = strictcount(BasicBlock bb | uniqueEnclosingCallable(bb, msg)) or @@ -799,6 +861,7 @@ module Flow< private class TSynthesizedCaptureNode = TSynthRead or TSynthThisQualifier or TSynthSsa; class SynthesizedCaptureNode extends ClosureNode, TSynthesizedCaptureNode { + /** Gets the basic block containing this synthesized capture node. */ BasicBlock getBasicBlock() { this = TSynthRead(_, result, _, _) or @@ -821,6 +884,9 @@ module Flow< exists(SsaFlow::SsaNode n | this = TSynthSsa(n) and n.getSourceVariable() = TThis(_)) } + /** + * Holds if this is the synthesized capture node at index `i` in basic block `bb`. + */ predicate hasCfgNode(BasicBlock bb, int i) { this = TSynthRead(_, bb, i, _) or