From cc87d2e38bf0f84cbf1593bb8142f2a892123973 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Tue, 1 Nov 2022 09:40:14 +0100 Subject: [PATCH 1/4] Data flow: Restrict public `PathNode`s to those that may reach a sink --- .../ruby/dataflow/internal/DataFlowImpl.qll | 144 ++++++++++-------- 1 file changed, 79 insertions(+), 65 deletions(-) diff --git a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl.qll b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl.qll index b5631b26b0bf..8cd1071d084a 100644 --- a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl.qll +++ b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl.qll @@ -2874,54 +2874,16 @@ private class AccessPathCons1 extends AccessPath, TAccessPathCons1 { } } -/** - * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. - * Only those `PathNode`s that are reachable from a source are generated. - */ -class PathNode extends TPathNode { - /** Gets a textual representation of this element. */ - string toString() { none() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - string toStringWithContext() { none() } - - /** - * 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/). - */ - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - none() - } - - /** Gets the underlying `Node`. */ - final Node getNode() { this.(PathNodeImpl).getNodeEx().projectToNode() = result } - +abstract private class PathNodeImpl extends TPathNode { /** Gets the `FlowState` of this node. */ - FlowState getState() { none() } + abstract FlowState getState(); /** Gets the associated configuration. */ - Configuration getConfiguration() { none() } - - /** Gets a successor of this node, if any. */ - final PathNode getASuccessor() { - result = this.(PathNodeImpl).getANonHiddenSuccessor() and - reach(this) and - reach(result) - } + abstract Configuration getConfiguration(); /** Holds if this node is a source. */ - predicate isSource() { none() } -} + abstract predicate isSource(); -abstract private class PathNodeImpl extends PathNode { abstract PathNodeImpl getASuccessorImpl(); private PathNodeImpl getASuccessorIfHidden() { @@ -2967,13 +2929,23 @@ abstract private class PathNodeImpl extends PathNode { result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" } - override string toString() { result = this.getNodeEx().toString() + this.ppAp() } + /** Gets a textual representation of this element. */ + string toString() { result = this.getNodeEx().toString() + this.ppAp() } - override string toStringWithContext() { - result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() - } + /** + * Gets a textual representation of this element, including a textual + * representation of the call context. + */ + string toStringWithContext() { result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() } - override predicate hasLocationInfo( + /** + * 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/). + */ + predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn ) { this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) @@ -2986,14 +2958,59 @@ private predicate directReach(PathNodeImpl n) { } /** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */ -private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) } +private predicate reach(PathNodeImpl n) { directReach(n) or Subpaths::retReach(n) } /** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */ -private predicate pathSucc(PathNodeImpl n1, PathNode n2) { +private predicate pathSucc(PathNodeImpl n1, PathNodeImpl n2) { n1.getANonHiddenSuccessor() = n2 and directReach(n2) } -private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2) +private predicate pathSuccPlus(PathNodeImpl n1, PathNodeImpl n2) = fastTC(pathSucc/2)(n1, n2) + +/** + * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. + * Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated. + */ +class PathNode instanceof PathNodeImpl { + PathNode() { reach(this) } + + /** Gets a textual representation of this element. */ + final string toString() { result = super.toString() } + + /** + * Gets a textual representation of this element, including a textual + * representation of the call context. + */ + final string toStringWithContext() { result = super.toStringWithContext() } + + /** + * 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/). + */ + final predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } + + /** Gets the underlying `Node`. */ + final Node getNode() { super.getNodeEx().projectToNode() = result } + + /** Gets the `FlowState` of this node. */ + final FlowState getState() { result = super.getState() } + + /** Gets the associated configuration. */ + final Configuration getConfiguration() { result = super.getConfiguration() } + + /** Gets a successor of this node, if any. */ + final PathNode getASuccessor() { result = super.getANonHiddenSuccessor() } + + /** Holds if this node is a source. */ + final predicate isSource() { super.isSource() } +} /** * Provides the query predicates needed to include a graph in a path-problem query. @@ -3004,7 +3021,7 @@ module PathGraph { /** Holds if `n` is a node in the graph of data flow path explanations. */ query predicate nodes(PathNode n, string key, string val) { - reach(n) and key = "semmle.label" and val = n.toString() + key = "semmle.label" and val = n.toString() } /** @@ -3013,11 +3030,7 @@ module PathGraph { * `ret -> out` is summarized as the edge `arg -> out`. */ query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) { - Subpaths::subpaths(arg, par, ret, out) and - reach(arg) and - reach(par) and - reach(ret) and - reach(out) + Subpaths::subpaths(arg, par, ret, out) } } @@ -3399,7 +3412,7 @@ private module Subpaths { */ pragma[nomagic] private predicate subpaths02( - PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, + PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, NodeEx out, FlowState sout, AccessPath apout ) { subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and @@ -3407,14 +3420,14 @@ private module Subpaths { } pragma[nomagic] - private Configuration getPathNodeConf(PathNode n) { result = n.getConfiguration() } + private Configuration getPathNodeConf(PathNodeImpl n) { result = n.getConfiguration() } /** * Holds if `(arg, par, ret, out)` forms a subpath-tuple. */ pragma[nomagic] private predicate subpaths03( - PathNode arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout + PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout ) { exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode | subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and @@ -3444,7 +3457,7 @@ private module Subpaths { * a subpath between `par` and `ret` with the connecting edges `arg -> par` and * `ret -> out` is summarized as the edge `arg -> out`. */ - predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) { + predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) { exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 | pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and @@ -3460,7 +3473,7 @@ private module Subpaths { * Holds if `n` can reach a return node in a summarized subpath that can reach a sink. */ predicate retReach(PathNodeImpl n) { - exists(PathNode out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) + exists(PathNodeImpl out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) or exists(PathNodeImpl mid | retReach(mid) and @@ -3477,11 +3490,12 @@ private module Subpaths { * sinks. */ private predicate flowsTo( - PathNode flowsource, PathNodeSink flowsink, Node source, Node sink, Configuration configuration + PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink, + Configuration configuration ) { flowsource.isSource() and flowsource.getConfiguration() = configuration and - flowsource.(PathNodeImpl).getNodeEx().asNode() = source and + flowsource.getNodeEx().asNode() = source and (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and flowsink.getNodeEx().asNode() = sink } @@ -3504,14 +3518,14 @@ private predicate finalStats( fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and - tuples = count(PathNode pn) + tuples = count(PathNodeImpl pn) or fwd = false and nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and - tuples = count(PathNode pn | reach(pn)) + tuples = count(PathNode pn) } /** From d3488da0c224ff598f6044f003a913d7e53ca072 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Tue, 1 Nov 2022 09:40:40 +0100 Subject: [PATCH 2/4] Data flow: Sync files --- .../cpp/ir/dataflow/internal/DataFlowImpl.qll | 144 ++++++++++-------- .../ir/dataflow/internal/DataFlowImpl2.qll | 144 ++++++++++-------- .../ir/dataflow/internal/DataFlowImpl3.qll | 144 ++++++++++-------- .../ir/dataflow/internal/DataFlowImpl4.qll | 144 ++++++++++-------- .../cpp/dataflow/internal/DataFlowImpl.qll | 144 ++++++++++-------- .../cpp/dataflow/internal/DataFlowImpl2.qll | 144 ++++++++++-------- .../cpp/dataflow/internal/DataFlowImpl3.qll | 144 ++++++++++-------- .../cpp/dataflow/internal/DataFlowImpl4.qll | 144 ++++++++++-------- .../dataflow/internal/DataFlowImplLocal.qll | 144 ++++++++++-------- .../cpp/ir/dataflow/internal/DataFlowImpl.qll | 144 ++++++++++-------- .../ir/dataflow/internal/DataFlowImpl2.qll | 144 ++++++++++-------- .../ir/dataflow/internal/DataFlowImpl3.qll | 144 ++++++++++-------- .../ir/dataflow/internal/DataFlowImpl4.qll | 144 ++++++++++-------- .../csharp/dataflow/internal/DataFlowImpl.qll | 144 ++++++++++-------- .../dataflow/internal/DataFlowImpl2.qll | 144 ++++++++++-------- .../dataflow/internal/DataFlowImpl3.qll | 144 ++++++++++-------- .../dataflow/internal/DataFlowImpl4.qll | 144 ++++++++++-------- .../dataflow/internal/DataFlowImpl5.qll | 144 ++++++++++-------- .../DataFlowImplForContentDataFlow.qll | 144 ++++++++++-------- .../java/dataflow/internal/DataFlowImpl.qll | 144 ++++++++++-------- .../java/dataflow/internal/DataFlowImpl2.qll | 144 ++++++++++-------- .../java/dataflow/internal/DataFlowImpl3.qll | 144 ++++++++++-------- .../java/dataflow/internal/DataFlowImpl4.qll | 144 ++++++++++-------- .../java/dataflow/internal/DataFlowImpl5.qll | 144 ++++++++++-------- .../java/dataflow/internal/DataFlowImpl6.qll | 144 ++++++++++-------- .../DataFlowImplForOnActivityResult.qll | 144 ++++++++++-------- .../DataFlowImplForSerializability.qll | 144 ++++++++++-------- .../dataflow/new/internal/DataFlowImpl.qll | 144 ++++++++++-------- .../dataflow/new/internal/DataFlowImpl2.qll | 144 ++++++++++-------- .../dataflow/new/internal/DataFlowImpl3.qll | 144 ++++++++++-------- .../dataflow/new/internal/DataFlowImpl4.qll | 144 ++++++++++-------- .../ruby/dataflow/internal/DataFlowImpl2.qll | 144 ++++++++++-------- .../DataFlowImplForHttpClientLibraries.qll | 144 ++++++++++-------- .../internal/DataFlowImplForPathname.qll | 144 ++++++++++-------- .../internal/DataFlowImplForRegExp.qll | 144 ++++++++++-------- .../swift/dataflow/internal/DataFlowImpl.qll | 144 ++++++++++-------- 36 files changed, 2844 insertions(+), 2340 deletions(-) diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll index b5631b26b0bf..8cd1071d084a 100644 --- a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll +++ b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll @@ -2874,54 +2874,16 @@ private class AccessPathCons1 extends AccessPath, TAccessPathCons1 { } } -/** - * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. - * Only those `PathNode`s that are reachable from a source are generated. - */ -class PathNode extends TPathNode { - /** Gets a textual representation of this element. */ - string toString() { none() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - string toStringWithContext() { none() } - - /** - * 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/). - */ - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - none() - } - - /** Gets the underlying `Node`. */ - final Node getNode() { this.(PathNodeImpl).getNodeEx().projectToNode() = result } - +abstract private class PathNodeImpl extends TPathNode { /** Gets the `FlowState` of this node. */ - FlowState getState() { none() } + abstract FlowState getState(); /** Gets the associated configuration. */ - Configuration getConfiguration() { none() } - - /** Gets a successor of this node, if any. */ - final PathNode getASuccessor() { - result = this.(PathNodeImpl).getANonHiddenSuccessor() and - reach(this) and - reach(result) - } + abstract Configuration getConfiguration(); /** Holds if this node is a source. */ - predicate isSource() { none() } -} + abstract predicate isSource(); -abstract private class PathNodeImpl extends PathNode { abstract PathNodeImpl getASuccessorImpl(); private PathNodeImpl getASuccessorIfHidden() { @@ -2967,13 +2929,23 @@ abstract private class PathNodeImpl extends PathNode { result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" } - override string toString() { result = this.getNodeEx().toString() + this.ppAp() } + /** Gets a textual representation of this element. */ + string toString() { result = this.getNodeEx().toString() + this.ppAp() } - override string toStringWithContext() { - result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() - } + /** + * Gets a textual representation of this element, including a textual + * representation of the call context. + */ + string toStringWithContext() { result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() } - override predicate hasLocationInfo( + /** + * 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/). + */ + predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn ) { this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) @@ -2986,14 +2958,59 @@ private predicate directReach(PathNodeImpl n) { } /** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */ -private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) } +private predicate reach(PathNodeImpl n) { directReach(n) or Subpaths::retReach(n) } /** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */ -private predicate pathSucc(PathNodeImpl n1, PathNode n2) { +private predicate pathSucc(PathNodeImpl n1, PathNodeImpl n2) { n1.getANonHiddenSuccessor() = n2 and directReach(n2) } -private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2) +private predicate pathSuccPlus(PathNodeImpl n1, PathNodeImpl n2) = fastTC(pathSucc/2)(n1, n2) + +/** + * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. + * Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated. + */ +class PathNode instanceof PathNodeImpl { + PathNode() { reach(this) } + + /** Gets a textual representation of this element. */ + final string toString() { result = super.toString() } + + /** + * Gets a textual representation of this element, including a textual + * representation of the call context. + */ + final string toStringWithContext() { result = super.toStringWithContext() } + + /** + * 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/). + */ + final predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } + + /** Gets the underlying `Node`. */ + final Node getNode() { super.getNodeEx().projectToNode() = result } + + /** Gets the `FlowState` of this node. */ + final FlowState getState() { result = super.getState() } + + /** Gets the associated configuration. */ + final Configuration getConfiguration() { result = super.getConfiguration() } + + /** Gets a successor of this node, if any. */ + final PathNode getASuccessor() { result = super.getANonHiddenSuccessor() } + + /** Holds if this node is a source. */ + final predicate isSource() { super.isSource() } +} /** * Provides the query predicates needed to include a graph in a path-problem query. @@ -3004,7 +3021,7 @@ module PathGraph { /** Holds if `n` is a node in the graph of data flow path explanations. */ query predicate nodes(PathNode n, string key, string val) { - reach(n) and key = "semmle.label" and val = n.toString() + key = "semmle.label" and val = n.toString() } /** @@ -3013,11 +3030,7 @@ module PathGraph { * `ret -> out` is summarized as the edge `arg -> out`. */ query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) { - Subpaths::subpaths(arg, par, ret, out) and - reach(arg) and - reach(par) and - reach(ret) and - reach(out) + Subpaths::subpaths(arg, par, ret, out) } } @@ -3399,7 +3412,7 @@ private module Subpaths { */ pragma[nomagic] private predicate subpaths02( - PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, + PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, NodeEx out, FlowState sout, AccessPath apout ) { subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and @@ -3407,14 +3420,14 @@ private module Subpaths { } pragma[nomagic] - private Configuration getPathNodeConf(PathNode n) { result = n.getConfiguration() } + private Configuration getPathNodeConf(PathNodeImpl n) { result = n.getConfiguration() } /** * Holds if `(arg, par, ret, out)` forms a subpath-tuple. */ pragma[nomagic] private predicate subpaths03( - PathNode arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout + PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout ) { exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode | subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and @@ -3444,7 +3457,7 @@ private module Subpaths { * a subpath between `par` and `ret` with the connecting edges `arg -> par` and * `ret -> out` is summarized as the edge `arg -> out`. */ - predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) { + predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) { exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 | pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and @@ -3460,7 +3473,7 @@ private module Subpaths { * Holds if `n` can reach a return node in a summarized subpath that can reach a sink. */ predicate retReach(PathNodeImpl n) { - exists(PathNode out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) + exists(PathNodeImpl out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) or exists(PathNodeImpl mid | retReach(mid) and @@ -3477,11 +3490,12 @@ private module Subpaths { * sinks. */ private predicate flowsTo( - PathNode flowsource, PathNodeSink flowsink, Node source, Node sink, Configuration configuration + PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink, + Configuration configuration ) { flowsource.isSource() and flowsource.getConfiguration() = configuration and - flowsource.(PathNodeImpl).getNodeEx().asNode() = source and + flowsource.getNodeEx().asNode() = source and (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and flowsink.getNodeEx().asNode() = sink } @@ -3504,14 +3518,14 @@ private predicate finalStats( fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and - tuples = count(PathNode pn) + tuples = count(PathNodeImpl pn) or fwd = false and nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and - tuples = count(PathNode pn | reach(pn)) + tuples = count(PathNode pn) } /** diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll index b5631b26b0bf..8cd1071d084a 100644 --- a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll +++ b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll @@ -2874,54 +2874,16 @@ private class AccessPathCons1 extends AccessPath, TAccessPathCons1 { } } -/** - * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. - * Only those `PathNode`s that are reachable from a source are generated. - */ -class PathNode extends TPathNode { - /** Gets a textual representation of this element. */ - string toString() { none() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - string toStringWithContext() { none() } - - /** - * 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/). - */ - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - none() - } - - /** Gets the underlying `Node`. */ - final Node getNode() { this.(PathNodeImpl).getNodeEx().projectToNode() = result } - +abstract private class PathNodeImpl extends TPathNode { /** Gets the `FlowState` of this node. */ - FlowState getState() { none() } + abstract FlowState getState(); /** Gets the associated configuration. */ - Configuration getConfiguration() { none() } - - /** Gets a successor of this node, if any. */ - final PathNode getASuccessor() { - result = this.(PathNodeImpl).getANonHiddenSuccessor() and - reach(this) and - reach(result) - } + abstract Configuration getConfiguration(); /** Holds if this node is a source. */ - predicate isSource() { none() } -} + abstract predicate isSource(); -abstract private class PathNodeImpl extends PathNode { abstract PathNodeImpl getASuccessorImpl(); private PathNodeImpl getASuccessorIfHidden() { @@ -2967,13 +2929,23 @@ abstract private class PathNodeImpl extends PathNode { result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" } - override string toString() { result = this.getNodeEx().toString() + this.ppAp() } + /** Gets a textual representation of this element. */ + string toString() { result = this.getNodeEx().toString() + this.ppAp() } - override string toStringWithContext() { - result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() - } + /** + * Gets a textual representation of this element, including a textual + * representation of the call context. + */ + string toStringWithContext() { result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() } - override predicate hasLocationInfo( + /** + * 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/). + */ + predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn ) { this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) @@ -2986,14 +2958,59 @@ private predicate directReach(PathNodeImpl n) { } /** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */ -private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) } +private predicate reach(PathNodeImpl n) { directReach(n) or Subpaths::retReach(n) } /** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */ -private predicate pathSucc(PathNodeImpl n1, PathNode n2) { +private predicate pathSucc(PathNodeImpl n1, PathNodeImpl n2) { n1.getANonHiddenSuccessor() = n2 and directReach(n2) } -private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2) +private predicate pathSuccPlus(PathNodeImpl n1, PathNodeImpl n2) = fastTC(pathSucc/2)(n1, n2) + +/** + * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. + * Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated. + */ +class PathNode instanceof PathNodeImpl { + PathNode() { reach(this) } + + /** Gets a textual representation of this element. */ + final string toString() { result = super.toString() } + + /** + * Gets a textual representation of this element, including a textual + * representation of the call context. + */ + final string toStringWithContext() { result = super.toStringWithContext() } + + /** + * 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/). + */ + final predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } + + /** Gets the underlying `Node`. */ + final Node getNode() { super.getNodeEx().projectToNode() = result } + + /** Gets the `FlowState` of this node. */ + final FlowState getState() { result = super.getState() } + + /** Gets the associated configuration. */ + final Configuration getConfiguration() { result = super.getConfiguration() } + + /** Gets a successor of this node, if any. */ + final PathNode getASuccessor() { result = super.getANonHiddenSuccessor() } + + /** Holds if this node is a source. */ + final predicate isSource() { super.isSource() } +} /** * Provides the query predicates needed to include a graph in a path-problem query. @@ -3004,7 +3021,7 @@ module PathGraph { /** Holds if `n` is a node in the graph of data flow path explanations. */ query predicate nodes(PathNode n, string key, string val) { - reach(n) and key = "semmle.label" and val = n.toString() + key = "semmle.label" and val = n.toString() } /** @@ -3013,11 +3030,7 @@ module PathGraph { * `ret -> out` is summarized as the edge `arg -> out`. */ query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) { - Subpaths::subpaths(arg, par, ret, out) and - reach(arg) and - reach(par) and - reach(ret) and - reach(out) + Subpaths::subpaths(arg, par, ret, out) } } @@ -3399,7 +3412,7 @@ private module Subpaths { */ pragma[nomagic] private predicate subpaths02( - PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, + PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, NodeEx out, FlowState sout, AccessPath apout ) { subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and @@ -3407,14 +3420,14 @@ private module Subpaths { } pragma[nomagic] - private Configuration getPathNodeConf(PathNode n) { result = n.getConfiguration() } + private Configuration getPathNodeConf(PathNodeImpl n) { result = n.getConfiguration() } /** * Holds if `(arg, par, ret, out)` forms a subpath-tuple. */ pragma[nomagic] private predicate subpaths03( - PathNode arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout + PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout ) { exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode | subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and @@ -3444,7 +3457,7 @@ private module Subpaths { * a subpath between `par` and `ret` with the connecting edges `arg -> par` and * `ret -> out` is summarized as the edge `arg -> out`. */ - predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) { + predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) { exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 | pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and @@ -3460,7 +3473,7 @@ private module Subpaths { * Holds if `n` can reach a return node in a summarized subpath that can reach a sink. */ predicate retReach(PathNodeImpl n) { - exists(PathNode out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) + exists(PathNodeImpl out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) or exists(PathNodeImpl mid | retReach(mid) and @@ -3477,11 +3490,12 @@ private module Subpaths { * sinks. */ private predicate flowsTo( - PathNode flowsource, PathNodeSink flowsink, Node source, Node sink, Configuration configuration + PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink, + Configuration configuration ) { flowsource.isSource() and flowsource.getConfiguration() = configuration and - flowsource.(PathNodeImpl).getNodeEx().asNode() = source and + flowsource.getNodeEx().asNode() = source and (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and flowsink.getNodeEx().asNode() = sink } @@ -3504,14 +3518,14 @@ private predicate finalStats( fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and - tuples = count(PathNode pn) + tuples = count(PathNodeImpl pn) or fwd = false and nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and - tuples = count(PathNode pn | reach(pn)) + tuples = count(PathNode pn) } /** diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll index b5631b26b0bf..8cd1071d084a 100644 --- a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll +++ b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll @@ -2874,54 +2874,16 @@ private class AccessPathCons1 extends AccessPath, TAccessPathCons1 { } } -/** - * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. - * Only those `PathNode`s that are reachable from a source are generated. - */ -class PathNode extends TPathNode { - /** Gets a textual representation of this element. */ - string toString() { none() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - string toStringWithContext() { none() } - - /** - * 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/). - */ - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - none() - } - - /** Gets the underlying `Node`. */ - final Node getNode() { this.(PathNodeImpl).getNodeEx().projectToNode() = result } - +abstract private class PathNodeImpl extends TPathNode { /** Gets the `FlowState` of this node. */ - FlowState getState() { none() } + abstract FlowState getState(); /** Gets the associated configuration. */ - Configuration getConfiguration() { none() } - - /** Gets a successor of this node, if any. */ - final PathNode getASuccessor() { - result = this.(PathNodeImpl).getANonHiddenSuccessor() and - reach(this) and - reach(result) - } + abstract Configuration getConfiguration(); /** Holds if this node is a source. */ - predicate isSource() { none() } -} + abstract predicate isSource(); -abstract private class PathNodeImpl extends PathNode { abstract PathNodeImpl getASuccessorImpl(); private PathNodeImpl getASuccessorIfHidden() { @@ -2967,13 +2929,23 @@ abstract private class PathNodeImpl extends PathNode { result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" } - override string toString() { result = this.getNodeEx().toString() + this.ppAp() } + /** Gets a textual representation of this element. */ + string toString() { result = this.getNodeEx().toString() + this.ppAp() } - override string toStringWithContext() { - result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() - } + /** + * Gets a textual representation of this element, including a textual + * representation of the call context. + */ + string toStringWithContext() { result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() } - override predicate hasLocationInfo( + /** + * 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/). + */ + predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn ) { this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) @@ -2986,14 +2958,59 @@ private predicate directReach(PathNodeImpl n) { } /** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */ -private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) } +private predicate reach(PathNodeImpl n) { directReach(n) or Subpaths::retReach(n) } /** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */ -private predicate pathSucc(PathNodeImpl n1, PathNode n2) { +private predicate pathSucc(PathNodeImpl n1, PathNodeImpl n2) { n1.getANonHiddenSuccessor() = n2 and directReach(n2) } -private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2) +private predicate pathSuccPlus(PathNodeImpl n1, PathNodeImpl n2) = fastTC(pathSucc/2)(n1, n2) + +/** + * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. + * Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated. + */ +class PathNode instanceof PathNodeImpl { + PathNode() { reach(this) } + + /** Gets a textual representation of this element. */ + final string toString() { result = super.toString() } + + /** + * Gets a textual representation of this element, including a textual + * representation of the call context. + */ + final string toStringWithContext() { result = super.toStringWithContext() } + + /** + * 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/). + */ + final predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } + + /** Gets the underlying `Node`. */ + final Node getNode() { super.getNodeEx().projectToNode() = result } + + /** Gets the `FlowState` of this node. */ + final FlowState getState() { result = super.getState() } + + /** Gets the associated configuration. */ + final Configuration getConfiguration() { result = super.getConfiguration() } + + /** Gets a successor of this node, if any. */ + final PathNode getASuccessor() { result = super.getANonHiddenSuccessor() } + + /** Holds if this node is a source. */ + final predicate isSource() { super.isSource() } +} /** * Provides the query predicates needed to include a graph in a path-problem query. @@ -3004,7 +3021,7 @@ module PathGraph { /** Holds if `n` is a node in the graph of data flow path explanations. */ query predicate nodes(PathNode n, string key, string val) { - reach(n) and key = "semmle.label" and val = n.toString() + key = "semmle.label" and val = n.toString() } /** @@ -3013,11 +3030,7 @@ module PathGraph { * `ret -> out` is summarized as the edge `arg -> out`. */ query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) { - Subpaths::subpaths(arg, par, ret, out) and - reach(arg) and - reach(par) and - reach(ret) and - reach(out) + Subpaths::subpaths(arg, par, ret, out) } } @@ -3399,7 +3412,7 @@ private module Subpaths { */ pragma[nomagic] private predicate subpaths02( - PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, + PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, NodeEx out, FlowState sout, AccessPath apout ) { subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and @@ -3407,14 +3420,14 @@ private module Subpaths { } pragma[nomagic] - private Configuration getPathNodeConf(PathNode n) { result = n.getConfiguration() } + private Configuration getPathNodeConf(PathNodeImpl n) { result = n.getConfiguration() } /** * Holds if `(arg, par, ret, out)` forms a subpath-tuple. */ pragma[nomagic] private predicate subpaths03( - PathNode arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout + PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout ) { exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode | subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and @@ -3444,7 +3457,7 @@ private module Subpaths { * a subpath between `par` and `ret` with the connecting edges `arg -> par` and * `ret -> out` is summarized as the edge `arg -> out`. */ - predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) { + predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) { exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 | pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and @@ -3460,7 +3473,7 @@ private module Subpaths { * Holds if `n` can reach a return node in a summarized subpath that can reach a sink. */ predicate retReach(PathNodeImpl n) { - exists(PathNode out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) + exists(PathNodeImpl out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) or exists(PathNodeImpl mid | retReach(mid) and @@ -3477,11 +3490,12 @@ private module Subpaths { * sinks. */ private predicate flowsTo( - PathNode flowsource, PathNodeSink flowsink, Node source, Node sink, Configuration configuration + PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink, + Configuration configuration ) { flowsource.isSource() and flowsource.getConfiguration() = configuration and - flowsource.(PathNodeImpl).getNodeEx().asNode() = source and + flowsource.getNodeEx().asNode() = source and (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and flowsink.getNodeEx().asNode() = sink } @@ -3504,14 +3518,14 @@ private predicate finalStats( fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and - tuples = count(PathNode pn) + tuples = count(PathNodeImpl pn) or fwd = false and nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and - tuples = count(PathNode pn | reach(pn)) + tuples = count(PathNode pn) } /** diff --git a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll index b5631b26b0bf..8cd1071d084a 100644 --- a/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll +++ b/cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll @@ -2874,54 +2874,16 @@ private class AccessPathCons1 extends AccessPath, TAccessPathCons1 { } } -/** - * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. - * Only those `PathNode`s that are reachable from a source are generated. - */ -class PathNode extends TPathNode { - /** Gets a textual representation of this element. */ - string toString() { none() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - string toStringWithContext() { none() } - - /** - * 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/). - */ - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - none() - } - - /** Gets the underlying `Node`. */ - final Node getNode() { this.(PathNodeImpl).getNodeEx().projectToNode() = result } - +abstract private class PathNodeImpl extends TPathNode { /** Gets the `FlowState` of this node. */ - FlowState getState() { none() } + abstract FlowState getState(); /** Gets the associated configuration. */ - Configuration getConfiguration() { none() } - - /** Gets a successor of this node, if any. */ - final PathNode getASuccessor() { - result = this.(PathNodeImpl).getANonHiddenSuccessor() and - reach(this) and - reach(result) - } + abstract Configuration getConfiguration(); /** Holds if this node is a source. */ - predicate isSource() { none() } -} + abstract predicate isSource(); -abstract private class PathNodeImpl extends PathNode { abstract PathNodeImpl getASuccessorImpl(); private PathNodeImpl getASuccessorIfHidden() { @@ -2967,13 +2929,23 @@ abstract private class PathNodeImpl extends PathNode { result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" } - override string toString() { result = this.getNodeEx().toString() + this.ppAp() } + /** Gets a textual representation of this element. */ + string toString() { result = this.getNodeEx().toString() + this.ppAp() } - override string toStringWithContext() { - result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() - } + /** + * Gets a textual representation of this element, including a textual + * representation of the call context. + */ + string toStringWithContext() { result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() } - override predicate hasLocationInfo( + /** + * 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/). + */ + predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn ) { this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) @@ -2986,14 +2958,59 @@ private predicate directReach(PathNodeImpl n) { } /** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */ -private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) } +private predicate reach(PathNodeImpl n) { directReach(n) or Subpaths::retReach(n) } /** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */ -private predicate pathSucc(PathNodeImpl n1, PathNode n2) { +private predicate pathSucc(PathNodeImpl n1, PathNodeImpl n2) { n1.getANonHiddenSuccessor() = n2 and directReach(n2) } -private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2) +private predicate pathSuccPlus(PathNodeImpl n1, PathNodeImpl n2) = fastTC(pathSucc/2)(n1, n2) + +/** + * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. + * Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated. + */ +class PathNode instanceof PathNodeImpl { + PathNode() { reach(this) } + + /** Gets a textual representation of this element. */ + final string toString() { result = super.toString() } + + /** + * Gets a textual representation of this element, including a textual + * representation of the call context. + */ + final string toStringWithContext() { result = super.toStringWithContext() } + + /** + * 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/). + */ + final predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } + + /** Gets the underlying `Node`. */ + final Node getNode() { super.getNodeEx().projectToNode() = result } + + /** Gets the `FlowState` of this node. */ + final FlowState getState() { result = super.getState() } + + /** Gets the associated configuration. */ + final Configuration getConfiguration() { result = super.getConfiguration() } + + /** Gets a successor of this node, if any. */ + final PathNode getASuccessor() { result = super.getANonHiddenSuccessor() } + + /** Holds if this node is a source. */ + final predicate isSource() { super.isSource() } +} /** * Provides the query predicates needed to include a graph in a path-problem query. @@ -3004,7 +3021,7 @@ module PathGraph { /** Holds if `n` is a node in the graph of data flow path explanations. */ query predicate nodes(PathNode n, string key, string val) { - reach(n) and key = "semmle.label" and val = n.toString() + key = "semmle.label" and val = n.toString() } /** @@ -3013,11 +3030,7 @@ module PathGraph { * `ret -> out` is summarized as the edge `arg -> out`. */ query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) { - Subpaths::subpaths(arg, par, ret, out) and - reach(arg) and - reach(par) and - reach(ret) and - reach(out) + Subpaths::subpaths(arg, par, ret, out) } } @@ -3399,7 +3412,7 @@ private module Subpaths { */ pragma[nomagic] private predicate subpaths02( - PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, + PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, NodeEx out, FlowState sout, AccessPath apout ) { subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and @@ -3407,14 +3420,14 @@ private module Subpaths { } pragma[nomagic] - private Configuration getPathNodeConf(PathNode n) { result = n.getConfiguration() } + private Configuration getPathNodeConf(PathNodeImpl n) { result = n.getConfiguration() } /** * Holds if `(arg, par, ret, out)` forms a subpath-tuple. */ pragma[nomagic] private predicate subpaths03( - PathNode arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout + PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout ) { exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode | subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and @@ -3444,7 +3457,7 @@ private module Subpaths { * a subpath between `par` and `ret` with the connecting edges `arg -> par` and * `ret -> out` is summarized as the edge `arg -> out`. */ - predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) { + predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) { exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 | pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and @@ -3460,7 +3473,7 @@ private module Subpaths { * Holds if `n` can reach a return node in a summarized subpath that can reach a sink. */ predicate retReach(PathNodeImpl n) { - exists(PathNode out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) + exists(PathNodeImpl out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) or exists(PathNodeImpl mid | retReach(mid) and @@ -3477,11 +3490,12 @@ private module Subpaths { * sinks. */ private predicate flowsTo( - PathNode flowsource, PathNodeSink flowsink, Node source, Node sink, Configuration configuration + PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink, + Configuration configuration ) { flowsource.isSource() and flowsource.getConfiguration() = configuration and - flowsource.(PathNodeImpl).getNodeEx().asNode() = source and + flowsource.getNodeEx().asNode() = source and (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and flowsink.getNodeEx().asNode() = sink } @@ -3504,14 +3518,14 @@ private predicate finalStats( fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and - tuples = count(PathNode pn) + tuples = count(PathNodeImpl pn) or fwd = false and nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and - tuples = count(PathNode pn | reach(pn)) + tuples = count(PathNode pn) } /** diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll index b5631b26b0bf..8cd1071d084a 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl.qll @@ -2874,54 +2874,16 @@ private class AccessPathCons1 extends AccessPath, TAccessPathCons1 { } } -/** - * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. - * Only those `PathNode`s that are reachable from a source are generated. - */ -class PathNode extends TPathNode { - /** Gets a textual representation of this element. */ - string toString() { none() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - string toStringWithContext() { none() } - - /** - * 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/). - */ - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - none() - } - - /** Gets the underlying `Node`. */ - final Node getNode() { this.(PathNodeImpl).getNodeEx().projectToNode() = result } - +abstract private class PathNodeImpl extends TPathNode { /** Gets the `FlowState` of this node. */ - FlowState getState() { none() } + abstract FlowState getState(); /** Gets the associated configuration. */ - Configuration getConfiguration() { none() } - - /** Gets a successor of this node, if any. */ - final PathNode getASuccessor() { - result = this.(PathNodeImpl).getANonHiddenSuccessor() and - reach(this) and - reach(result) - } + abstract Configuration getConfiguration(); /** Holds if this node is a source. */ - predicate isSource() { none() } -} + abstract predicate isSource(); -abstract private class PathNodeImpl extends PathNode { abstract PathNodeImpl getASuccessorImpl(); private PathNodeImpl getASuccessorIfHidden() { @@ -2967,13 +2929,23 @@ abstract private class PathNodeImpl extends PathNode { result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" } - override string toString() { result = this.getNodeEx().toString() + this.ppAp() } + /** Gets a textual representation of this element. */ + string toString() { result = this.getNodeEx().toString() + this.ppAp() } - override string toStringWithContext() { - result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() - } + /** + * Gets a textual representation of this element, including a textual + * representation of the call context. + */ + string toStringWithContext() { result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() } - override predicate hasLocationInfo( + /** + * 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/). + */ + predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn ) { this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) @@ -2986,14 +2958,59 @@ private predicate directReach(PathNodeImpl n) { } /** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */ -private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) } +private predicate reach(PathNodeImpl n) { directReach(n) or Subpaths::retReach(n) } /** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */ -private predicate pathSucc(PathNodeImpl n1, PathNode n2) { +private predicate pathSucc(PathNodeImpl n1, PathNodeImpl n2) { n1.getANonHiddenSuccessor() = n2 and directReach(n2) } -private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2) +private predicate pathSuccPlus(PathNodeImpl n1, PathNodeImpl n2) = fastTC(pathSucc/2)(n1, n2) + +/** + * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. + * Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated. + */ +class PathNode instanceof PathNodeImpl { + PathNode() { reach(this) } + + /** Gets a textual representation of this element. */ + final string toString() { result = super.toString() } + + /** + * Gets a textual representation of this element, including a textual + * representation of the call context. + */ + final string toStringWithContext() { result = super.toStringWithContext() } + + /** + * 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/). + */ + final predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } + + /** Gets the underlying `Node`. */ + final Node getNode() { super.getNodeEx().projectToNode() = result } + + /** Gets the `FlowState` of this node. */ + final FlowState getState() { result = super.getState() } + + /** Gets the associated configuration. */ + final Configuration getConfiguration() { result = super.getConfiguration() } + + /** Gets a successor of this node, if any. */ + final PathNode getASuccessor() { result = super.getANonHiddenSuccessor() } + + /** Holds if this node is a source. */ + final predicate isSource() { super.isSource() } +} /** * Provides the query predicates needed to include a graph in a path-problem query. @@ -3004,7 +3021,7 @@ module PathGraph { /** Holds if `n` is a node in the graph of data flow path explanations. */ query predicate nodes(PathNode n, string key, string val) { - reach(n) and key = "semmle.label" and val = n.toString() + key = "semmle.label" and val = n.toString() } /** @@ -3013,11 +3030,7 @@ module PathGraph { * `ret -> out` is summarized as the edge `arg -> out`. */ query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) { - Subpaths::subpaths(arg, par, ret, out) and - reach(arg) and - reach(par) and - reach(ret) and - reach(out) + Subpaths::subpaths(arg, par, ret, out) } } @@ -3399,7 +3412,7 @@ private module Subpaths { */ pragma[nomagic] private predicate subpaths02( - PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, + PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, NodeEx out, FlowState sout, AccessPath apout ) { subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and @@ -3407,14 +3420,14 @@ private module Subpaths { } pragma[nomagic] - private Configuration getPathNodeConf(PathNode n) { result = n.getConfiguration() } + private Configuration getPathNodeConf(PathNodeImpl n) { result = n.getConfiguration() } /** * Holds if `(arg, par, ret, out)` forms a subpath-tuple. */ pragma[nomagic] private predicate subpaths03( - PathNode arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout + PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout ) { exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode | subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and @@ -3444,7 +3457,7 @@ private module Subpaths { * a subpath between `par` and `ret` with the connecting edges `arg -> par` and * `ret -> out` is summarized as the edge `arg -> out`. */ - predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) { + predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) { exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 | pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and @@ -3460,7 +3473,7 @@ private module Subpaths { * Holds if `n` can reach a return node in a summarized subpath that can reach a sink. */ predicate retReach(PathNodeImpl n) { - exists(PathNode out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) + exists(PathNodeImpl out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) or exists(PathNodeImpl mid | retReach(mid) and @@ -3477,11 +3490,12 @@ private module Subpaths { * sinks. */ private predicate flowsTo( - PathNode flowsource, PathNodeSink flowsink, Node source, Node sink, Configuration configuration + PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink, + Configuration configuration ) { flowsource.isSource() and flowsource.getConfiguration() = configuration and - flowsource.(PathNodeImpl).getNodeEx().asNode() = source and + flowsource.getNodeEx().asNode() = source and (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and flowsink.getNodeEx().asNode() = sink } @@ -3504,14 +3518,14 @@ private predicate finalStats( fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and - tuples = count(PathNode pn) + tuples = count(PathNodeImpl pn) or fwd = false and nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and - tuples = count(PathNode pn | reach(pn)) + tuples = count(PathNode pn) } /** diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll index b5631b26b0bf..8cd1071d084a 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl2.qll @@ -2874,54 +2874,16 @@ private class AccessPathCons1 extends AccessPath, TAccessPathCons1 { } } -/** - * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. - * Only those `PathNode`s that are reachable from a source are generated. - */ -class PathNode extends TPathNode { - /** Gets a textual representation of this element. */ - string toString() { none() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - string toStringWithContext() { none() } - - /** - * 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/). - */ - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - none() - } - - /** Gets the underlying `Node`. */ - final Node getNode() { this.(PathNodeImpl).getNodeEx().projectToNode() = result } - +abstract private class PathNodeImpl extends TPathNode { /** Gets the `FlowState` of this node. */ - FlowState getState() { none() } + abstract FlowState getState(); /** Gets the associated configuration. */ - Configuration getConfiguration() { none() } - - /** Gets a successor of this node, if any. */ - final PathNode getASuccessor() { - result = this.(PathNodeImpl).getANonHiddenSuccessor() and - reach(this) and - reach(result) - } + abstract Configuration getConfiguration(); /** Holds if this node is a source. */ - predicate isSource() { none() } -} + abstract predicate isSource(); -abstract private class PathNodeImpl extends PathNode { abstract PathNodeImpl getASuccessorImpl(); private PathNodeImpl getASuccessorIfHidden() { @@ -2967,13 +2929,23 @@ abstract private class PathNodeImpl extends PathNode { result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" } - override string toString() { result = this.getNodeEx().toString() + this.ppAp() } + /** Gets a textual representation of this element. */ + string toString() { result = this.getNodeEx().toString() + this.ppAp() } - override string toStringWithContext() { - result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() - } + /** + * Gets a textual representation of this element, including a textual + * representation of the call context. + */ + string toStringWithContext() { result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() } - override predicate hasLocationInfo( + /** + * 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/). + */ + predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn ) { this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) @@ -2986,14 +2958,59 @@ private predicate directReach(PathNodeImpl n) { } /** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */ -private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) } +private predicate reach(PathNodeImpl n) { directReach(n) or Subpaths::retReach(n) } /** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */ -private predicate pathSucc(PathNodeImpl n1, PathNode n2) { +private predicate pathSucc(PathNodeImpl n1, PathNodeImpl n2) { n1.getANonHiddenSuccessor() = n2 and directReach(n2) } -private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2) +private predicate pathSuccPlus(PathNodeImpl n1, PathNodeImpl n2) = fastTC(pathSucc/2)(n1, n2) + +/** + * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. + * Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated. + */ +class PathNode instanceof PathNodeImpl { + PathNode() { reach(this) } + + /** Gets a textual representation of this element. */ + final string toString() { result = super.toString() } + + /** + * Gets a textual representation of this element, including a textual + * representation of the call context. + */ + final string toStringWithContext() { result = super.toStringWithContext() } + + /** + * 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/). + */ + final predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } + + /** Gets the underlying `Node`. */ + final Node getNode() { super.getNodeEx().projectToNode() = result } + + /** Gets the `FlowState` of this node. */ + final FlowState getState() { result = super.getState() } + + /** Gets the associated configuration. */ + final Configuration getConfiguration() { result = super.getConfiguration() } + + /** Gets a successor of this node, if any. */ + final PathNode getASuccessor() { result = super.getANonHiddenSuccessor() } + + /** Holds if this node is a source. */ + final predicate isSource() { super.isSource() } +} /** * Provides the query predicates needed to include a graph in a path-problem query. @@ -3004,7 +3021,7 @@ module PathGraph { /** Holds if `n` is a node in the graph of data flow path explanations. */ query predicate nodes(PathNode n, string key, string val) { - reach(n) and key = "semmle.label" and val = n.toString() + key = "semmle.label" and val = n.toString() } /** @@ -3013,11 +3030,7 @@ module PathGraph { * `ret -> out` is summarized as the edge `arg -> out`. */ query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) { - Subpaths::subpaths(arg, par, ret, out) and - reach(arg) and - reach(par) and - reach(ret) and - reach(out) + Subpaths::subpaths(arg, par, ret, out) } } @@ -3399,7 +3412,7 @@ private module Subpaths { */ pragma[nomagic] private predicate subpaths02( - PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, + PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, NodeEx out, FlowState sout, AccessPath apout ) { subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and @@ -3407,14 +3420,14 @@ private module Subpaths { } pragma[nomagic] - private Configuration getPathNodeConf(PathNode n) { result = n.getConfiguration() } + private Configuration getPathNodeConf(PathNodeImpl n) { result = n.getConfiguration() } /** * Holds if `(arg, par, ret, out)` forms a subpath-tuple. */ pragma[nomagic] private predicate subpaths03( - PathNode arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout + PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout ) { exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode | subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and @@ -3444,7 +3457,7 @@ private module Subpaths { * a subpath between `par` and `ret` with the connecting edges `arg -> par` and * `ret -> out` is summarized as the edge `arg -> out`. */ - predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) { + predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) { exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 | pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and @@ -3460,7 +3473,7 @@ private module Subpaths { * Holds if `n` can reach a return node in a summarized subpath that can reach a sink. */ predicate retReach(PathNodeImpl n) { - exists(PathNode out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) + exists(PathNodeImpl out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) or exists(PathNodeImpl mid | retReach(mid) and @@ -3477,11 +3490,12 @@ private module Subpaths { * sinks. */ private predicate flowsTo( - PathNode flowsource, PathNodeSink flowsink, Node source, Node sink, Configuration configuration + PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink, + Configuration configuration ) { flowsource.isSource() and flowsource.getConfiguration() = configuration and - flowsource.(PathNodeImpl).getNodeEx().asNode() = source and + flowsource.getNodeEx().asNode() = source and (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and flowsink.getNodeEx().asNode() = sink } @@ -3504,14 +3518,14 @@ private predicate finalStats( fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and - tuples = count(PathNode pn) + tuples = count(PathNodeImpl pn) or fwd = false and nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and - tuples = count(PathNode pn | reach(pn)) + tuples = count(PathNode pn) } /** diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll index b5631b26b0bf..8cd1071d084a 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl3.qll @@ -2874,54 +2874,16 @@ private class AccessPathCons1 extends AccessPath, TAccessPathCons1 { } } -/** - * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. - * Only those `PathNode`s that are reachable from a source are generated. - */ -class PathNode extends TPathNode { - /** Gets a textual representation of this element. */ - string toString() { none() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - string toStringWithContext() { none() } - - /** - * 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/). - */ - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - none() - } - - /** Gets the underlying `Node`. */ - final Node getNode() { this.(PathNodeImpl).getNodeEx().projectToNode() = result } - +abstract private class PathNodeImpl extends TPathNode { /** Gets the `FlowState` of this node. */ - FlowState getState() { none() } + abstract FlowState getState(); /** Gets the associated configuration. */ - Configuration getConfiguration() { none() } - - /** Gets a successor of this node, if any. */ - final PathNode getASuccessor() { - result = this.(PathNodeImpl).getANonHiddenSuccessor() and - reach(this) and - reach(result) - } + abstract Configuration getConfiguration(); /** Holds if this node is a source. */ - predicate isSource() { none() } -} + abstract predicate isSource(); -abstract private class PathNodeImpl extends PathNode { abstract PathNodeImpl getASuccessorImpl(); private PathNodeImpl getASuccessorIfHidden() { @@ -2967,13 +2929,23 @@ abstract private class PathNodeImpl extends PathNode { result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" } - override string toString() { result = this.getNodeEx().toString() + this.ppAp() } + /** Gets a textual representation of this element. */ + string toString() { result = this.getNodeEx().toString() + this.ppAp() } - override string toStringWithContext() { - result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() - } + /** + * Gets a textual representation of this element, including a textual + * representation of the call context. + */ + string toStringWithContext() { result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() } - override predicate hasLocationInfo( + /** + * 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/). + */ + predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn ) { this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) @@ -2986,14 +2958,59 @@ private predicate directReach(PathNodeImpl n) { } /** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */ -private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) } +private predicate reach(PathNodeImpl n) { directReach(n) or Subpaths::retReach(n) } /** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */ -private predicate pathSucc(PathNodeImpl n1, PathNode n2) { +private predicate pathSucc(PathNodeImpl n1, PathNodeImpl n2) { n1.getANonHiddenSuccessor() = n2 and directReach(n2) } -private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2) +private predicate pathSuccPlus(PathNodeImpl n1, PathNodeImpl n2) = fastTC(pathSucc/2)(n1, n2) + +/** + * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. + * Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated. + */ +class PathNode instanceof PathNodeImpl { + PathNode() { reach(this) } + + /** Gets a textual representation of this element. */ + final string toString() { result = super.toString() } + + /** + * Gets a textual representation of this element, including a textual + * representation of the call context. + */ + final string toStringWithContext() { result = super.toStringWithContext() } + + /** + * 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/). + */ + final predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } + + /** Gets the underlying `Node`. */ + final Node getNode() { super.getNodeEx().projectToNode() = result } + + /** Gets the `FlowState` of this node. */ + final FlowState getState() { result = super.getState() } + + /** Gets the associated configuration. */ + final Configuration getConfiguration() { result = super.getConfiguration() } + + /** Gets a successor of this node, if any. */ + final PathNode getASuccessor() { result = super.getANonHiddenSuccessor() } + + /** Holds if this node is a source. */ + final predicate isSource() { super.isSource() } +} /** * Provides the query predicates needed to include a graph in a path-problem query. @@ -3004,7 +3021,7 @@ module PathGraph { /** Holds if `n` is a node in the graph of data flow path explanations. */ query predicate nodes(PathNode n, string key, string val) { - reach(n) and key = "semmle.label" and val = n.toString() + key = "semmle.label" and val = n.toString() } /** @@ -3013,11 +3030,7 @@ module PathGraph { * `ret -> out` is summarized as the edge `arg -> out`. */ query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) { - Subpaths::subpaths(arg, par, ret, out) and - reach(arg) and - reach(par) and - reach(ret) and - reach(out) + Subpaths::subpaths(arg, par, ret, out) } } @@ -3399,7 +3412,7 @@ private module Subpaths { */ pragma[nomagic] private predicate subpaths02( - PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, + PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, NodeEx out, FlowState sout, AccessPath apout ) { subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and @@ -3407,14 +3420,14 @@ private module Subpaths { } pragma[nomagic] - private Configuration getPathNodeConf(PathNode n) { result = n.getConfiguration() } + private Configuration getPathNodeConf(PathNodeImpl n) { result = n.getConfiguration() } /** * Holds if `(arg, par, ret, out)` forms a subpath-tuple. */ pragma[nomagic] private predicate subpaths03( - PathNode arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout + PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout ) { exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode | subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and @@ -3444,7 +3457,7 @@ private module Subpaths { * a subpath between `par` and `ret` with the connecting edges `arg -> par` and * `ret -> out` is summarized as the edge `arg -> out`. */ - predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) { + predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) { exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 | pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and @@ -3460,7 +3473,7 @@ private module Subpaths { * Holds if `n` can reach a return node in a summarized subpath that can reach a sink. */ predicate retReach(PathNodeImpl n) { - exists(PathNode out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) + exists(PathNodeImpl out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) or exists(PathNodeImpl mid | retReach(mid) and @@ -3477,11 +3490,12 @@ private module Subpaths { * sinks. */ private predicate flowsTo( - PathNode flowsource, PathNodeSink flowsink, Node source, Node sink, Configuration configuration + PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink, + Configuration configuration ) { flowsource.isSource() and flowsource.getConfiguration() = configuration and - flowsource.(PathNodeImpl).getNodeEx().asNode() = source and + flowsource.getNodeEx().asNode() = source and (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and flowsink.getNodeEx().asNode() = sink } @@ -3504,14 +3518,14 @@ private predicate finalStats( fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and - tuples = count(PathNode pn) + tuples = count(PathNodeImpl pn) or fwd = false and nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and - tuples = count(PathNode pn | reach(pn)) + tuples = count(PathNode pn) } /** diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll index b5631b26b0bf..8cd1071d084a 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImpl4.qll @@ -2874,54 +2874,16 @@ private class AccessPathCons1 extends AccessPath, TAccessPathCons1 { } } -/** - * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. - * Only those `PathNode`s that are reachable from a source are generated. - */ -class PathNode extends TPathNode { - /** Gets a textual representation of this element. */ - string toString() { none() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - string toStringWithContext() { none() } - - /** - * 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/). - */ - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - none() - } - - /** Gets the underlying `Node`. */ - final Node getNode() { this.(PathNodeImpl).getNodeEx().projectToNode() = result } - +abstract private class PathNodeImpl extends TPathNode { /** Gets the `FlowState` of this node. */ - FlowState getState() { none() } + abstract FlowState getState(); /** Gets the associated configuration. */ - Configuration getConfiguration() { none() } - - /** Gets a successor of this node, if any. */ - final PathNode getASuccessor() { - result = this.(PathNodeImpl).getANonHiddenSuccessor() and - reach(this) and - reach(result) - } + abstract Configuration getConfiguration(); /** Holds if this node is a source. */ - predicate isSource() { none() } -} + abstract predicate isSource(); -abstract private class PathNodeImpl extends PathNode { abstract PathNodeImpl getASuccessorImpl(); private PathNodeImpl getASuccessorIfHidden() { @@ -2967,13 +2929,23 @@ abstract private class PathNodeImpl extends PathNode { result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" } - override string toString() { result = this.getNodeEx().toString() + this.ppAp() } + /** Gets a textual representation of this element. */ + string toString() { result = this.getNodeEx().toString() + this.ppAp() } - override string toStringWithContext() { - result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() - } + /** + * Gets a textual representation of this element, including a textual + * representation of the call context. + */ + string toStringWithContext() { result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() } - override predicate hasLocationInfo( + /** + * 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/). + */ + predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn ) { this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) @@ -2986,14 +2958,59 @@ private predicate directReach(PathNodeImpl n) { } /** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */ -private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) } +private predicate reach(PathNodeImpl n) { directReach(n) or Subpaths::retReach(n) } /** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */ -private predicate pathSucc(PathNodeImpl n1, PathNode n2) { +private predicate pathSucc(PathNodeImpl n1, PathNodeImpl n2) { n1.getANonHiddenSuccessor() = n2 and directReach(n2) } -private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2) +private predicate pathSuccPlus(PathNodeImpl n1, PathNodeImpl n2) = fastTC(pathSucc/2)(n1, n2) + +/** + * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. + * Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated. + */ +class PathNode instanceof PathNodeImpl { + PathNode() { reach(this) } + + /** Gets a textual representation of this element. */ + final string toString() { result = super.toString() } + + /** + * Gets a textual representation of this element, including a textual + * representation of the call context. + */ + final string toStringWithContext() { result = super.toStringWithContext() } + + /** + * 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/). + */ + final predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } + + /** Gets the underlying `Node`. */ + final Node getNode() { super.getNodeEx().projectToNode() = result } + + /** Gets the `FlowState` of this node. */ + final FlowState getState() { result = super.getState() } + + /** Gets the associated configuration. */ + final Configuration getConfiguration() { result = super.getConfiguration() } + + /** Gets a successor of this node, if any. */ + final PathNode getASuccessor() { result = super.getANonHiddenSuccessor() } + + /** Holds if this node is a source. */ + final predicate isSource() { super.isSource() } +} /** * Provides the query predicates needed to include a graph in a path-problem query. @@ -3004,7 +3021,7 @@ module PathGraph { /** Holds if `n` is a node in the graph of data flow path explanations. */ query predicate nodes(PathNode n, string key, string val) { - reach(n) and key = "semmle.label" and val = n.toString() + key = "semmle.label" and val = n.toString() } /** @@ -3013,11 +3030,7 @@ module PathGraph { * `ret -> out` is summarized as the edge `arg -> out`. */ query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) { - Subpaths::subpaths(arg, par, ret, out) and - reach(arg) and - reach(par) and - reach(ret) and - reach(out) + Subpaths::subpaths(arg, par, ret, out) } } @@ -3399,7 +3412,7 @@ private module Subpaths { */ pragma[nomagic] private predicate subpaths02( - PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, + PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, NodeEx out, FlowState sout, AccessPath apout ) { subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and @@ -3407,14 +3420,14 @@ private module Subpaths { } pragma[nomagic] - private Configuration getPathNodeConf(PathNode n) { result = n.getConfiguration() } + private Configuration getPathNodeConf(PathNodeImpl n) { result = n.getConfiguration() } /** * Holds if `(arg, par, ret, out)` forms a subpath-tuple. */ pragma[nomagic] private predicate subpaths03( - PathNode arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout + PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout ) { exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode | subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and @@ -3444,7 +3457,7 @@ private module Subpaths { * a subpath between `par` and `ret` with the connecting edges `arg -> par` and * `ret -> out` is summarized as the edge `arg -> out`. */ - predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) { + predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) { exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 | pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and @@ -3460,7 +3473,7 @@ private module Subpaths { * Holds if `n` can reach a return node in a summarized subpath that can reach a sink. */ predicate retReach(PathNodeImpl n) { - exists(PathNode out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) + exists(PathNodeImpl out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) or exists(PathNodeImpl mid | retReach(mid) and @@ -3477,11 +3490,12 @@ private module Subpaths { * sinks. */ private predicate flowsTo( - PathNode flowsource, PathNodeSink flowsink, Node source, Node sink, Configuration configuration + PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink, + Configuration configuration ) { flowsource.isSource() and flowsource.getConfiguration() = configuration and - flowsource.(PathNodeImpl).getNodeEx().asNode() = source and + flowsource.getNodeEx().asNode() = source and (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and flowsink.getNodeEx().asNode() = sink } @@ -3504,14 +3518,14 @@ private predicate finalStats( fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and - tuples = count(PathNode pn) + tuples = count(PathNodeImpl pn) or fwd = false and nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and - tuples = count(PathNode pn | reach(pn)) + tuples = count(PathNode pn) } /** diff --git a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll index b5631b26b0bf..8cd1071d084a 100644 --- a/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll +++ b/cpp/ql/lib/semmle/code/cpp/dataflow/internal/DataFlowImplLocal.qll @@ -2874,54 +2874,16 @@ private class AccessPathCons1 extends AccessPath, TAccessPathCons1 { } } -/** - * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. - * Only those `PathNode`s that are reachable from a source are generated. - */ -class PathNode extends TPathNode { - /** Gets a textual representation of this element. */ - string toString() { none() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - string toStringWithContext() { none() } - - /** - * 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/). - */ - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - none() - } - - /** Gets the underlying `Node`. */ - final Node getNode() { this.(PathNodeImpl).getNodeEx().projectToNode() = result } - +abstract private class PathNodeImpl extends TPathNode { /** Gets the `FlowState` of this node. */ - FlowState getState() { none() } + abstract FlowState getState(); /** Gets the associated configuration. */ - Configuration getConfiguration() { none() } - - /** Gets a successor of this node, if any. */ - final PathNode getASuccessor() { - result = this.(PathNodeImpl).getANonHiddenSuccessor() and - reach(this) and - reach(result) - } + abstract Configuration getConfiguration(); /** Holds if this node is a source. */ - predicate isSource() { none() } -} + abstract predicate isSource(); -abstract private class PathNodeImpl extends PathNode { abstract PathNodeImpl getASuccessorImpl(); private PathNodeImpl getASuccessorIfHidden() { @@ -2967,13 +2929,23 @@ abstract private class PathNodeImpl extends PathNode { result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" } - override string toString() { result = this.getNodeEx().toString() + this.ppAp() } + /** Gets a textual representation of this element. */ + string toString() { result = this.getNodeEx().toString() + this.ppAp() } - override string toStringWithContext() { - result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() - } + /** + * Gets a textual representation of this element, including a textual + * representation of the call context. + */ + string toStringWithContext() { result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() } - override predicate hasLocationInfo( + /** + * 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/). + */ + predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn ) { this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) @@ -2986,14 +2958,59 @@ private predicate directReach(PathNodeImpl n) { } /** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */ -private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) } +private predicate reach(PathNodeImpl n) { directReach(n) or Subpaths::retReach(n) } /** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */ -private predicate pathSucc(PathNodeImpl n1, PathNode n2) { +private predicate pathSucc(PathNodeImpl n1, PathNodeImpl n2) { n1.getANonHiddenSuccessor() = n2 and directReach(n2) } -private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2) +private predicate pathSuccPlus(PathNodeImpl n1, PathNodeImpl n2) = fastTC(pathSucc/2)(n1, n2) + +/** + * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. + * Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated. + */ +class PathNode instanceof PathNodeImpl { + PathNode() { reach(this) } + + /** Gets a textual representation of this element. */ + final string toString() { result = super.toString() } + + /** + * Gets a textual representation of this element, including a textual + * representation of the call context. + */ + final string toStringWithContext() { result = super.toStringWithContext() } + + /** + * 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/). + */ + final predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } + + /** Gets the underlying `Node`. */ + final Node getNode() { super.getNodeEx().projectToNode() = result } + + /** Gets the `FlowState` of this node. */ + final FlowState getState() { result = super.getState() } + + /** Gets the associated configuration. */ + final Configuration getConfiguration() { result = super.getConfiguration() } + + /** Gets a successor of this node, if any. */ + final PathNode getASuccessor() { result = super.getANonHiddenSuccessor() } + + /** Holds if this node is a source. */ + final predicate isSource() { super.isSource() } +} /** * Provides the query predicates needed to include a graph in a path-problem query. @@ -3004,7 +3021,7 @@ module PathGraph { /** Holds if `n` is a node in the graph of data flow path explanations. */ query predicate nodes(PathNode n, string key, string val) { - reach(n) and key = "semmle.label" and val = n.toString() + key = "semmle.label" and val = n.toString() } /** @@ -3013,11 +3030,7 @@ module PathGraph { * `ret -> out` is summarized as the edge `arg -> out`. */ query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) { - Subpaths::subpaths(arg, par, ret, out) and - reach(arg) and - reach(par) and - reach(ret) and - reach(out) + Subpaths::subpaths(arg, par, ret, out) } } @@ -3399,7 +3412,7 @@ private module Subpaths { */ pragma[nomagic] private predicate subpaths02( - PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, + PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, NodeEx out, FlowState sout, AccessPath apout ) { subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and @@ -3407,14 +3420,14 @@ private module Subpaths { } pragma[nomagic] - private Configuration getPathNodeConf(PathNode n) { result = n.getConfiguration() } + private Configuration getPathNodeConf(PathNodeImpl n) { result = n.getConfiguration() } /** * Holds if `(arg, par, ret, out)` forms a subpath-tuple. */ pragma[nomagic] private predicate subpaths03( - PathNode arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout + PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout ) { exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode | subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and @@ -3444,7 +3457,7 @@ private module Subpaths { * a subpath between `par` and `ret` with the connecting edges `arg -> par` and * `ret -> out` is summarized as the edge `arg -> out`. */ - predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) { + predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) { exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 | pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and @@ -3460,7 +3473,7 @@ private module Subpaths { * Holds if `n` can reach a return node in a summarized subpath that can reach a sink. */ predicate retReach(PathNodeImpl n) { - exists(PathNode out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) + exists(PathNodeImpl out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) or exists(PathNodeImpl mid | retReach(mid) and @@ -3477,11 +3490,12 @@ private module Subpaths { * sinks. */ private predicate flowsTo( - PathNode flowsource, PathNodeSink flowsink, Node source, Node sink, Configuration configuration + PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink, + Configuration configuration ) { flowsource.isSource() and flowsource.getConfiguration() = configuration and - flowsource.(PathNodeImpl).getNodeEx().asNode() = source and + flowsource.getNodeEx().asNode() = source and (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and flowsink.getNodeEx().asNode() = sink } @@ -3504,14 +3518,14 @@ private predicate finalStats( fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and - tuples = count(PathNode pn) + tuples = count(PathNodeImpl pn) or fwd = false and nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and - tuples = count(PathNode pn | reach(pn)) + tuples = count(PathNode pn) } /** diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll index b5631b26b0bf..8cd1071d084a 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll @@ -2874,54 +2874,16 @@ private class AccessPathCons1 extends AccessPath, TAccessPathCons1 { } } -/** - * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. - * Only those `PathNode`s that are reachable from a source are generated. - */ -class PathNode extends TPathNode { - /** Gets a textual representation of this element. */ - string toString() { none() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - string toStringWithContext() { none() } - - /** - * 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/). - */ - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - none() - } - - /** Gets the underlying `Node`. */ - final Node getNode() { this.(PathNodeImpl).getNodeEx().projectToNode() = result } - +abstract private class PathNodeImpl extends TPathNode { /** Gets the `FlowState` of this node. */ - FlowState getState() { none() } + abstract FlowState getState(); /** Gets the associated configuration. */ - Configuration getConfiguration() { none() } - - /** Gets a successor of this node, if any. */ - final PathNode getASuccessor() { - result = this.(PathNodeImpl).getANonHiddenSuccessor() and - reach(this) and - reach(result) - } + abstract Configuration getConfiguration(); /** Holds if this node is a source. */ - predicate isSource() { none() } -} + abstract predicate isSource(); -abstract private class PathNodeImpl extends PathNode { abstract PathNodeImpl getASuccessorImpl(); private PathNodeImpl getASuccessorIfHidden() { @@ -2967,13 +2929,23 @@ abstract private class PathNodeImpl extends PathNode { result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" } - override string toString() { result = this.getNodeEx().toString() + this.ppAp() } + /** Gets a textual representation of this element. */ + string toString() { result = this.getNodeEx().toString() + this.ppAp() } - override string toStringWithContext() { - result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() - } + /** + * Gets a textual representation of this element, including a textual + * representation of the call context. + */ + string toStringWithContext() { result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() } - override predicate hasLocationInfo( + /** + * 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/). + */ + predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn ) { this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) @@ -2986,14 +2958,59 @@ private predicate directReach(PathNodeImpl n) { } /** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */ -private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) } +private predicate reach(PathNodeImpl n) { directReach(n) or Subpaths::retReach(n) } /** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */ -private predicate pathSucc(PathNodeImpl n1, PathNode n2) { +private predicate pathSucc(PathNodeImpl n1, PathNodeImpl n2) { n1.getANonHiddenSuccessor() = n2 and directReach(n2) } -private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2) +private predicate pathSuccPlus(PathNodeImpl n1, PathNodeImpl n2) = fastTC(pathSucc/2)(n1, n2) + +/** + * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. + * Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated. + */ +class PathNode instanceof PathNodeImpl { + PathNode() { reach(this) } + + /** Gets a textual representation of this element. */ + final string toString() { result = super.toString() } + + /** + * Gets a textual representation of this element, including a textual + * representation of the call context. + */ + final string toStringWithContext() { result = super.toStringWithContext() } + + /** + * 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/). + */ + final predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } + + /** Gets the underlying `Node`. */ + final Node getNode() { super.getNodeEx().projectToNode() = result } + + /** Gets the `FlowState` of this node. */ + final FlowState getState() { result = super.getState() } + + /** Gets the associated configuration. */ + final Configuration getConfiguration() { result = super.getConfiguration() } + + /** Gets a successor of this node, if any. */ + final PathNode getASuccessor() { result = super.getANonHiddenSuccessor() } + + /** Holds if this node is a source. */ + final predicate isSource() { super.isSource() } +} /** * Provides the query predicates needed to include a graph in a path-problem query. @@ -3004,7 +3021,7 @@ module PathGraph { /** Holds if `n` is a node in the graph of data flow path explanations. */ query predicate nodes(PathNode n, string key, string val) { - reach(n) and key = "semmle.label" and val = n.toString() + key = "semmle.label" and val = n.toString() } /** @@ -3013,11 +3030,7 @@ module PathGraph { * `ret -> out` is summarized as the edge `arg -> out`. */ query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) { - Subpaths::subpaths(arg, par, ret, out) and - reach(arg) and - reach(par) and - reach(ret) and - reach(out) + Subpaths::subpaths(arg, par, ret, out) } } @@ -3399,7 +3412,7 @@ private module Subpaths { */ pragma[nomagic] private predicate subpaths02( - PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, + PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, NodeEx out, FlowState sout, AccessPath apout ) { subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and @@ -3407,14 +3420,14 @@ private module Subpaths { } pragma[nomagic] - private Configuration getPathNodeConf(PathNode n) { result = n.getConfiguration() } + private Configuration getPathNodeConf(PathNodeImpl n) { result = n.getConfiguration() } /** * Holds if `(arg, par, ret, out)` forms a subpath-tuple. */ pragma[nomagic] private predicate subpaths03( - PathNode arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout + PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout ) { exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode | subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and @@ -3444,7 +3457,7 @@ private module Subpaths { * a subpath between `par` and `ret` with the connecting edges `arg -> par` and * `ret -> out` is summarized as the edge `arg -> out`. */ - predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) { + predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) { exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 | pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and @@ -3460,7 +3473,7 @@ private module Subpaths { * Holds if `n` can reach a return node in a summarized subpath that can reach a sink. */ predicate retReach(PathNodeImpl n) { - exists(PathNode out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) + exists(PathNodeImpl out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) or exists(PathNodeImpl mid | retReach(mid) and @@ -3477,11 +3490,12 @@ private module Subpaths { * sinks. */ private predicate flowsTo( - PathNode flowsource, PathNodeSink flowsink, Node source, Node sink, Configuration configuration + PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink, + Configuration configuration ) { flowsource.isSource() and flowsource.getConfiguration() = configuration and - flowsource.(PathNodeImpl).getNodeEx().asNode() = source and + flowsource.getNodeEx().asNode() = source and (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and flowsink.getNodeEx().asNode() = sink } @@ -3504,14 +3518,14 @@ private predicate finalStats( fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and - tuples = count(PathNode pn) + tuples = count(PathNodeImpl pn) or fwd = false and nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and - tuples = count(PathNode pn | reach(pn)) + tuples = count(PathNode pn) } /** diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll index b5631b26b0bf..8cd1071d084a 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl2.qll @@ -2874,54 +2874,16 @@ private class AccessPathCons1 extends AccessPath, TAccessPathCons1 { } } -/** - * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. - * Only those `PathNode`s that are reachable from a source are generated. - */ -class PathNode extends TPathNode { - /** Gets a textual representation of this element. */ - string toString() { none() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - string toStringWithContext() { none() } - - /** - * 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/). - */ - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - none() - } - - /** Gets the underlying `Node`. */ - final Node getNode() { this.(PathNodeImpl).getNodeEx().projectToNode() = result } - +abstract private class PathNodeImpl extends TPathNode { /** Gets the `FlowState` of this node. */ - FlowState getState() { none() } + abstract FlowState getState(); /** Gets the associated configuration. */ - Configuration getConfiguration() { none() } - - /** Gets a successor of this node, if any. */ - final PathNode getASuccessor() { - result = this.(PathNodeImpl).getANonHiddenSuccessor() and - reach(this) and - reach(result) - } + abstract Configuration getConfiguration(); /** Holds if this node is a source. */ - predicate isSource() { none() } -} + abstract predicate isSource(); -abstract private class PathNodeImpl extends PathNode { abstract PathNodeImpl getASuccessorImpl(); private PathNodeImpl getASuccessorIfHidden() { @@ -2967,13 +2929,23 @@ abstract private class PathNodeImpl extends PathNode { result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" } - override string toString() { result = this.getNodeEx().toString() + this.ppAp() } + /** Gets a textual representation of this element. */ + string toString() { result = this.getNodeEx().toString() + this.ppAp() } - override string toStringWithContext() { - result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() - } + /** + * Gets a textual representation of this element, including a textual + * representation of the call context. + */ + string toStringWithContext() { result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() } - override predicate hasLocationInfo( + /** + * 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/). + */ + predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn ) { this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) @@ -2986,14 +2958,59 @@ private predicate directReach(PathNodeImpl n) { } /** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */ -private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) } +private predicate reach(PathNodeImpl n) { directReach(n) or Subpaths::retReach(n) } /** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */ -private predicate pathSucc(PathNodeImpl n1, PathNode n2) { +private predicate pathSucc(PathNodeImpl n1, PathNodeImpl n2) { n1.getANonHiddenSuccessor() = n2 and directReach(n2) } -private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2) +private predicate pathSuccPlus(PathNodeImpl n1, PathNodeImpl n2) = fastTC(pathSucc/2)(n1, n2) + +/** + * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. + * Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated. + */ +class PathNode instanceof PathNodeImpl { + PathNode() { reach(this) } + + /** Gets a textual representation of this element. */ + final string toString() { result = super.toString() } + + /** + * Gets a textual representation of this element, including a textual + * representation of the call context. + */ + final string toStringWithContext() { result = super.toStringWithContext() } + + /** + * 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/). + */ + final predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } + + /** Gets the underlying `Node`. */ + final Node getNode() { super.getNodeEx().projectToNode() = result } + + /** Gets the `FlowState` of this node. */ + final FlowState getState() { result = super.getState() } + + /** Gets the associated configuration. */ + final Configuration getConfiguration() { result = super.getConfiguration() } + + /** Gets a successor of this node, if any. */ + final PathNode getASuccessor() { result = super.getANonHiddenSuccessor() } + + /** Holds if this node is a source. */ + final predicate isSource() { super.isSource() } +} /** * Provides the query predicates needed to include a graph in a path-problem query. @@ -3004,7 +3021,7 @@ module PathGraph { /** Holds if `n` is a node in the graph of data flow path explanations. */ query predicate nodes(PathNode n, string key, string val) { - reach(n) and key = "semmle.label" and val = n.toString() + key = "semmle.label" and val = n.toString() } /** @@ -3013,11 +3030,7 @@ module PathGraph { * `ret -> out` is summarized as the edge `arg -> out`. */ query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) { - Subpaths::subpaths(arg, par, ret, out) and - reach(arg) and - reach(par) and - reach(ret) and - reach(out) + Subpaths::subpaths(arg, par, ret, out) } } @@ -3399,7 +3412,7 @@ private module Subpaths { */ pragma[nomagic] private predicate subpaths02( - PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, + PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, NodeEx out, FlowState sout, AccessPath apout ) { subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and @@ -3407,14 +3420,14 @@ private module Subpaths { } pragma[nomagic] - private Configuration getPathNodeConf(PathNode n) { result = n.getConfiguration() } + private Configuration getPathNodeConf(PathNodeImpl n) { result = n.getConfiguration() } /** * Holds if `(arg, par, ret, out)` forms a subpath-tuple. */ pragma[nomagic] private predicate subpaths03( - PathNode arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout + PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout ) { exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode | subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and @@ -3444,7 +3457,7 @@ private module Subpaths { * a subpath between `par` and `ret` with the connecting edges `arg -> par` and * `ret -> out` is summarized as the edge `arg -> out`. */ - predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) { + predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) { exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 | pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and @@ -3460,7 +3473,7 @@ private module Subpaths { * Holds if `n` can reach a return node in a summarized subpath that can reach a sink. */ predicate retReach(PathNodeImpl n) { - exists(PathNode out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) + exists(PathNodeImpl out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) or exists(PathNodeImpl mid | retReach(mid) and @@ -3477,11 +3490,12 @@ private module Subpaths { * sinks. */ private predicate flowsTo( - PathNode flowsource, PathNodeSink flowsink, Node source, Node sink, Configuration configuration + PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink, + Configuration configuration ) { flowsource.isSource() and flowsource.getConfiguration() = configuration and - flowsource.(PathNodeImpl).getNodeEx().asNode() = source and + flowsource.getNodeEx().asNode() = source and (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and flowsink.getNodeEx().asNode() = sink } @@ -3504,14 +3518,14 @@ private predicate finalStats( fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and - tuples = count(PathNode pn) + tuples = count(PathNodeImpl pn) or fwd = false and nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and - tuples = count(PathNode pn | reach(pn)) + tuples = count(PathNode pn) } /** diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll index b5631b26b0bf..8cd1071d084a 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl3.qll @@ -2874,54 +2874,16 @@ private class AccessPathCons1 extends AccessPath, TAccessPathCons1 { } } -/** - * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. - * Only those `PathNode`s that are reachable from a source are generated. - */ -class PathNode extends TPathNode { - /** Gets a textual representation of this element. */ - string toString() { none() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - string toStringWithContext() { none() } - - /** - * 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/). - */ - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - none() - } - - /** Gets the underlying `Node`. */ - final Node getNode() { this.(PathNodeImpl).getNodeEx().projectToNode() = result } - +abstract private class PathNodeImpl extends TPathNode { /** Gets the `FlowState` of this node. */ - FlowState getState() { none() } + abstract FlowState getState(); /** Gets the associated configuration. */ - Configuration getConfiguration() { none() } - - /** Gets a successor of this node, if any. */ - final PathNode getASuccessor() { - result = this.(PathNodeImpl).getANonHiddenSuccessor() and - reach(this) and - reach(result) - } + abstract Configuration getConfiguration(); /** Holds if this node is a source. */ - predicate isSource() { none() } -} + abstract predicate isSource(); -abstract private class PathNodeImpl extends PathNode { abstract PathNodeImpl getASuccessorImpl(); private PathNodeImpl getASuccessorIfHidden() { @@ -2967,13 +2929,23 @@ abstract private class PathNodeImpl extends PathNode { result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" } - override string toString() { result = this.getNodeEx().toString() + this.ppAp() } + /** Gets a textual representation of this element. */ + string toString() { result = this.getNodeEx().toString() + this.ppAp() } - override string toStringWithContext() { - result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() - } + /** + * Gets a textual representation of this element, including a textual + * representation of the call context. + */ + string toStringWithContext() { result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() } - override predicate hasLocationInfo( + /** + * 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/). + */ + predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn ) { this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) @@ -2986,14 +2958,59 @@ private predicate directReach(PathNodeImpl n) { } /** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */ -private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) } +private predicate reach(PathNodeImpl n) { directReach(n) or Subpaths::retReach(n) } /** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */ -private predicate pathSucc(PathNodeImpl n1, PathNode n2) { +private predicate pathSucc(PathNodeImpl n1, PathNodeImpl n2) { n1.getANonHiddenSuccessor() = n2 and directReach(n2) } -private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2) +private predicate pathSuccPlus(PathNodeImpl n1, PathNodeImpl n2) = fastTC(pathSucc/2)(n1, n2) + +/** + * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. + * Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated. + */ +class PathNode instanceof PathNodeImpl { + PathNode() { reach(this) } + + /** Gets a textual representation of this element. */ + final string toString() { result = super.toString() } + + /** + * Gets a textual representation of this element, including a textual + * representation of the call context. + */ + final string toStringWithContext() { result = super.toStringWithContext() } + + /** + * 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/). + */ + final predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } + + /** Gets the underlying `Node`. */ + final Node getNode() { super.getNodeEx().projectToNode() = result } + + /** Gets the `FlowState` of this node. */ + final FlowState getState() { result = super.getState() } + + /** Gets the associated configuration. */ + final Configuration getConfiguration() { result = super.getConfiguration() } + + /** Gets a successor of this node, if any. */ + final PathNode getASuccessor() { result = super.getANonHiddenSuccessor() } + + /** Holds if this node is a source. */ + final predicate isSource() { super.isSource() } +} /** * Provides the query predicates needed to include a graph in a path-problem query. @@ -3004,7 +3021,7 @@ module PathGraph { /** Holds if `n` is a node in the graph of data flow path explanations. */ query predicate nodes(PathNode n, string key, string val) { - reach(n) and key = "semmle.label" and val = n.toString() + key = "semmle.label" and val = n.toString() } /** @@ -3013,11 +3030,7 @@ module PathGraph { * `ret -> out` is summarized as the edge `arg -> out`. */ query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) { - Subpaths::subpaths(arg, par, ret, out) and - reach(arg) and - reach(par) and - reach(ret) and - reach(out) + Subpaths::subpaths(arg, par, ret, out) } } @@ -3399,7 +3412,7 @@ private module Subpaths { */ pragma[nomagic] private predicate subpaths02( - PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, + PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, NodeEx out, FlowState sout, AccessPath apout ) { subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and @@ -3407,14 +3420,14 @@ private module Subpaths { } pragma[nomagic] - private Configuration getPathNodeConf(PathNode n) { result = n.getConfiguration() } + private Configuration getPathNodeConf(PathNodeImpl n) { result = n.getConfiguration() } /** * Holds if `(arg, par, ret, out)` forms a subpath-tuple. */ pragma[nomagic] private predicate subpaths03( - PathNode arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout + PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout ) { exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode | subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and @@ -3444,7 +3457,7 @@ private module Subpaths { * a subpath between `par` and `ret` with the connecting edges `arg -> par` and * `ret -> out` is summarized as the edge `arg -> out`. */ - predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) { + predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) { exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 | pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and @@ -3460,7 +3473,7 @@ private module Subpaths { * Holds if `n` can reach a return node in a summarized subpath that can reach a sink. */ predicate retReach(PathNodeImpl n) { - exists(PathNode out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) + exists(PathNodeImpl out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) or exists(PathNodeImpl mid | retReach(mid) and @@ -3477,11 +3490,12 @@ private module Subpaths { * sinks. */ private predicate flowsTo( - PathNode flowsource, PathNodeSink flowsink, Node source, Node sink, Configuration configuration + PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink, + Configuration configuration ) { flowsource.isSource() and flowsource.getConfiguration() = configuration and - flowsource.(PathNodeImpl).getNodeEx().asNode() = source and + flowsource.getNodeEx().asNode() = source and (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and flowsink.getNodeEx().asNode() = sink } @@ -3504,14 +3518,14 @@ private predicate finalStats( fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and - tuples = count(PathNode pn) + tuples = count(PathNodeImpl pn) or fwd = false and nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and - tuples = count(PathNode pn | reach(pn)) + tuples = count(PathNode pn) } /** diff --git a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll index b5631b26b0bf..8cd1071d084a 100644 --- a/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll +++ b/cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl4.qll @@ -2874,54 +2874,16 @@ private class AccessPathCons1 extends AccessPath, TAccessPathCons1 { } } -/** - * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. - * Only those `PathNode`s that are reachable from a source are generated. - */ -class PathNode extends TPathNode { - /** Gets a textual representation of this element. */ - string toString() { none() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - string toStringWithContext() { none() } - - /** - * 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/). - */ - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - none() - } - - /** Gets the underlying `Node`. */ - final Node getNode() { this.(PathNodeImpl).getNodeEx().projectToNode() = result } - +abstract private class PathNodeImpl extends TPathNode { /** Gets the `FlowState` of this node. */ - FlowState getState() { none() } + abstract FlowState getState(); /** Gets the associated configuration. */ - Configuration getConfiguration() { none() } - - /** Gets a successor of this node, if any. */ - final PathNode getASuccessor() { - result = this.(PathNodeImpl).getANonHiddenSuccessor() and - reach(this) and - reach(result) - } + abstract Configuration getConfiguration(); /** Holds if this node is a source. */ - predicate isSource() { none() } -} + abstract predicate isSource(); -abstract private class PathNodeImpl extends PathNode { abstract PathNodeImpl getASuccessorImpl(); private PathNodeImpl getASuccessorIfHidden() { @@ -2967,13 +2929,23 @@ abstract private class PathNodeImpl extends PathNode { result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" } - override string toString() { result = this.getNodeEx().toString() + this.ppAp() } + /** Gets a textual representation of this element. */ + string toString() { result = this.getNodeEx().toString() + this.ppAp() } - override string toStringWithContext() { - result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() - } + /** + * Gets a textual representation of this element, including a textual + * representation of the call context. + */ + string toStringWithContext() { result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() } - override predicate hasLocationInfo( + /** + * 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/). + */ + predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn ) { this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) @@ -2986,14 +2958,59 @@ private predicate directReach(PathNodeImpl n) { } /** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */ -private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) } +private predicate reach(PathNodeImpl n) { directReach(n) or Subpaths::retReach(n) } /** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */ -private predicate pathSucc(PathNodeImpl n1, PathNode n2) { +private predicate pathSucc(PathNodeImpl n1, PathNodeImpl n2) { n1.getANonHiddenSuccessor() = n2 and directReach(n2) } -private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2) +private predicate pathSuccPlus(PathNodeImpl n1, PathNodeImpl n2) = fastTC(pathSucc/2)(n1, n2) + +/** + * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. + * Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated. + */ +class PathNode instanceof PathNodeImpl { + PathNode() { reach(this) } + + /** Gets a textual representation of this element. */ + final string toString() { result = super.toString() } + + /** + * Gets a textual representation of this element, including a textual + * representation of the call context. + */ + final string toStringWithContext() { result = super.toStringWithContext() } + + /** + * 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/). + */ + final predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } + + /** Gets the underlying `Node`. */ + final Node getNode() { super.getNodeEx().projectToNode() = result } + + /** Gets the `FlowState` of this node. */ + final FlowState getState() { result = super.getState() } + + /** Gets the associated configuration. */ + final Configuration getConfiguration() { result = super.getConfiguration() } + + /** Gets a successor of this node, if any. */ + final PathNode getASuccessor() { result = super.getANonHiddenSuccessor() } + + /** Holds if this node is a source. */ + final predicate isSource() { super.isSource() } +} /** * Provides the query predicates needed to include a graph in a path-problem query. @@ -3004,7 +3021,7 @@ module PathGraph { /** Holds if `n` is a node in the graph of data flow path explanations. */ query predicate nodes(PathNode n, string key, string val) { - reach(n) and key = "semmle.label" and val = n.toString() + key = "semmle.label" and val = n.toString() } /** @@ -3013,11 +3030,7 @@ module PathGraph { * `ret -> out` is summarized as the edge `arg -> out`. */ query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) { - Subpaths::subpaths(arg, par, ret, out) and - reach(arg) and - reach(par) and - reach(ret) and - reach(out) + Subpaths::subpaths(arg, par, ret, out) } } @@ -3399,7 +3412,7 @@ private module Subpaths { */ pragma[nomagic] private predicate subpaths02( - PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, + PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, NodeEx out, FlowState sout, AccessPath apout ) { subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and @@ -3407,14 +3420,14 @@ private module Subpaths { } pragma[nomagic] - private Configuration getPathNodeConf(PathNode n) { result = n.getConfiguration() } + private Configuration getPathNodeConf(PathNodeImpl n) { result = n.getConfiguration() } /** * Holds if `(arg, par, ret, out)` forms a subpath-tuple. */ pragma[nomagic] private predicate subpaths03( - PathNode arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout + PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout ) { exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode | subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and @@ -3444,7 +3457,7 @@ private module Subpaths { * a subpath between `par` and `ret` with the connecting edges `arg -> par` and * `ret -> out` is summarized as the edge `arg -> out`. */ - predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) { + predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) { exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 | pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and @@ -3460,7 +3473,7 @@ private module Subpaths { * Holds if `n` can reach a return node in a summarized subpath that can reach a sink. */ predicate retReach(PathNodeImpl n) { - exists(PathNode out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) + exists(PathNodeImpl out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) or exists(PathNodeImpl mid | retReach(mid) and @@ -3477,11 +3490,12 @@ private module Subpaths { * sinks. */ private predicate flowsTo( - PathNode flowsource, PathNodeSink flowsink, Node source, Node sink, Configuration configuration + PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink, + Configuration configuration ) { flowsource.isSource() and flowsource.getConfiguration() = configuration and - flowsource.(PathNodeImpl).getNodeEx().asNode() = source and + flowsource.getNodeEx().asNode() = source and (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and flowsink.getNodeEx().asNode() = sink } @@ -3504,14 +3518,14 @@ private predicate finalStats( fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and - tuples = count(PathNode pn) + tuples = count(PathNodeImpl pn) or fwd = false and nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and - tuples = count(PathNode pn | reach(pn)) + tuples = count(PathNode pn) } /** diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll index b5631b26b0bf..8cd1071d084a 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl.qll @@ -2874,54 +2874,16 @@ private class AccessPathCons1 extends AccessPath, TAccessPathCons1 { } } -/** - * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. - * Only those `PathNode`s that are reachable from a source are generated. - */ -class PathNode extends TPathNode { - /** Gets a textual representation of this element. */ - string toString() { none() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - string toStringWithContext() { none() } - - /** - * 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/). - */ - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - none() - } - - /** Gets the underlying `Node`. */ - final Node getNode() { this.(PathNodeImpl).getNodeEx().projectToNode() = result } - +abstract private class PathNodeImpl extends TPathNode { /** Gets the `FlowState` of this node. */ - FlowState getState() { none() } + abstract FlowState getState(); /** Gets the associated configuration. */ - Configuration getConfiguration() { none() } - - /** Gets a successor of this node, if any. */ - final PathNode getASuccessor() { - result = this.(PathNodeImpl).getANonHiddenSuccessor() and - reach(this) and - reach(result) - } + abstract Configuration getConfiguration(); /** Holds if this node is a source. */ - predicate isSource() { none() } -} + abstract predicate isSource(); -abstract private class PathNodeImpl extends PathNode { abstract PathNodeImpl getASuccessorImpl(); private PathNodeImpl getASuccessorIfHidden() { @@ -2967,13 +2929,23 @@ abstract private class PathNodeImpl extends PathNode { result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" } - override string toString() { result = this.getNodeEx().toString() + this.ppAp() } + /** Gets a textual representation of this element. */ + string toString() { result = this.getNodeEx().toString() + this.ppAp() } - override string toStringWithContext() { - result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() - } + /** + * Gets a textual representation of this element, including a textual + * representation of the call context. + */ + string toStringWithContext() { result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() } - override predicate hasLocationInfo( + /** + * 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/). + */ + predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn ) { this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) @@ -2986,14 +2958,59 @@ private predicate directReach(PathNodeImpl n) { } /** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */ -private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) } +private predicate reach(PathNodeImpl n) { directReach(n) or Subpaths::retReach(n) } /** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */ -private predicate pathSucc(PathNodeImpl n1, PathNode n2) { +private predicate pathSucc(PathNodeImpl n1, PathNodeImpl n2) { n1.getANonHiddenSuccessor() = n2 and directReach(n2) } -private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2) +private predicate pathSuccPlus(PathNodeImpl n1, PathNodeImpl n2) = fastTC(pathSucc/2)(n1, n2) + +/** + * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. + * Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated. + */ +class PathNode instanceof PathNodeImpl { + PathNode() { reach(this) } + + /** Gets a textual representation of this element. */ + final string toString() { result = super.toString() } + + /** + * Gets a textual representation of this element, including a textual + * representation of the call context. + */ + final string toStringWithContext() { result = super.toStringWithContext() } + + /** + * 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/). + */ + final predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } + + /** Gets the underlying `Node`. */ + final Node getNode() { super.getNodeEx().projectToNode() = result } + + /** Gets the `FlowState` of this node. */ + final FlowState getState() { result = super.getState() } + + /** Gets the associated configuration. */ + final Configuration getConfiguration() { result = super.getConfiguration() } + + /** Gets a successor of this node, if any. */ + final PathNode getASuccessor() { result = super.getANonHiddenSuccessor() } + + /** Holds if this node is a source. */ + final predicate isSource() { super.isSource() } +} /** * Provides the query predicates needed to include a graph in a path-problem query. @@ -3004,7 +3021,7 @@ module PathGraph { /** Holds if `n` is a node in the graph of data flow path explanations. */ query predicate nodes(PathNode n, string key, string val) { - reach(n) and key = "semmle.label" and val = n.toString() + key = "semmle.label" and val = n.toString() } /** @@ -3013,11 +3030,7 @@ module PathGraph { * `ret -> out` is summarized as the edge `arg -> out`. */ query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) { - Subpaths::subpaths(arg, par, ret, out) and - reach(arg) and - reach(par) and - reach(ret) and - reach(out) + Subpaths::subpaths(arg, par, ret, out) } } @@ -3399,7 +3412,7 @@ private module Subpaths { */ pragma[nomagic] private predicate subpaths02( - PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, + PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, NodeEx out, FlowState sout, AccessPath apout ) { subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and @@ -3407,14 +3420,14 @@ private module Subpaths { } pragma[nomagic] - private Configuration getPathNodeConf(PathNode n) { result = n.getConfiguration() } + private Configuration getPathNodeConf(PathNodeImpl n) { result = n.getConfiguration() } /** * Holds if `(arg, par, ret, out)` forms a subpath-tuple. */ pragma[nomagic] private predicate subpaths03( - PathNode arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout + PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout ) { exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode | subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and @@ -3444,7 +3457,7 @@ private module Subpaths { * a subpath between `par` and `ret` with the connecting edges `arg -> par` and * `ret -> out` is summarized as the edge `arg -> out`. */ - predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) { + predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) { exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 | pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and @@ -3460,7 +3473,7 @@ private module Subpaths { * Holds if `n` can reach a return node in a summarized subpath that can reach a sink. */ predicate retReach(PathNodeImpl n) { - exists(PathNode out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) + exists(PathNodeImpl out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) or exists(PathNodeImpl mid | retReach(mid) and @@ -3477,11 +3490,12 @@ private module Subpaths { * sinks. */ private predicate flowsTo( - PathNode flowsource, PathNodeSink flowsink, Node source, Node sink, Configuration configuration + PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink, + Configuration configuration ) { flowsource.isSource() and flowsource.getConfiguration() = configuration and - flowsource.(PathNodeImpl).getNodeEx().asNode() = source and + flowsource.getNodeEx().asNode() = source and (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and flowsink.getNodeEx().asNode() = sink } @@ -3504,14 +3518,14 @@ private predicate finalStats( fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and - tuples = count(PathNode pn) + tuples = count(PathNodeImpl pn) or fwd = false and nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and - tuples = count(PathNode pn | reach(pn)) + tuples = count(PathNode pn) } /** diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll index b5631b26b0bf..8cd1071d084a 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl2.qll @@ -2874,54 +2874,16 @@ private class AccessPathCons1 extends AccessPath, TAccessPathCons1 { } } -/** - * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. - * Only those `PathNode`s that are reachable from a source are generated. - */ -class PathNode extends TPathNode { - /** Gets a textual representation of this element. */ - string toString() { none() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - string toStringWithContext() { none() } - - /** - * 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/). - */ - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - none() - } - - /** Gets the underlying `Node`. */ - final Node getNode() { this.(PathNodeImpl).getNodeEx().projectToNode() = result } - +abstract private class PathNodeImpl extends TPathNode { /** Gets the `FlowState` of this node. */ - FlowState getState() { none() } + abstract FlowState getState(); /** Gets the associated configuration. */ - Configuration getConfiguration() { none() } - - /** Gets a successor of this node, if any. */ - final PathNode getASuccessor() { - result = this.(PathNodeImpl).getANonHiddenSuccessor() and - reach(this) and - reach(result) - } + abstract Configuration getConfiguration(); /** Holds if this node is a source. */ - predicate isSource() { none() } -} + abstract predicate isSource(); -abstract private class PathNodeImpl extends PathNode { abstract PathNodeImpl getASuccessorImpl(); private PathNodeImpl getASuccessorIfHidden() { @@ -2967,13 +2929,23 @@ abstract private class PathNodeImpl extends PathNode { result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" } - override string toString() { result = this.getNodeEx().toString() + this.ppAp() } + /** Gets a textual representation of this element. */ + string toString() { result = this.getNodeEx().toString() + this.ppAp() } - override string toStringWithContext() { - result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() - } + /** + * Gets a textual representation of this element, including a textual + * representation of the call context. + */ + string toStringWithContext() { result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() } - override predicate hasLocationInfo( + /** + * 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/). + */ + predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn ) { this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) @@ -2986,14 +2958,59 @@ private predicate directReach(PathNodeImpl n) { } /** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */ -private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) } +private predicate reach(PathNodeImpl n) { directReach(n) or Subpaths::retReach(n) } /** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */ -private predicate pathSucc(PathNodeImpl n1, PathNode n2) { +private predicate pathSucc(PathNodeImpl n1, PathNodeImpl n2) { n1.getANonHiddenSuccessor() = n2 and directReach(n2) } -private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2) +private predicate pathSuccPlus(PathNodeImpl n1, PathNodeImpl n2) = fastTC(pathSucc/2)(n1, n2) + +/** + * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. + * Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated. + */ +class PathNode instanceof PathNodeImpl { + PathNode() { reach(this) } + + /** Gets a textual representation of this element. */ + final string toString() { result = super.toString() } + + /** + * Gets a textual representation of this element, including a textual + * representation of the call context. + */ + final string toStringWithContext() { result = super.toStringWithContext() } + + /** + * 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/). + */ + final predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } + + /** Gets the underlying `Node`. */ + final Node getNode() { super.getNodeEx().projectToNode() = result } + + /** Gets the `FlowState` of this node. */ + final FlowState getState() { result = super.getState() } + + /** Gets the associated configuration. */ + final Configuration getConfiguration() { result = super.getConfiguration() } + + /** Gets a successor of this node, if any. */ + final PathNode getASuccessor() { result = super.getANonHiddenSuccessor() } + + /** Holds if this node is a source. */ + final predicate isSource() { super.isSource() } +} /** * Provides the query predicates needed to include a graph in a path-problem query. @@ -3004,7 +3021,7 @@ module PathGraph { /** Holds if `n` is a node in the graph of data flow path explanations. */ query predicate nodes(PathNode n, string key, string val) { - reach(n) and key = "semmle.label" and val = n.toString() + key = "semmle.label" and val = n.toString() } /** @@ -3013,11 +3030,7 @@ module PathGraph { * `ret -> out` is summarized as the edge `arg -> out`. */ query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) { - Subpaths::subpaths(arg, par, ret, out) and - reach(arg) and - reach(par) and - reach(ret) and - reach(out) + Subpaths::subpaths(arg, par, ret, out) } } @@ -3399,7 +3412,7 @@ private module Subpaths { */ pragma[nomagic] private predicate subpaths02( - PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, + PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, NodeEx out, FlowState sout, AccessPath apout ) { subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and @@ -3407,14 +3420,14 @@ private module Subpaths { } pragma[nomagic] - private Configuration getPathNodeConf(PathNode n) { result = n.getConfiguration() } + private Configuration getPathNodeConf(PathNodeImpl n) { result = n.getConfiguration() } /** * Holds if `(arg, par, ret, out)` forms a subpath-tuple. */ pragma[nomagic] private predicate subpaths03( - PathNode arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout + PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout ) { exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode | subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and @@ -3444,7 +3457,7 @@ private module Subpaths { * a subpath between `par` and `ret` with the connecting edges `arg -> par` and * `ret -> out` is summarized as the edge `arg -> out`. */ - predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) { + predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) { exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 | pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and @@ -3460,7 +3473,7 @@ private module Subpaths { * Holds if `n` can reach a return node in a summarized subpath that can reach a sink. */ predicate retReach(PathNodeImpl n) { - exists(PathNode out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) + exists(PathNodeImpl out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) or exists(PathNodeImpl mid | retReach(mid) and @@ -3477,11 +3490,12 @@ private module Subpaths { * sinks. */ private predicate flowsTo( - PathNode flowsource, PathNodeSink flowsink, Node source, Node sink, Configuration configuration + PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink, + Configuration configuration ) { flowsource.isSource() and flowsource.getConfiguration() = configuration and - flowsource.(PathNodeImpl).getNodeEx().asNode() = source and + flowsource.getNodeEx().asNode() = source and (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and flowsink.getNodeEx().asNode() = sink } @@ -3504,14 +3518,14 @@ private predicate finalStats( fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and - tuples = count(PathNode pn) + tuples = count(PathNodeImpl pn) or fwd = false and nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and - tuples = count(PathNode pn | reach(pn)) + tuples = count(PathNode pn) } /** diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll index b5631b26b0bf..8cd1071d084a 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl3.qll @@ -2874,54 +2874,16 @@ private class AccessPathCons1 extends AccessPath, TAccessPathCons1 { } } -/** - * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. - * Only those `PathNode`s that are reachable from a source are generated. - */ -class PathNode extends TPathNode { - /** Gets a textual representation of this element. */ - string toString() { none() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - string toStringWithContext() { none() } - - /** - * 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/). - */ - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - none() - } - - /** Gets the underlying `Node`. */ - final Node getNode() { this.(PathNodeImpl).getNodeEx().projectToNode() = result } - +abstract private class PathNodeImpl extends TPathNode { /** Gets the `FlowState` of this node. */ - FlowState getState() { none() } + abstract FlowState getState(); /** Gets the associated configuration. */ - Configuration getConfiguration() { none() } - - /** Gets a successor of this node, if any. */ - final PathNode getASuccessor() { - result = this.(PathNodeImpl).getANonHiddenSuccessor() and - reach(this) and - reach(result) - } + abstract Configuration getConfiguration(); /** Holds if this node is a source. */ - predicate isSource() { none() } -} + abstract predicate isSource(); -abstract private class PathNodeImpl extends PathNode { abstract PathNodeImpl getASuccessorImpl(); private PathNodeImpl getASuccessorIfHidden() { @@ -2967,13 +2929,23 @@ abstract private class PathNodeImpl extends PathNode { result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" } - override string toString() { result = this.getNodeEx().toString() + this.ppAp() } + /** Gets a textual representation of this element. */ + string toString() { result = this.getNodeEx().toString() + this.ppAp() } - override string toStringWithContext() { - result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() - } + /** + * Gets a textual representation of this element, including a textual + * representation of the call context. + */ + string toStringWithContext() { result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() } - override predicate hasLocationInfo( + /** + * 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/). + */ + predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn ) { this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) @@ -2986,14 +2958,59 @@ private predicate directReach(PathNodeImpl n) { } /** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */ -private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) } +private predicate reach(PathNodeImpl n) { directReach(n) or Subpaths::retReach(n) } /** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */ -private predicate pathSucc(PathNodeImpl n1, PathNode n2) { +private predicate pathSucc(PathNodeImpl n1, PathNodeImpl n2) { n1.getANonHiddenSuccessor() = n2 and directReach(n2) } -private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2) +private predicate pathSuccPlus(PathNodeImpl n1, PathNodeImpl n2) = fastTC(pathSucc/2)(n1, n2) + +/** + * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. + * Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated. + */ +class PathNode instanceof PathNodeImpl { + PathNode() { reach(this) } + + /** Gets a textual representation of this element. */ + final string toString() { result = super.toString() } + + /** + * Gets a textual representation of this element, including a textual + * representation of the call context. + */ + final string toStringWithContext() { result = super.toStringWithContext() } + + /** + * 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/). + */ + final predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } + + /** Gets the underlying `Node`. */ + final Node getNode() { super.getNodeEx().projectToNode() = result } + + /** Gets the `FlowState` of this node. */ + final FlowState getState() { result = super.getState() } + + /** Gets the associated configuration. */ + final Configuration getConfiguration() { result = super.getConfiguration() } + + /** Gets a successor of this node, if any. */ + final PathNode getASuccessor() { result = super.getANonHiddenSuccessor() } + + /** Holds if this node is a source. */ + final predicate isSource() { super.isSource() } +} /** * Provides the query predicates needed to include a graph in a path-problem query. @@ -3004,7 +3021,7 @@ module PathGraph { /** Holds if `n` is a node in the graph of data flow path explanations. */ query predicate nodes(PathNode n, string key, string val) { - reach(n) and key = "semmle.label" and val = n.toString() + key = "semmle.label" and val = n.toString() } /** @@ -3013,11 +3030,7 @@ module PathGraph { * `ret -> out` is summarized as the edge `arg -> out`. */ query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) { - Subpaths::subpaths(arg, par, ret, out) and - reach(arg) and - reach(par) and - reach(ret) and - reach(out) + Subpaths::subpaths(arg, par, ret, out) } } @@ -3399,7 +3412,7 @@ private module Subpaths { */ pragma[nomagic] private predicate subpaths02( - PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, + PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, NodeEx out, FlowState sout, AccessPath apout ) { subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and @@ -3407,14 +3420,14 @@ private module Subpaths { } pragma[nomagic] - private Configuration getPathNodeConf(PathNode n) { result = n.getConfiguration() } + private Configuration getPathNodeConf(PathNodeImpl n) { result = n.getConfiguration() } /** * Holds if `(arg, par, ret, out)` forms a subpath-tuple. */ pragma[nomagic] private predicate subpaths03( - PathNode arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout + PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout ) { exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode | subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and @@ -3444,7 +3457,7 @@ private module Subpaths { * a subpath between `par` and `ret` with the connecting edges `arg -> par` and * `ret -> out` is summarized as the edge `arg -> out`. */ - predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) { + predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) { exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 | pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and @@ -3460,7 +3473,7 @@ private module Subpaths { * Holds if `n` can reach a return node in a summarized subpath that can reach a sink. */ predicate retReach(PathNodeImpl n) { - exists(PathNode out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) + exists(PathNodeImpl out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) or exists(PathNodeImpl mid | retReach(mid) and @@ -3477,11 +3490,12 @@ private module Subpaths { * sinks. */ private predicate flowsTo( - PathNode flowsource, PathNodeSink flowsink, Node source, Node sink, Configuration configuration + PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink, + Configuration configuration ) { flowsource.isSource() and flowsource.getConfiguration() = configuration and - flowsource.(PathNodeImpl).getNodeEx().asNode() = source and + flowsource.getNodeEx().asNode() = source and (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and flowsink.getNodeEx().asNode() = sink } @@ -3504,14 +3518,14 @@ private predicate finalStats( fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and - tuples = count(PathNode pn) + tuples = count(PathNodeImpl pn) or fwd = false and nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and - tuples = count(PathNode pn | reach(pn)) + tuples = count(PathNode pn) } /** diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll index b5631b26b0bf..8cd1071d084a 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl4.qll @@ -2874,54 +2874,16 @@ private class AccessPathCons1 extends AccessPath, TAccessPathCons1 { } } -/** - * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. - * Only those `PathNode`s that are reachable from a source are generated. - */ -class PathNode extends TPathNode { - /** Gets a textual representation of this element. */ - string toString() { none() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - string toStringWithContext() { none() } - - /** - * 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/). - */ - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - none() - } - - /** Gets the underlying `Node`. */ - final Node getNode() { this.(PathNodeImpl).getNodeEx().projectToNode() = result } - +abstract private class PathNodeImpl extends TPathNode { /** Gets the `FlowState` of this node. */ - FlowState getState() { none() } + abstract FlowState getState(); /** Gets the associated configuration. */ - Configuration getConfiguration() { none() } - - /** Gets a successor of this node, if any. */ - final PathNode getASuccessor() { - result = this.(PathNodeImpl).getANonHiddenSuccessor() and - reach(this) and - reach(result) - } + abstract Configuration getConfiguration(); /** Holds if this node is a source. */ - predicate isSource() { none() } -} + abstract predicate isSource(); -abstract private class PathNodeImpl extends PathNode { abstract PathNodeImpl getASuccessorImpl(); private PathNodeImpl getASuccessorIfHidden() { @@ -2967,13 +2929,23 @@ abstract private class PathNodeImpl extends PathNode { result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" } - override string toString() { result = this.getNodeEx().toString() + this.ppAp() } + /** Gets a textual representation of this element. */ + string toString() { result = this.getNodeEx().toString() + this.ppAp() } - override string toStringWithContext() { - result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() - } + /** + * Gets a textual representation of this element, including a textual + * representation of the call context. + */ + string toStringWithContext() { result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() } - override predicate hasLocationInfo( + /** + * 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/). + */ + predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn ) { this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) @@ -2986,14 +2958,59 @@ private predicate directReach(PathNodeImpl n) { } /** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */ -private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) } +private predicate reach(PathNodeImpl n) { directReach(n) or Subpaths::retReach(n) } /** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */ -private predicate pathSucc(PathNodeImpl n1, PathNode n2) { +private predicate pathSucc(PathNodeImpl n1, PathNodeImpl n2) { n1.getANonHiddenSuccessor() = n2 and directReach(n2) } -private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2) +private predicate pathSuccPlus(PathNodeImpl n1, PathNodeImpl n2) = fastTC(pathSucc/2)(n1, n2) + +/** + * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. + * Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated. + */ +class PathNode instanceof PathNodeImpl { + PathNode() { reach(this) } + + /** Gets a textual representation of this element. */ + final string toString() { result = super.toString() } + + /** + * Gets a textual representation of this element, including a textual + * representation of the call context. + */ + final string toStringWithContext() { result = super.toStringWithContext() } + + /** + * 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/). + */ + final predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } + + /** Gets the underlying `Node`. */ + final Node getNode() { super.getNodeEx().projectToNode() = result } + + /** Gets the `FlowState` of this node. */ + final FlowState getState() { result = super.getState() } + + /** Gets the associated configuration. */ + final Configuration getConfiguration() { result = super.getConfiguration() } + + /** Gets a successor of this node, if any. */ + final PathNode getASuccessor() { result = super.getANonHiddenSuccessor() } + + /** Holds if this node is a source. */ + final predicate isSource() { super.isSource() } +} /** * Provides the query predicates needed to include a graph in a path-problem query. @@ -3004,7 +3021,7 @@ module PathGraph { /** Holds if `n` is a node in the graph of data flow path explanations. */ query predicate nodes(PathNode n, string key, string val) { - reach(n) and key = "semmle.label" and val = n.toString() + key = "semmle.label" and val = n.toString() } /** @@ -3013,11 +3030,7 @@ module PathGraph { * `ret -> out` is summarized as the edge `arg -> out`. */ query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) { - Subpaths::subpaths(arg, par, ret, out) and - reach(arg) and - reach(par) and - reach(ret) and - reach(out) + Subpaths::subpaths(arg, par, ret, out) } } @@ -3399,7 +3412,7 @@ private module Subpaths { */ pragma[nomagic] private predicate subpaths02( - PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, + PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, NodeEx out, FlowState sout, AccessPath apout ) { subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and @@ -3407,14 +3420,14 @@ private module Subpaths { } pragma[nomagic] - private Configuration getPathNodeConf(PathNode n) { result = n.getConfiguration() } + private Configuration getPathNodeConf(PathNodeImpl n) { result = n.getConfiguration() } /** * Holds if `(arg, par, ret, out)` forms a subpath-tuple. */ pragma[nomagic] private predicate subpaths03( - PathNode arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout + PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout ) { exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode | subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and @@ -3444,7 +3457,7 @@ private module Subpaths { * a subpath between `par` and `ret` with the connecting edges `arg -> par` and * `ret -> out` is summarized as the edge `arg -> out`. */ - predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) { + predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) { exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 | pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and @@ -3460,7 +3473,7 @@ private module Subpaths { * Holds if `n` can reach a return node in a summarized subpath that can reach a sink. */ predicate retReach(PathNodeImpl n) { - exists(PathNode out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) + exists(PathNodeImpl out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) or exists(PathNodeImpl mid | retReach(mid) and @@ -3477,11 +3490,12 @@ private module Subpaths { * sinks. */ private predicate flowsTo( - PathNode flowsource, PathNodeSink flowsink, Node source, Node sink, Configuration configuration + PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink, + Configuration configuration ) { flowsource.isSource() and flowsource.getConfiguration() = configuration and - flowsource.(PathNodeImpl).getNodeEx().asNode() = source and + flowsource.getNodeEx().asNode() = source and (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and flowsink.getNodeEx().asNode() = sink } @@ -3504,14 +3518,14 @@ private predicate finalStats( fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and - tuples = count(PathNode pn) + tuples = count(PathNodeImpl pn) or fwd = false and nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and - tuples = count(PathNode pn | reach(pn)) + tuples = count(PathNode pn) } /** diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll index b5631b26b0bf..8cd1071d084a 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImpl5.qll @@ -2874,54 +2874,16 @@ private class AccessPathCons1 extends AccessPath, TAccessPathCons1 { } } -/** - * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. - * Only those `PathNode`s that are reachable from a source are generated. - */ -class PathNode extends TPathNode { - /** Gets a textual representation of this element. */ - string toString() { none() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - string toStringWithContext() { none() } - - /** - * 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/). - */ - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - none() - } - - /** Gets the underlying `Node`. */ - final Node getNode() { this.(PathNodeImpl).getNodeEx().projectToNode() = result } - +abstract private class PathNodeImpl extends TPathNode { /** Gets the `FlowState` of this node. */ - FlowState getState() { none() } + abstract FlowState getState(); /** Gets the associated configuration. */ - Configuration getConfiguration() { none() } - - /** Gets a successor of this node, if any. */ - final PathNode getASuccessor() { - result = this.(PathNodeImpl).getANonHiddenSuccessor() and - reach(this) and - reach(result) - } + abstract Configuration getConfiguration(); /** Holds if this node is a source. */ - predicate isSource() { none() } -} + abstract predicate isSource(); -abstract private class PathNodeImpl extends PathNode { abstract PathNodeImpl getASuccessorImpl(); private PathNodeImpl getASuccessorIfHidden() { @@ -2967,13 +2929,23 @@ abstract private class PathNodeImpl extends PathNode { result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" } - override string toString() { result = this.getNodeEx().toString() + this.ppAp() } + /** Gets a textual representation of this element. */ + string toString() { result = this.getNodeEx().toString() + this.ppAp() } - override string toStringWithContext() { - result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() - } + /** + * Gets a textual representation of this element, including a textual + * representation of the call context. + */ + string toStringWithContext() { result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() } - override predicate hasLocationInfo( + /** + * 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/). + */ + predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn ) { this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) @@ -2986,14 +2958,59 @@ private predicate directReach(PathNodeImpl n) { } /** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */ -private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) } +private predicate reach(PathNodeImpl n) { directReach(n) or Subpaths::retReach(n) } /** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */ -private predicate pathSucc(PathNodeImpl n1, PathNode n2) { +private predicate pathSucc(PathNodeImpl n1, PathNodeImpl n2) { n1.getANonHiddenSuccessor() = n2 and directReach(n2) } -private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2) +private predicate pathSuccPlus(PathNodeImpl n1, PathNodeImpl n2) = fastTC(pathSucc/2)(n1, n2) + +/** + * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. + * Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated. + */ +class PathNode instanceof PathNodeImpl { + PathNode() { reach(this) } + + /** Gets a textual representation of this element. */ + final string toString() { result = super.toString() } + + /** + * Gets a textual representation of this element, including a textual + * representation of the call context. + */ + final string toStringWithContext() { result = super.toStringWithContext() } + + /** + * 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/). + */ + final predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } + + /** Gets the underlying `Node`. */ + final Node getNode() { super.getNodeEx().projectToNode() = result } + + /** Gets the `FlowState` of this node. */ + final FlowState getState() { result = super.getState() } + + /** Gets the associated configuration. */ + final Configuration getConfiguration() { result = super.getConfiguration() } + + /** Gets a successor of this node, if any. */ + final PathNode getASuccessor() { result = super.getANonHiddenSuccessor() } + + /** Holds if this node is a source. */ + final predicate isSource() { super.isSource() } +} /** * Provides the query predicates needed to include a graph in a path-problem query. @@ -3004,7 +3021,7 @@ module PathGraph { /** Holds if `n` is a node in the graph of data flow path explanations. */ query predicate nodes(PathNode n, string key, string val) { - reach(n) and key = "semmle.label" and val = n.toString() + key = "semmle.label" and val = n.toString() } /** @@ -3013,11 +3030,7 @@ module PathGraph { * `ret -> out` is summarized as the edge `arg -> out`. */ query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) { - Subpaths::subpaths(arg, par, ret, out) and - reach(arg) and - reach(par) and - reach(ret) and - reach(out) + Subpaths::subpaths(arg, par, ret, out) } } @@ -3399,7 +3412,7 @@ private module Subpaths { */ pragma[nomagic] private predicate subpaths02( - PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, + PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, NodeEx out, FlowState sout, AccessPath apout ) { subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and @@ -3407,14 +3420,14 @@ private module Subpaths { } pragma[nomagic] - private Configuration getPathNodeConf(PathNode n) { result = n.getConfiguration() } + private Configuration getPathNodeConf(PathNodeImpl n) { result = n.getConfiguration() } /** * Holds if `(arg, par, ret, out)` forms a subpath-tuple. */ pragma[nomagic] private predicate subpaths03( - PathNode arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout + PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout ) { exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode | subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and @@ -3444,7 +3457,7 @@ private module Subpaths { * a subpath between `par` and `ret` with the connecting edges `arg -> par` and * `ret -> out` is summarized as the edge `arg -> out`. */ - predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) { + predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) { exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 | pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and @@ -3460,7 +3473,7 @@ private module Subpaths { * Holds if `n` can reach a return node in a summarized subpath that can reach a sink. */ predicate retReach(PathNodeImpl n) { - exists(PathNode out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) + exists(PathNodeImpl out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) or exists(PathNodeImpl mid | retReach(mid) and @@ -3477,11 +3490,12 @@ private module Subpaths { * sinks. */ private predicate flowsTo( - PathNode flowsource, PathNodeSink flowsink, Node source, Node sink, Configuration configuration + PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink, + Configuration configuration ) { flowsource.isSource() and flowsource.getConfiguration() = configuration and - flowsource.(PathNodeImpl).getNodeEx().asNode() = source and + flowsource.getNodeEx().asNode() = source and (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and flowsink.getNodeEx().asNode() = sink } @@ -3504,14 +3518,14 @@ private predicate finalStats( fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and - tuples = count(PathNode pn) + tuples = count(PathNodeImpl pn) or fwd = false and nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and - tuples = count(PathNode pn | reach(pn)) + tuples = count(PathNode pn) } /** diff --git a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplForContentDataFlow.qll b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplForContentDataFlow.qll index b5631b26b0bf..8cd1071d084a 100644 --- a/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplForContentDataFlow.qll +++ b/csharp/ql/lib/semmle/code/csharp/dataflow/internal/DataFlowImplForContentDataFlow.qll @@ -2874,54 +2874,16 @@ private class AccessPathCons1 extends AccessPath, TAccessPathCons1 { } } -/** - * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. - * Only those `PathNode`s that are reachable from a source are generated. - */ -class PathNode extends TPathNode { - /** Gets a textual representation of this element. */ - string toString() { none() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - string toStringWithContext() { none() } - - /** - * 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/). - */ - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - none() - } - - /** Gets the underlying `Node`. */ - final Node getNode() { this.(PathNodeImpl).getNodeEx().projectToNode() = result } - +abstract private class PathNodeImpl extends TPathNode { /** Gets the `FlowState` of this node. */ - FlowState getState() { none() } + abstract FlowState getState(); /** Gets the associated configuration. */ - Configuration getConfiguration() { none() } - - /** Gets a successor of this node, if any. */ - final PathNode getASuccessor() { - result = this.(PathNodeImpl).getANonHiddenSuccessor() and - reach(this) and - reach(result) - } + abstract Configuration getConfiguration(); /** Holds if this node is a source. */ - predicate isSource() { none() } -} + abstract predicate isSource(); -abstract private class PathNodeImpl extends PathNode { abstract PathNodeImpl getASuccessorImpl(); private PathNodeImpl getASuccessorIfHidden() { @@ -2967,13 +2929,23 @@ abstract private class PathNodeImpl extends PathNode { result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" } - override string toString() { result = this.getNodeEx().toString() + this.ppAp() } + /** Gets a textual representation of this element. */ + string toString() { result = this.getNodeEx().toString() + this.ppAp() } - override string toStringWithContext() { - result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() - } + /** + * Gets a textual representation of this element, including a textual + * representation of the call context. + */ + string toStringWithContext() { result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() } - override predicate hasLocationInfo( + /** + * 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/). + */ + predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn ) { this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) @@ -2986,14 +2958,59 @@ private predicate directReach(PathNodeImpl n) { } /** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */ -private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) } +private predicate reach(PathNodeImpl n) { directReach(n) or Subpaths::retReach(n) } /** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */ -private predicate pathSucc(PathNodeImpl n1, PathNode n2) { +private predicate pathSucc(PathNodeImpl n1, PathNodeImpl n2) { n1.getANonHiddenSuccessor() = n2 and directReach(n2) } -private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2) +private predicate pathSuccPlus(PathNodeImpl n1, PathNodeImpl n2) = fastTC(pathSucc/2)(n1, n2) + +/** + * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. + * Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated. + */ +class PathNode instanceof PathNodeImpl { + PathNode() { reach(this) } + + /** Gets a textual representation of this element. */ + final string toString() { result = super.toString() } + + /** + * Gets a textual representation of this element, including a textual + * representation of the call context. + */ + final string toStringWithContext() { result = super.toStringWithContext() } + + /** + * 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/). + */ + final predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } + + /** Gets the underlying `Node`. */ + final Node getNode() { super.getNodeEx().projectToNode() = result } + + /** Gets the `FlowState` of this node. */ + final FlowState getState() { result = super.getState() } + + /** Gets the associated configuration. */ + final Configuration getConfiguration() { result = super.getConfiguration() } + + /** Gets a successor of this node, if any. */ + final PathNode getASuccessor() { result = super.getANonHiddenSuccessor() } + + /** Holds if this node is a source. */ + final predicate isSource() { super.isSource() } +} /** * Provides the query predicates needed to include a graph in a path-problem query. @@ -3004,7 +3021,7 @@ module PathGraph { /** Holds if `n` is a node in the graph of data flow path explanations. */ query predicate nodes(PathNode n, string key, string val) { - reach(n) and key = "semmle.label" and val = n.toString() + key = "semmle.label" and val = n.toString() } /** @@ -3013,11 +3030,7 @@ module PathGraph { * `ret -> out` is summarized as the edge `arg -> out`. */ query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) { - Subpaths::subpaths(arg, par, ret, out) and - reach(arg) and - reach(par) and - reach(ret) and - reach(out) + Subpaths::subpaths(arg, par, ret, out) } } @@ -3399,7 +3412,7 @@ private module Subpaths { */ pragma[nomagic] private predicate subpaths02( - PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, + PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, NodeEx out, FlowState sout, AccessPath apout ) { subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and @@ -3407,14 +3420,14 @@ private module Subpaths { } pragma[nomagic] - private Configuration getPathNodeConf(PathNode n) { result = n.getConfiguration() } + private Configuration getPathNodeConf(PathNodeImpl n) { result = n.getConfiguration() } /** * Holds if `(arg, par, ret, out)` forms a subpath-tuple. */ pragma[nomagic] private predicate subpaths03( - PathNode arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout + PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout ) { exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode | subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and @@ -3444,7 +3457,7 @@ private module Subpaths { * a subpath between `par` and `ret` with the connecting edges `arg -> par` and * `ret -> out` is summarized as the edge `arg -> out`. */ - predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) { + predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) { exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 | pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and @@ -3460,7 +3473,7 @@ private module Subpaths { * Holds if `n` can reach a return node in a summarized subpath that can reach a sink. */ predicate retReach(PathNodeImpl n) { - exists(PathNode out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) + exists(PathNodeImpl out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) or exists(PathNodeImpl mid | retReach(mid) and @@ -3477,11 +3490,12 @@ private module Subpaths { * sinks. */ private predicate flowsTo( - PathNode flowsource, PathNodeSink flowsink, Node source, Node sink, Configuration configuration + PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink, + Configuration configuration ) { flowsource.isSource() and flowsource.getConfiguration() = configuration and - flowsource.(PathNodeImpl).getNodeEx().asNode() = source and + flowsource.getNodeEx().asNode() = source and (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and flowsink.getNodeEx().asNode() = sink } @@ -3504,14 +3518,14 @@ private predicate finalStats( fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and - tuples = count(PathNode pn) + tuples = count(PathNodeImpl pn) or fwd = false and nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and - tuples = count(PathNode pn | reach(pn)) + tuples = count(PathNode pn) } /** diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll index b5631b26b0bf..8cd1071d084a 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl.qll @@ -2874,54 +2874,16 @@ private class AccessPathCons1 extends AccessPath, TAccessPathCons1 { } } -/** - * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. - * Only those `PathNode`s that are reachable from a source are generated. - */ -class PathNode extends TPathNode { - /** Gets a textual representation of this element. */ - string toString() { none() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - string toStringWithContext() { none() } - - /** - * 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/). - */ - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - none() - } - - /** Gets the underlying `Node`. */ - final Node getNode() { this.(PathNodeImpl).getNodeEx().projectToNode() = result } - +abstract private class PathNodeImpl extends TPathNode { /** Gets the `FlowState` of this node. */ - FlowState getState() { none() } + abstract FlowState getState(); /** Gets the associated configuration. */ - Configuration getConfiguration() { none() } - - /** Gets a successor of this node, if any. */ - final PathNode getASuccessor() { - result = this.(PathNodeImpl).getANonHiddenSuccessor() and - reach(this) and - reach(result) - } + abstract Configuration getConfiguration(); /** Holds if this node is a source. */ - predicate isSource() { none() } -} + abstract predicate isSource(); -abstract private class PathNodeImpl extends PathNode { abstract PathNodeImpl getASuccessorImpl(); private PathNodeImpl getASuccessorIfHidden() { @@ -2967,13 +2929,23 @@ abstract private class PathNodeImpl extends PathNode { result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" } - override string toString() { result = this.getNodeEx().toString() + this.ppAp() } + /** Gets a textual representation of this element. */ + string toString() { result = this.getNodeEx().toString() + this.ppAp() } - override string toStringWithContext() { - result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() - } + /** + * Gets a textual representation of this element, including a textual + * representation of the call context. + */ + string toStringWithContext() { result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() } - override predicate hasLocationInfo( + /** + * 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/). + */ + predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn ) { this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) @@ -2986,14 +2958,59 @@ private predicate directReach(PathNodeImpl n) { } /** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */ -private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) } +private predicate reach(PathNodeImpl n) { directReach(n) or Subpaths::retReach(n) } /** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */ -private predicate pathSucc(PathNodeImpl n1, PathNode n2) { +private predicate pathSucc(PathNodeImpl n1, PathNodeImpl n2) { n1.getANonHiddenSuccessor() = n2 and directReach(n2) } -private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2) +private predicate pathSuccPlus(PathNodeImpl n1, PathNodeImpl n2) = fastTC(pathSucc/2)(n1, n2) + +/** + * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. + * Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated. + */ +class PathNode instanceof PathNodeImpl { + PathNode() { reach(this) } + + /** Gets a textual representation of this element. */ + final string toString() { result = super.toString() } + + /** + * Gets a textual representation of this element, including a textual + * representation of the call context. + */ + final string toStringWithContext() { result = super.toStringWithContext() } + + /** + * 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/). + */ + final predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } + + /** Gets the underlying `Node`. */ + final Node getNode() { super.getNodeEx().projectToNode() = result } + + /** Gets the `FlowState` of this node. */ + final FlowState getState() { result = super.getState() } + + /** Gets the associated configuration. */ + final Configuration getConfiguration() { result = super.getConfiguration() } + + /** Gets a successor of this node, if any. */ + final PathNode getASuccessor() { result = super.getANonHiddenSuccessor() } + + /** Holds if this node is a source. */ + final predicate isSource() { super.isSource() } +} /** * Provides the query predicates needed to include a graph in a path-problem query. @@ -3004,7 +3021,7 @@ module PathGraph { /** Holds if `n` is a node in the graph of data flow path explanations. */ query predicate nodes(PathNode n, string key, string val) { - reach(n) and key = "semmle.label" and val = n.toString() + key = "semmle.label" and val = n.toString() } /** @@ -3013,11 +3030,7 @@ module PathGraph { * `ret -> out` is summarized as the edge `arg -> out`. */ query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) { - Subpaths::subpaths(arg, par, ret, out) and - reach(arg) and - reach(par) and - reach(ret) and - reach(out) + Subpaths::subpaths(arg, par, ret, out) } } @@ -3399,7 +3412,7 @@ private module Subpaths { */ pragma[nomagic] private predicate subpaths02( - PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, + PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, NodeEx out, FlowState sout, AccessPath apout ) { subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and @@ -3407,14 +3420,14 @@ private module Subpaths { } pragma[nomagic] - private Configuration getPathNodeConf(PathNode n) { result = n.getConfiguration() } + private Configuration getPathNodeConf(PathNodeImpl n) { result = n.getConfiguration() } /** * Holds if `(arg, par, ret, out)` forms a subpath-tuple. */ pragma[nomagic] private predicate subpaths03( - PathNode arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout + PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout ) { exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode | subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and @@ -3444,7 +3457,7 @@ private module Subpaths { * a subpath between `par` and `ret` with the connecting edges `arg -> par` and * `ret -> out` is summarized as the edge `arg -> out`. */ - predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) { + predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) { exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 | pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and @@ -3460,7 +3473,7 @@ private module Subpaths { * Holds if `n` can reach a return node in a summarized subpath that can reach a sink. */ predicate retReach(PathNodeImpl n) { - exists(PathNode out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) + exists(PathNodeImpl out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) or exists(PathNodeImpl mid | retReach(mid) and @@ -3477,11 +3490,12 @@ private module Subpaths { * sinks. */ private predicate flowsTo( - PathNode flowsource, PathNodeSink flowsink, Node source, Node sink, Configuration configuration + PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink, + Configuration configuration ) { flowsource.isSource() and flowsource.getConfiguration() = configuration and - flowsource.(PathNodeImpl).getNodeEx().asNode() = source and + flowsource.getNodeEx().asNode() = source and (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and flowsink.getNodeEx().asNode() = sink } @@ -3504,14 +3518,14 @@ private predicate finalStats( fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and - tuples = count(PathNode pn) + tuples = count(PathNodeImpl pn) or fwd = false and nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and - tuples = count(PathNode pn | reach(pn)) + tuples = count(PathNode pn) } /** diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl2.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl2.qll index b5631b26b0bf..8cd1071d084a 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl2.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl2.qll @@ -2874,54 +2874,16 @@ private class AccessPathCons1 extends AccessPath, TAccessPathCons1 { } } -/** - * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. - * Only those `PathNode`s that are reachable from a source are generated. - */ -class PathNode extends TPathNode { - /** Gets a textual representation of this element. */ - string toString() { none() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - string toStringWithContext() { none() } - - /** - * 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/). - */ - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - none() - } - - /** Gets the underlying `Node`. */ - final Node getNode() { this.(PathNodeImpl).getNodeEx().projectToNode() = result } - +abstract private class PathNodeImpl extends TPathNode { /** Gets the `FlowState` of this node. */ - FlowState getState() { none() } + abstract FlowState getState(); /** Gets the associated configuration. */ - Configuration getConfiguration() { none() } - - /** Gets a successor of this node, if any. */ - final PathNode getASuccessor() { - result = this.(PathNodeImpl).getANonHiddenSuccessor() and - reach(this) and - reach(result) - } + abstract Configuration getConfiguration(); /** Holds if this node is a source. */ - predicate isSource() { none() } -} + abstract predicate isSource(); -abstract private class PathNodeImpl extends PathNode { abstract PathNodeImpl getASuccessorImpl(); private PathNodeImpl getASuccessorIfHidden() { @@ -2967,13 +2929,23 @@ abstract private class PathNodeImpl extends PathNode { result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" } - override string toString() { result = this.getNodeEx().toString() + this.ppAp() } + /** Gets a textual representation of this element. */ + string toString() { result = this.getNodeEx().toString() + this.ppAp() } - override string toStringWithContext() { - result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() - } + /** + * Gets a textual representation of this element, including a textual + * representation of the call context. + */ + string toStringWithContext() { result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() } - override predicate hasLocationInfo( + /** + * 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/). + */ + predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn ) { this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) @@ -2986,14 +2958,59 @@ private predicate directReach(PathNodeImpl n) { } /** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */ -private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) } +private predicate reach(PathNodeImpl n) { directReach(n) or Subpaths::retReach(n) } /** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */ -private predicate pathSucc(PathNodeImpl n1, PathNode n2) { +private predicate pathSucc(PathNodeImpl n1, PathNodeImpl n2) { n1.getANonHiddenSuccessor() = n2 and directReach(n2) } -private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2) +private predicate pathSuccPlus(PathNodeImpl n1, PathNodeImpl n2) = fastTC(pathSucc/2)(n1, n2) + +/** + * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. + * Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated. + */ +class PathNode instanceof PathNodeImpl { + PathNode() { reach(this) } + + /** Gets a textual representation of this element. */ + final string toString() { result = super.toString() } + + /** + * Gets a textual representation of this element, including a textual + * representation of the call context. + */ + final string toStringWithContext() { result = super.toStringWithContext() } + + /** + * 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/). + */ + final predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } + + /** Gets the underlying `Node`. */ + final Node getNode() { super.getNodeEx().projectToNode() = result } + + /** Gets the `FlowState` of this node. */ + final FlowState getState() { result = super.getState() } + + /** Gets the associated configuration. */ + final Configuration getConfiguration() { result = super.getConfiguration() } + + /** Gets a successor of this node, if any. */ + final PathNode getASuccessor() { result = super.getANonHiddenSuccessor() } + + /** Holds if this node is a source. */ + final predicate isSource() { super.isSource() } +} /** * Provides the query predicates needed to include a graph in a path-problem query. @@ -3004,7 +3021,7 @@ module PathGraph { /** Holds if `n` is a node in the graph of data flow path explanations. */ query predicate nodes(PathNode n, string key, string val) { - reach(n) and key = "semmle.label" and val = n.toString() + key = "semmle.label" and val = n.toString() } /** @@ -3013,11 +3030,7 @@ module PathGraph { * `ret -> out` is summarized as the edge `arg -> out`. */ query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) { - Subpaths::subpaths(arg, par, ret, out) and - reach(arg) and - reach(par) and - reach(ret) and - reach(out) + Subpaths::subpaths(arg, par, ret, out) } } @@ -3399,7 +3412,7 @@ private module Subpaths { */ pragma[nomagic] private predicate subpaths02( - PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, + PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, NodeEx out, FlowState sout, AccessPath apout ) { subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and @@ -3407,14 +3420,14 @@ private module Subpaths { } pragma[nomagic] - private Configuration getPathNodeConf(PathNode n) { result = n.getConfiguration() } + private Configuration getPathNodeConf(PathNodeImpl n) { result = n.getConfiguration() } /** * Holds if `(arg, par, ret, out)` forms a subpath-tuple. */ pragma[nomagic] private predicate subpaths03( - PathNode arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout + PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout ) { exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode | subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and @@ -3444,7 +3457,7 @@ private module Subpaths { * a subpath between `par` and `ret` with the connecting edges `arg -> par` and * `ret -> out` is summarized as the edge `arg -> out`. */ - predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) { + predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) { exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 | pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and @@ -3460,7 +3473,7 @@ private module Subpaths { * Holds if `n` can reach a return node in a summarized subpath that can reach a sink. */ predicate retReach(PathNodeImpl n) { - exists(PathNode out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) + exists(PathNodeImpl out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) or exists(PathNodeImpl mid | retReach(mid) and @@ -3477,11 +3490,12 @@ private module Subpaths { * sinks. */ private predicate flowsTo( - PathNode flowsource, PathNodeSink flowsink, Node source, Node sink, Configuration configuration + PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink, + Configuration configuration ) { flowsource.isSource() and flowsource.getConfiguration() = configuration and - flowsource.(PathNodeImpl).getNodeEx().asNode() = source and + flowsource.getNodeEx().asNode() = source and (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and flowsink.getNodeEx().asNode() = sink } @@ -3504,14 +3518,14 @@ private predicate finalStats( fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and - tuples = count(PathNode pn) + tuples = count(PathNodeImpl pn) or fwd = false and nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and - tuples = count(PathNode pn | reach(pn)) + tuples = count(PathNode pn) } /** diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl3.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl3.qll index b5631b26b0bf..8cd1071d084a 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl3.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl3.qll @@ -2874,54 +2874,16 @@ private class AccessPathCons1 extends AccessPath, TAccessPathCons1 { } } -/** - * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. - * Only those `PathNode`s that are reachable from a source are generated. - */ -class PathNode extends TPathNode { - /** Gets a textual representation of this element. */ - string toString() { none() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - string toStringWithContext() { none() } - - /** - * 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/). - */ - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - none() - } - - /** Gets the underlying `Node`. */ - final Node getNode() { this.(PathNodeImpl).getNodeEx().projectToNode() = result } - +abstract private class PathNodeImpl extends TPathNode { /** Gets the `FlowState` of this node. */ - FlowState getState() { none() } + abstract FlowState getState(); /** Gets the associated configuration. */ - Configuration getConfiguration() { none() } - - /** Gets a successor of this node, if any. */ - final PathNode getASuccessor() { - result = this.(PathNodeImpl).getANonHiddenSuccessor() and - reach(this) and - reach(result) - } + abstract Configuration getConfiguration(); /** Holds if this node is a source. */ - predicate isSource() { none() } -} + abstract predicate isSource(); -abstract private class PathNodeImpl extends PathNode { abstract PathNodeImpl getASuccessorImpl(); private PathNodeImpl getASuccessorIfHidden() { @@ -2967,13 +2929,23 @@ abstract private class PathNodeImpl extends PathNode { result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" } - override string toString() { result = this.getNodeEx().toString() + this.ppAp() } + /** Gets a textual representation of this element. */ + string toString() { result = this.getNodeEx().toString() + this.ppAp() } - override string toStringWithContext() { - result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() - } + /** + * Gets a textual representation of this element, including a textual + * representation of the call context. + */ + string toStringWithContext() { result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() } - override predicate hasLocationInfo( + /** + * 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/). + */ + predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn ) { this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) @@ -2986,14 +2958,59 @@ private predicate directReach(PathNodeImpl n) { } /** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */ -private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) } +private predicate reach(PathNodeImpl n) { directReach(n) or Subpaths::retReach(n) } /** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */ -private predicate pathSucc(PathNodeImpl n1, PathNode n2) { +private predicate pathSucc(PathNodeImpl n1, PathNodeImpl n2) { n1.getANonHiddenSuccessor() = n2 and directReach(n2) } -private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2) +private predicate pathSuccPlus(PathNodeImpl n1, PathNodeImpl n2) = fastTC(pathSucc/2)(n1, n2) + +/** + * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. + * Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated. + */ +class PathNode instanceof PathNodeImpl { + PathNode() { reach(this) } + + /** Gets a textual representation of this element. */ + final string toString() { result = super.toString() } + + /** + * Gets a textual representation of this element, including a textual + * representation of the call context. + */ + final string toStringWithContext() { result = super.toStringWithContext() } + + /** + * 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/). + */ + final predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } + + /** Gets the underlying `Node`. */ + final Node getNode() { super.getNodeEx().projectToNode() = result } + + /** Gets the `FlowState` of this node. */ + final FlowState getState() { result = super.getState() } + + /** Gets the associated configuration. */ + final Configuration getConfiguration() { result = super.getConfiguration() } + + /** Gets a successor of this node, if any. */ + final PathNode getASuccessor() { result = super.getANonHiddenSuccessor() } + + /** Holds if this node is a source. */ + final predicate isSource() { super.isSource() } +} /** * Provides the query predicates needed to include a graph in a path-problem query. @@ -3004,7 +3021,7 @@ module PathGraph { /** Holds if `n` is a node in the graph of data flow path explanations. */ query predicate nodes(PathNode n, string key, string val) { - reach(n) and key = "semmle.label" and val = n.toString() + key = "semmle.label" and val = n.toString() } /** @@ -3013,11 +3030,7 @@ module PathGraph { * `ret -> out` is summarized as the edge `arg -> out`. */ query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) { - Subpaths::subpaths(arg, par, ret, out) and - reach(arg) and - reach(par) and - reach(ret) and - reach(out) + Subpaths::subpaths(arg, par, ret, out) } } @@ -3399,7 +3412,7 @@ private module Subpaths { */ pragma[nomagic] private predicate subpaths02( - PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, + PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, NodeEx out, FlowState sout, AccessPath apout ) { subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and @@ -3407,14 +3420,14 @@ private module Subpaths { } pragma[nomagic] - private Configuration getPathNodeConf(PathNode n) { result = n.getConfiguration() } + private Configuration getPathNodeConf(PathNodeImpl n) { result = n.getConfiguration() } /** * Holds if `(arg, par, ret, out)` forms a subpath-tuple. */ pragma[nomagic] private predicate subpaths03( - PathNode arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout + PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout ) { exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode | subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and @@ -3444,7 +3457,7 @@ private module Subpaths { * a subpath between `par` and `ret` with the connecting edges `arg -> par` and * `ret -> out` is summarized as the edge `arg -> out`. */ - predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) { + predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) { exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 | pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and @@ -3460,7 +3473,7 @@ private module Subpaths { * Holds if `n` can reach a return node in a summarized subpath that can reach a sink. */ predicate retReach(PathNodeImpl n) { - exists(PathNode out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) + exists(PathNodeImpl out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) or exists(PathNodeImpl mid | retReach(mid) and @@ -3477,11 +3490,12 @@ private module Subpaths { * sinks. */ private predicate flowsTo( - PathNode flowsource, PathNodeSink flowsink, Node source, Node sink, Configuration configuration + PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink, + Configuration configuration ) { flowsource.isSource() and flowsource.getConfiguration() = configuration and - flowsource.(PathNodeImpl).getNodeEx().asNode() = source and + flowsource.getNodeEx().asNode() = source and (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and flowsink.getNodeEx().asNode() = sink } @@ -3504,14 +3518,14 @@ private predicate finalStats( fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and - tuples = count(PathNode pn) + tuples = count(PathNodeImpl pn) or fwd = false and nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and - tuples = count(PathNode pn | reach(pn)) + tuples = count(PathNode pn) } /** diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl4.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl4.qll index b5631b26b0bf..8cd1071d084a 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl4.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl4.qll @@ -2874,54 +2874,16 @@ private class AccessPathCons1 extends AccessPath, TAccessPathCons1 { } } -/** - * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. - * Only those `PathNode`s that are reachable from a source are generated. - */ -class PathNode extends TPathNode { - /** Gets a textual representation of this element. */ - string toString() { none() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - string toStringWithContext() { none() } - - /** - * 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/). - */ - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - none() - } - - /** Gets the underlying `Node`. */ - final Node getNode() { this.(PathNodeImpl).getNodeEx().projectToNode() = result } - +abstract private class PathNodeImpl extends TPathNode { /** Gets the `FlowState` of this node. */ - FlowState getState() { none() } + abstract FlowState getState(); /** Gets the associated configuration. */ - Configuration getConfiguration() { none() } - - /** Gets a successor of this node, if any. */ - final PathNode getASuccessor() { - result = this.(PathNodeImpl).getANonHiddenSuccessor() and - reach(this) and - reach(result) - } + abstract Configuration getConfiguration(); /** Holds if this node is a source. */ - predicate isSource() { none() } -} + abstract predicate isSource(); -abstract private class PathNodeImpl extends PathNode { abstract PathNodeImpl getASuccessorImpl(); private PathNodeImpl getASuccessorIfHidden() { @@ -2967,13 +2929,23 @@ abstract private class PathNodeImpl extends PathNode { result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" } - override string toString() { result = this.getNodeEx().toString() + this.ppAp() } + /** Gets a textual representation of this element. */ + string toString() { result = this.getNodeEx().toString() + this.ppAp() } - override string toStringWithContext() { - result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() - } + /** + * Gets a textual representation of this element, including a textual + * representation of the call context. + */ + string toStringWithContext() { result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() } - override predicate hasLocationInfo( + /** + * 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/). + */ + predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn ) { this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) @@ -2986,14 +2958,59 @@ private predicate directReach(PathNodeImpl n) { } /** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */ -private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) } +private predicate reach(PathNodeImpl n) { directReach(n) or Subpaths::retReach(n) } /** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */ -private predicate pathSucc(PathNodeImpl n1, PathNode n2) { +private predicate pathSucc(PathNodeImpl n1, PathNodeImpl n2) { n1.getANonHiddenSuccessor() = n2 and directReach(n2) } -private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2) +private predicate pathSuccPlus(PathNodeImpl n1, PathNodeImpl n2) = fastTC(pathSucc/2)(n1, n2) + +/** + * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. + * Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated. + */ +class PathNode instanceof PathNodeImpl { + PathNode() { reach(this) } + + /** Gets a textual representation of this element. */ + final string toString() { result = super.toString() } + + /** + * Gets a textual representation of this element, including a textual + * representation of the call context. + */ + final string toStringWithContext() { result = super.toStringWithContext() } + + /** + * 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/). + */ + final predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } + + /** Gets the underlying `Node`. */ + final Node getNode() { super.getNodeEx().projectToNode() = result } + + /** Gets the `FlowState` of this node. */ + final FlowState getState() { result = super.getState() } + + /** Gets the associated configuration. */ + final Configuration getConfiguration() { result = super.getConfiguration() } + + /** Gets a successor of this node, if any. */ + final PathNode getASuccessor() { result = super.getANonHiddenSuccessor() } + + /** Holds if this node is a source. */ + final predicate isSource() { super.isSource() } +} /** * Provides the query predicates needed to include a graph in a path-problem query. @@ -3004,7 +3021,7 @@ module PathGraph { /** Holds if `n` is a node in the graph of data flow path explanations. */ query predicate nodes(PathNode n, string key, string val) { - reach(n) and key = "semmle.label" and val = n.toString() + key = "semmle.label" and val = n.toString() } /** @@ -3013,11 +3030,7 @@ module PathGraph { * `ret -> out` is summarized as the edge `arg -> out`. */ query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) { - Subpaths::subpaths(arg, par, ret, out) and - reach(arg) and - reach(par) and - reach(ret) and - reach(out) + Subpaths::subpaths(arg, par, ret, out) } } @@ -3399,7 +3412,7 @@ private module Subpaths { */ pragma[nomagic] private predicate subpaths02( - PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, + PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, NodeEx out, FlowState sout, AccessPath apout ) { subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and @@ -3407,14 +3420,14 @@ private module Subpaths { } pragma[nomagic] - private Configuration getPathNodeConf(PathNode n) { result = n.getConfiguration() } + private Configuration getPathNodeConf(PathNodeImpl n) { result = n.getConfiguration() } /** * Holds if `(arg, par, ret, out)` forms a subpath-tuple. */ pragma[nomagic] private predicate subpaths03( - PathNode arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout + PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout ) { exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode | subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and @@ -3444,7 +3457,7 @@ private module Subpaths { * a subpath between `par` and `ret` with the connecting edges `arg -> par` and * `ret -> out` is summarized as the edge `arg -> out`. */ - predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) { + predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) { exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 | pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and @@ -3460,7 +3473,7 @@ private module Subpaths { * Holds if `n` can reach a return node in a summarized subpath that can reach a sink. */ predicate retReach(PathNodeImpl n) { - exists(PathNode out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) + exists(PathNodeImpl out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) or exists(PathNodeImpl mid | retReach(mid) and @@ -3477,11 +3490,12 @@ private module Subpaths { * sinks. */ private predicate flowsTo( - PathNode flowsource, PathNodeSink flowsink, Node source, Node sink, Configuration configuration + PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink, + Configuration configuration ) { flowsource.isSource() and flowsource.getConfiguration() = configuration and - flowsource.(PathNodeImpl).getNodeEx().asNode() = source and + flowsource.getNodeEx().asNode() = source and (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and flowsink.getNodeEx().asNode() = sink } @@ -3504,14 +3518,14 @@ private predicate finalStats( fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and - tuples = count(PathNode pn) + tuples = count(PathNodeImpl pn) or fwd = false and nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and - tuples = count(PathNode pn | reach(pn)) + tuples = count(PathNode pn) } /** diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl5.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl5.qll index b5631b26b0bf..8cd1071d084a 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl5.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl5.qll @@ -2874,54 +2874,16 @@ private class AccessPathCons1 extends AccessPath, TAccessPathCons1 { } } -/** - * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. - * Only those `PathNode`s that are reachable from a source are generated. - */ -class PathNode extends TPathNode { - /** Gets a textual representation of this element. */ - string toString() { none() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - string toStringWithContext() { none() } - - /** - * 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/). - */ - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - none() - } - - /** Gets the underlying `Node`. */ - final Node getNode() { this.(PathNodeImpl).getNodeEx().projectToNode() = result } - +abstract private class PathNodeImpl extends TPathNode { /** Gets the `FlowState` of this node. */ - FlowState getState() { none() } + abstract FlowState getState(); /** Gets the associated configuration. */ - Configuration getConfiguration() { none() } - - /** Gets a successor of this node, if any. */ - final PathNode getASuccessor() { - result = this.(PathNodeImpl).getANonHiddenSuccessor() and - reach(this) and - reach(result) - } + abstract Configuration getConfiguration(); /** Holds if this node is a source. */ - predicate isSource() { none() } -} + abstract predicate isSource(); -abstract private class PathNodeImpl extends PathNode { abstract PathNodeImpl getASuccessorImpl(); private PathNodeImpl getASuccessorIfHidden() { @@ -2967,13 +2929,23 @@ abstract private class PathNodeImpl extends PathNode { result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" } - override string toString() { result = this.getNodeEx().toString() + this.ppAp() } + /** Gets a textual representation of this element. */ + string toString() { result = this.getNodeEx().toString() + this.ppAp() } - override string toStringWithContext() { - result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() - } + /** + * Gets a textual representation of this element, including a textual + * representation of the call context. + */ + string toStringWithContext() { result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() } - override predicate hasLocationInfo( + /** + * 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/). + */ + predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn ) { this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) @@ -2986,14 +2958,59 @@ private predicate directReach(PathNodeImpl n) { } /** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */ -private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) } +private predicate reach(PathNodeImpl n) { directReach(n) or Subpaths::retReach(n) } /** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */ -private predicate pathSucc(PathNodeImpl n1, PathNode n2) { +private predicate pathSucc(PathNodeImpl n1, PathNodeImpl n2) { n1.getANonHiddenSuccessor() = n2 and directReach(n2) } -private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2) +private predicate pathSuccPlus(PathNodeImpl n1, PathNodeImpl n2) = fastTC(pathSucc/2)(n1, n2) + +/** + * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. + * Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated. + */ +class PathNode instanceof PathNodeImpl { + PathNode() { reach(this) } + + /** Gets a textual representation of this element. */ + final string toString() { result = super.toString() } + + /** + * Gets a textual representation of this element, including a textual + * representation of the call context. + */ + final string toStringWithContext() { result = super.toStringWithContext() } + + /** + * 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/). + */ + final predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } + + /** Gets the underlying `Node`. */ + final Node getNode() { super.getNodeEx().projectToNode() = result } + + /** Gets the `FlowState` of this node. */ + final FlowState getState() { result = super.getState() } + + /** Gets the associated configuration. */ + final Configuration getConfiguration() { result = super.getConfiguration() } + + /** Gets a successor of this node, if any. */ + final PathNode getASuccessor() { result = super.getANonHiddenSuccessor() } + + /** Holds if this node is a source. */ + final predicate isSource() { super.isSource() } +} /** * Provides the query predicates needed to include a graph in a path-problem query. @@ -3004,7 +3021,7 @@ module PathGraph { /** Holds if `n` is a node in the graph of data flow path explanations. */ query predicate nodes(PathNode n, string key, string val) { - reach(n) and key = "semmle.label" and val = n.toString() + key = "semmle.label" and val = n.toString() } /** @@ -3013,11 +3030,7 @@ module PathGraph { * `ret -> out` is summarized as the edge `arg -> out`. */ query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) { - Subpaths::subpaths(arg, par, ret, out) and - reach(arg) and - reach(par) and - reach(ret) and - reach(out) + Subpaths::subpaths(arg, par, ret, out) } } @@ -3399,7 +3412,7 @@ private module Subpaths { */ pragma[nomagic] private predicate subpaths02( - PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, + PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, NodeEx out, FlowState sout, AccessPath apout ) { subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and @@ -3407,14 +3420,14 @@ private module Subpaths { } pragma[nomagic] - private Configuration getPathNodeConf(PathNode n) { result = n.getConfiguration() } + private Configuration getPathNodeConf(PathNodeImpl n) { result = n.getConfiguration() } /** * Holds if `(arg, par, ret, out)` forms a subpath-tuple. */ pragma[nomagic] private predicate subpaths03( - PathNode arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout + PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout ) { exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode | subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and @@ -3444,7 +3457,7 @@ private module Subpaths { * a subpath between `par` and `ret` with the connecting edges `arg -> par` and * `ret -> out` is summarized as the edge `arg -> out`. */ - predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) { + predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) { exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 | pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and @@ -3460,7 +3473,7 @@ private module Subpaths { * Holds if `n` can reach a return node in a summarized subpath that can reach a sink. */ predicate retReach(PathNodeImpl n) { - exists(PathNode out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) + exists(PathNodeImpl out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) or exists(PathNodeImpl mid | retReach(mid) and @@ -3477,11 +3490,12 @@ private module Subpaths { * sinks. */ private predicate flowsTo( - PathNode flowsource, PathNodeSink flowsink, Node source, Node sink, Configuration configuration + PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink, + Configuration configuration ) { flowsource.isSource() and flowsource.getConfiguration() = configuration and - flowsource.(PathNodeImpl).getNodeEx().asNode() = source and + flowsource.getNodeEx().asNode() = source and (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and flowsink.getNodeEx().asNode() = sink } @@ -3504,14 +3518,14 @@ private predicate finalStats( fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and - tuples = count(PathNode pn) + tuples = count(PathNodeImpl pn) or fwd = false and nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and - tuples = count(PathNode pn | reach(pn)) + tuples = count(PathNode pn) } /** diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl6.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl6.qll index b5631b26b0bf..8cd1071d084a 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl6.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImpl6.qll @@ -2874,54 +2874,16 @@ private class AccessPathCons1 extends AccessPath, TAccessPathCons1 { } } -/** - * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. - * Only those `PathNode`s that are reachable from a source are generated. - */ -class PathNode extends TPathNode { - /** Gets a textual representation of this element. */ - string toString() { none() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - string toStringWithContext() { none() } - - /** - * 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/). - */ - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - none() - } - - /** Gets the underlying `Node`. */ - final Node getNode() { this.(PathNodeImpl).getNodeEx().projectToNode() = result } - +abstract private class PathNodeImpl extends TPathNode { /** Gets the `FlowState` of this node. */ - FlowState getState() { none() } + abstract FlowState getState(); /** Gets the associated configuration. */ - Configuration getConfiguration() { none() } - - /** Gets a successor of this node, if any. */ - final PathNode getASuccessor() { - result = this.(PathNodeImpl).getANonHiddenSuccessor() and - reach(this) and - reach(result) - } + abstract Configuration getConfiguration(); /** Holds if this node is a source. */ - predicate isSource() { none() } -} + abstract predicate isSource(); -abstract private class PathNodeImpl extends PathNode { abstract PathNodeImpl getASuccessorImpl(); private PathNodeImpl getASuccessorIfHidden() { @@ -2967,13 +2929,23 @@ abstract private class PathNodeImpl extends PathNode { result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" } - override string toString() { result = this.getNodeEx().toString() + this.ppAp() } + /** Gets a textual representation of this element. */ + string toString() { result = this.getNodeEx().toString() + this.ppAp() } - override string toStringWithContext() { - result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() - } + /** + * Gets a textual representation of this element, including a textual + * representation of the call context. + */ + string toStringWithContext() { result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() } - override predicate hasLocationInfo( + /** + * 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/). + */ + predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn ) { this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) @@ -2986,14 +2958,59 @@ private predicate directReach(PathNodeImpl n) { } /** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */ -private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) } +private predicate reach(PathNodeImpl n) { directReach(n) or Subpaths::retReach(n) } /** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */ -private predicate pathSucc(PathNodeImpl n1, PathNode n2) { +private predicate pathSucc(PathNodeImpl n1, PathNodeImpl n2) { n1.getANonHiddenSuccessor() = n2 and directReach(n2) } -private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2) +private predicate pathSuccPlus(PathNodeImpl n1, PathNodeImpl n2) = fastTC(pathSucc/2)(n1, n2) + +/** + * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. + * Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated. + */ +class PathNode instanceof PathNodeImpl { + PathNode() { reach(this) } + + /** Gets a textual representation of this element. */ + final string toString() { result = super.toString() } + + /** + * Gets a textual representation of this element, including a textual + * representation of the call context. + */ + final string toStringWithContext() { result = super.toStringWithContext() } + + /** + * 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/). + */ + final predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } + + /** Gets the underlying `Node`. */ + final Node getNode() { super.getNodeEx().projectToNode() = result } + + /** Gets the `FlowState` of this node. */ + final FlowState getState() { result = super.getState() } + + /** Gets the associated configuration. */ + final Configuration getConfiguration() { result = super.getConfiguration() } + + /** Gets a successor of this node, if any. */ + final PathNode getASuccessor() { result = super.getANonHiddenSuccessor() } + + /** Holds if this node is a source. */ + final predicate isSource() { super.isSource() } +} /** * Provides the query predicates needed to include a graph in a path-problem query. @@ -3004,7 +3021,7 @@ module PathGraph { /** Holds if `n` is a node in the graph of data flow path explanations. */ query predicate nodes(PathNode n, string key, string val) { - reach(n) and key = "semmle.label" and val = n.toString() + key = "semmle.label" and val = n.toString() } /** @@ -3013,11 +3030,7 @@ module PathGraph { * `ret -> out` is summarized as the edge `arg -> out`. */ query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) { - Subpaths::subpaths(arg, par, ret, out) and - reach(arg) and - reach(par) and - reach(ret) and - reach(out) + Subpaths::subpaths(arg, par, ret, out) } } @@ -3399,7 +3412,7 @@ private module Subpaths { */ pragma[nomagic] private predicate subpaths02( - PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, + PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, NodeEx out, FlowState sout, AccessPath apout ) { subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and @@ -3407,14 +3420,14 @@ private module Subpaths { } pragma[nomagic] - private Configuration getPathNodeConf(PathNode n) { result = n.getConfiguration() } + private Configuration getPathNodeConf(PathNodeImpl n) { result = n.getConfiguration() } /** * Holds if `(arg, par, ret, out)` forms a subpath-tuple. */ pragma[nomagic] private predicate subpaths03( - PathNode arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout + PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout ) { exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode | subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and @@ -3444,7 +3457,7 @@ private module Subpaths { * a subpath between `par` and `ret` with the connecting edges `arg -> par` and * `ret -> out` is summarized as the edge `arg -> out`. */ - predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) { + predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) { exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 | pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and @@ -3460,7 +3473,7 @@ private module Subpaths { * Holds if `n` can reach a return node in a summarized subpath that can reach a sink. */ predicate retReach(PathNodeImpl n) { - exists(PathNode out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) + exists(PathNodeImpl out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) or exists(PathNodeImpl mid | retReach(mid) and @@ -3477,11 +3490,12 @@ private module Subpaths { * sinks. */ private predicate flowsTo( - PathNode flowsource, PathNodeSink flowsink, Node source, Node sink, Configuration configuration + PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink, + Configuration configuration ) { flowsource.isSource() and flowsource.getConfiguration() = configuration and - flowsource.(PathNodeImpl).getNodeEx().asNode() = source and + flowsource.getNodeEx().asNode() = source and (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and flowsink.getNodeEx().asNode() = sink } @@ -3504,14 +3518,14 @@ private predicate finalStats( fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and - tuples = count(PathNode pn) + tuples = count(PathNodeImpl pn) or fwd = false and nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and - tuples = count(PathNode pn | reach(pn)) + tuples = count(PathNode pn) } /** diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplForOnActivityResult.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplForOnActivityResult.qll index b5631b26b0bf..8cd1071d084a 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplForOnActivityResult.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplForOnActivityResult.qll @@ -2874,54 +2874,16 @@ private class AccessPathCons1 extends AccessPath, TAccessPathCons1 { } } -/** - * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. - * Only those `PathNode`s that are reachable from a source are generated. - */ -class PathNode extends TPathNode { - /** Gets a textual representation of this element. */ - string toString() { none() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - string toStringWithContext() { none() } - - /** - * 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/). - */ - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - none() - } - - /** Gets the underlying `Node`. */ - final Node getNode() { this.(PathNodeImpl).getNodeEx().projectToNode() = result } - +abstract private class PathNodeImpl extends TPathNode { /** Gets the `FlowState` of this node. */ - FlowState getState() { none() } + abstract FlowState getState(); /** Gets the associated configuration. */ - Configuration getConfiguration() { none() } - - /** Gets a successor of this node, if any. */ - final PathNode getASuccessor() { - result = this.(PathNodeImpl).getANonHiddenSuccessor() and - reach(this) and - reach(result) - } + abstract Configuration getConfiguration(); /** Holds if this node is a source. */ - predicate isSource() { none() } -} + abstract predicate isSource(); -abstract private class PathNodeImpl extends PathNode { abstract PathNodeImpl getASuccessorImpl(); private PathNodeImpl getASuccessorIfHidden() { @@ -2967,13 +2929,23 @@ abstract private class PathNodeImpl extends PathNode { result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" } - override string toString() { result = this.getNodeEx().toString() + this.ppAp() } + /** Gets a textual representation of this element. */ + string toString() { result = this.getNodeEx().toString() + this.ppAp() } - override string toStringWithContext() { - result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() - } + /** + * Gets a textual representation of this element, including a textual + * representation of the call context. + */ + string toStringWithContext() { result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() } - override predicate hasLocationInfo( + /** + * 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/). + */ + predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn ) { this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) @@ -2986,14 +2958,59 @@ private predicate directReach(PathNodeImpl n) { } /** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */ -private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) } +private predicate reach(PathNodeImpl n) { directReach(n) or Subpaths::retReach(n) } /** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */ -private predicate pathSucc(PathNodeImpl n1, PathNode n2) { +private predicate pathSucc(PathNodeImpl n1, PathNodeImpl n2) { n1.getANonHiddenSuccessor() = n2 and directReach(n2) } -private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2) +private predicate pathSuccPlus(PathNodeImpl n1, PathNodeImpl n2) = fastTC(pathSucc/2)(n1, n2) + +/** + * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. + * Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated. + */ +class PathNode instanceof PathNodeImpl { + PathNode() { reach(this) } + + /** Gets a textual representation of this element. */ + final string toString() { result = super.toString() } + + /** + * Gets a textual representation of this element, including a textual + * representation of the call context. + */ + final string toStringWithContext() { result = super.toStringWithContext() } + + /** + * 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/). + */ + final predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } + + /** Gets the underlying `Node`. */ + final Node getNode() { super.getNodeEx().projectToNode() = result } + + /** Gets the `FlowState` of this node. */ + final FlowState getState() { result = super.getState() } + + /** Gets the associated configuration. */ + final Configuration getConfiguration() { result = super.getConfiguration() } + + /** Gets a successor of this node, if any. */ + final PathNode getASuccessor() { result = super.getANonHiddenSuccessor() } + + /** Holds if this node is a source. */ + final predicate isSource() { super.isSource() } +} /** * Provides the query predicates needed to include a graph in a path-problem query. @@ -3004,7 +3021,7 @@ module PathGraph { /** Holds if `n` is a node in the graph of data flow path explanations. */ query predicate nodes(PathNode n, string key, string val) { - reach(n) and key = "semmle.label" and val = n.toString() + key = "semmle.label" and val = n.toString() } /** @@ -3013,11 +3030,7 @@ module PathGraph { * `ret -> out` is summarized as the edge `arg -> out`. */ query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) { - Subpaths::subpaths(arg, par, ret, out) and - reach(arg) and - reach(par) and - reach(ret) and - reach(out) + Subpaths::subpaths(arg, par, ret, out) } } @@ -3399,7 +3412,7 @@ private module Subpaths { */ pragma[nomagic] private predicate subpaths02( - PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, + PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, NodeEx out, FlowState sout, AccessPath apout ) { subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and @@ -3407,14 +3420,14 @@ private module Subpaths { } pragma[nomagic] - private Configuration getPathNodeConf(PathNode n) { result = n.getConfiguration() } + private Configuration getPathNodeConf(PathNodeImpl n) { result = n.getConfiguration() } /** * Holds if `(arg, par, ret, out)` forms a subpath-tuple. */ pragma[nomagic] private predicate subpaths03( - PathNode arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout + PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout ) { exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode | subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and @@ -3444,7 +3457,7 @@ private module Subpaths { * a subpath between `par` and `ret` with the connecting edges `arg -> par` and * `ret -> out` is summarized as the edge `arg -> out`. */ - predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) { + predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) { exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 | pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and @@ -3460,7 +3473,7 @@ private module Subpaths { * Holds if `n` can reach a return node in a summarized subpath that can reach a sink. */ predicate retReach(PathNodeImpl n) { - exists(PathNode out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) + exists(PathNodeImpl out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) or exists(PathNodeImpl mid | retReach(mid) and @@ -3477,11 +3490,12 @@ private module Subpaths { * sinks. */ private predicate flowsTo( - PathNode flowsource, PathNodeSink flowsink, Node source, Node sink, Configuration configuration + PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink, + Configuration configuration ) { flowsource.isSource() and flowsource.getConfiguration() = configuration and - flowsource.(PathNodeImpl).getNodeEx().asNode() = source and + flowsource.getNodeEx().asNode() = source and (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and flowsink.getNodeEx().asNode() = sink } @@ -3504,14 +3518,14 @@ private predicate finalStats( fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and - tuples = count(PathNode pn) + tuples = count(PathNodeImpl pn) or fwd = false and nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and - tuples = count(PathNode pn | reach(pn)) + tuples = count(PathNode pn) } /** diff --git a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplForSerializability.qll b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplForSerializability.qll index b5631b26b0bf..8cd1071d084a 100644 --- a/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplForSerializability.qll +++ b/java/ql/lib/semmle/code/java/dataflow/internal/DataFlowImplForSerializability.qll @@ -2874,54 +2874,16 @@ private class AccessPathCons1 extends AccessPath, TAccessPathCons1 { } } -/** - * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. - * Only those `PathNode`s that are reachable from a source are generated. - */ -class PathNode extends TPathNode { - /** Gets a textual representation of this element. */ - string toString() { none() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - string toStringWithContext() { none() } - - /** - * 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/). - */ - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - none() - } - - /** Gets the underlying `Node`. */ - final Node getNode() { this.(PathNodeImpl).getNodeEx().projectToNode() = result } - +abstract private class PathNodeImpl extends TPathNode { /** Gets the `FlowState` of this node. */ - FlowState getState() { none() } + abstract FlowState getState(); /** Gets the associated configuration. */ - Configuration getConfiguration() { none() } - - /** Gets a successor of this node, if any. */ - final PathNode getASuccessor() { - result = this.(PathNodeImpl).getANonHiddenSuccessor() and - reach(this) and - reach(result) - } + abstract Configuration getConfiguration(); /** Holds if this node is a source. */ - predicate isSource() { none() } -} + abstract predicate isSource(); -abstract private class PathNodeImpl extends PathNode { abstract PathNodeImpl getASuccessorImpl(); private PathNodeImpl getASuccessorIfHidden() { @@ -2967,13 +2929,23 @@ abstract private class PathNodeImpl extends PathNode { result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" } - override string toString() { result = this.getNodeEx().toString() + this.ppAp() } + /** Gets a textual representation of this element. */ + string toString() { result = this.getNodeEx().toString() + this.ppAp() } - override string toStringWithContext() { - result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() - } + /** + * Gets a textual representation of this element, including a textual + * representation of the call context. + */ + string toStringWithContext() { result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() } - override predicate hasLocationInfo( + /** + * 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/). + */ + predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn ) { this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) @@ -2986,14 +2958,59 @@ private predicate directReach(PathNodeImpl n) { } /** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */ -private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) } +private predicate reach(PathNodeImpl n) { directReach(n) or Subpaths::retReach(n) } /** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */ -private predicate pathSucc(PathNodeImpl n1, PathNode n2) { +private predicate pathSucc(PathNodeImpl n1, PathNodeImpl n2) { n1.getANonHiddenSuccessor() = n2 and directReach(n2) } -private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2) +private predicate pathSuccPlus(PathNodeImpl n1, PathNodeImpl n2) = fastTC(pathSucc/2)(n1, n2) + +/** + * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. + * Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated. + */ +class PathNode instanceof PathNodeImpl { + PathNode() { reach(this) } + + /** Gets a textual representation of this element. */ + final string toString() { result = super.toString() } + + /** + * Gets a textual representation of this element, including a textual + * representation of the call context. + */ + final string toStringWithContext() { result = super.toStringWithContext() } + + /** + * 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/). + */ + final predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } + + /** Gets the underlying `Node`. */ + final Node getNode() { super.getNodeEx().projectToNode() = result } + + /** Gets the `FlowState` of this node. */ + final FlowState getState() { result = super.getState() } + + /** Gets the associated configuration. */ + final Configuration getConfiguration() { result = super.getConfiguration() } + + /** Gets a successor of this node, if any. */ + final PathNode getASuccessor() { result = super.getANonHiddenSuccessor() } + + /** Holds if this node is a source. */ + final predicate isSource() { super.isSource() } +} /** * Provides the query predicates needed to include a graph in a path-problem query. @@ -3004,7 +3021,7 @@ module PathGraph { /** Holds if `n` is a node in the graph of data flow path explanations. */ query predicate nodes(PathNode n, string key, string val) { - reach(n) and key = "semmle.label" and val = n.toString() + key = "semmle.label" and val = n.toString() } /** @@ -3013,11 +3030,7 @@ module PathGraph { * `ret -> out` is summarized as the edge `arg -> out`. */ query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) { - Subpaths::subpaths(arg, par, ret, out) and - reach(arg) and - reach(par) and - reach(ret) and - reach(out) + Subpaths::subpaths(arg, par, ret, out) } } @@ -3399,7 +3412,7 @@ private module Subpaths { */ pragma[nomagic] private predicate subpaths02( - PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, + PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, NodeEx out, FlowState sout, AccessPath apout ) { subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and @@ -3407,14 +3420,14 @@ private module Subpaths { } pragma[nomagic] - private Configuration getPathNodeConf(PathNode n) { result = n.getConfiguration() } + private Configuration getPathNodeConf(PathNodeImpl n) { result = n.getConfiguration() } /** * Holds if `(arg, par, ret, out)` forms a subpath-tuple. */ pragma[nomagic] private predicate subpaths03( - PathNode arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout + PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout ) { exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode | subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and @@ -3444,7 +3457,7 @@ private module Subpaths { * a subpath between `par` and `ret` with the connecting edges `arg -> par` and * `ret -> out` is summarized as the edge `arg -> out`. */ - predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) { + predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) { exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 | pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and @@ -3460,7 +3473,7 @@ private module Subpaths { * Holds if `n` can reach a return node in a summarized subpath that can reach a sink. */ predicate retReach(PathNodeImpl n) { - exists(PathNode out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) + exists(PathNodeImpl out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) or exists(PathNodeImpl mid | retReach(mid) and @@ -3477,11 +3490,12 @@ private module Subpaths { * sinks. */ private predicate flowsTo( - PathNode flowsource, PathNodeSink flowsink, Node source, Node sink, Configuration configuration + PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink, + Configuration configuration ) { flowsource.isSource() and flowsource.getConfiguration() = configuration and - flowsource.(PathNodeImpl).getNodeEx().asNode() = source and + flowsource.getNodeEx().asNode() = source and (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and flowsink.getNodeEx().asNode() = sink } @@ -3504,14 +3518,14 @@ private predicate finalStats( fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and - tuples = count(PathNode pn) + tuples = count(PathNodeImpl pn) or fwd = false and nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and - tuples = count(PathNode pn | reach(pn)) + tuples = count(PathNode pn) } /** diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl.qll b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl.qll index b5631b26b0bf..8cd1071d084a 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl.qll @@ -2874,54 +2874,16 @@ private class AccessPathCons1 extends AccessPath, TAccessPathCons1 { } } -/** - * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. - * Only those `PathNode`s that are reachable from a source are generated. - */ -class PathNode extends TPathNode { - /** Gets a textual representation of this element. */ - string toString() { none() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - string toStringWithContext() { none() } - - /** - * 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/). - */ - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - none() - } - - /** Gets the underlying `Node`. */ - final Node getNode() { this.(PathNodeImpl).getNodeEx().projectToNode() = result } - +abstract private class PathNodeImpl extends TPathNode { /** Gets the `FlowState` of this node. */ - FlowState getState() { none() } + abstract FlowState getState(); /** Gets the associated configuration. */ - Configuration getConfiguration() { none() } - - /** Gets a successor of this node, if any. */ - final PathNode getASuccessor() { - result = this.(PathNodeImpl).getANonHiddenSuccessor() and - reach(this) and - reach(result) - } + abstract Configuration getConfiguration(); /** Holds if this node is a source. */ - predicate isSource() { none() } -} + abstract predicate isSource(); -abstract private class PathNodeImpl extends PathNode { abstract PathNodeImpl getASuccessorImpl(); private PathNodeImpl getASuccessorIfHidden() { @@ -2967,13 +2929,23 @@ abstract private class PathNodeImpl extends PathNode { result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" } - override string toString() { result = this.getNodeEx().toString() + this.ppAp() } + /** Gets a textual representation of this element. */ + string toString() { result = this.getNodeEx().toString() + this.ppAp() } - override string toStringWithContext() { - result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() - } + /** + * Gets a textual representation of this element, including a textual + * representation of the call context. + */ + string toStringWithContext() { result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() } - override predicate hasLocationInfo( + /** + * 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/). + */ + predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn ) { this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) @@ -2986,14 +2958,59 @@ private predicate directReach(PathNodeImpl n) { } /** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */ -private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) } +private predicate reach(PathNodeImpl n) { directReach(n) or Subpaths::retReach(n) } /** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */ -private predicate pathSucc(PathNodeImpl n1, PathNode n2) { +private predicate pathSucc(PathNodeImpl n1, PathNodeImpl n2) { n1.getANonHiddenSuccessor() = n2 and directReach(n2) } -private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2) +private predicate pathSuccPlus(PathNodeImpl n1, PathNodeImpl n2) = fastTC(pathSucc/2)(n1, n2) + +/** + * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. + * Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated. + */ +class PathNode instanceof PathNodeImpl { + PathNode() { reach(this) } + + /** Gets a textual representation of this element. */ + final string toString() { result = super.toString() } + + /** + * Gets a textual representation of this element, including a textual + * representation of the call context. + */ + final string toStringWithContext() { result = super.toStringWithContext() } + + /** + * 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/). + */ + final predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } + + /** Gets the underlying `Node`. */ + final Node getNode() { super.getNodeEx().projectToNode() = result } + + /** Gets the `FlowState` of this node. */ + final FlowState getState() { result = super.getState() } + + /** Gets the associated configuration. */ + final Configuration getConfiguration() { result = super.getConfiguration() } + + /** Gets a successor of this node, if any. */ + final PathNode getASuccessor() { result = super.getANonHiddenSuccessor() } + + /** Holds if this node is a source. */ + final predicate isSource() { super.isSource() } +} /** * Provides the query predicates needed to include a graph in a path-problem query. @@ -3004,7 +3021,7 @@ module PathGraph { /** Holds if `n` is a node in the graph of data flow path explanations. */ query predicate nodes(PathNode n, string key, string val) { - reach(n) and key = "semmle.label" and val = n.toString() + key = "semmle.label" and val = n.toString() } /** @@ -3013,11 +3030,7 @@ module PathGraph { * `ret -> out` is summarized as the edge `arg -> out`. */ query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) { - Subpaths::subpaths(arg, par, ret, out) and - reach(arg) and - reach(par) and - reach(ret) and - reach(out) + Subpaths::subpaths(arg, par, ret, out) } } @@ -3399,7 +3412,7 @@ private module Subpaths { */ pragma[nomagic] private predicate subpaths02( - PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, + PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, NodeEx out, FlowState sout, AccessPath apout ) { subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and @@ -3407,14 +3420,14 @@ private module Subpaths { } pragma[nomagic] - private Configuration getPathNodeConf(PathNode n) { result = n.getConfiguration() } + private Configuration getPathNodeConf(PathNodeImpl n) { result = n.getConfiguration() } /** * Holds if `(arg, par, ret, out)` forms a subpath-tuple. */ pragma[nomagic] private predicate subpaths03( - PathNode arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout + PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout ) { exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode | subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and @@ -3444,7 +3457,7 @@ private module Subpaths { * a subpath between `par` and `ret` with the connecting edges `arg -> par` and * `ret -> out` is summarized as the edge `arg -> out`. */ - predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) { + predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) { exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 | pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and @@ -3460,7 +3473,7 @@ private module Subpaths { * Holds if `n` can reach a return node in a summarized subpath that can reach a sink. */ predicate retReach(PathNodeImpl n) { - exists(PathNode out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) + exists(PathNodeImpl out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) or exists(PathNodeImpl mid | retReach(mid) and @@ -3477,11 +3490,12 @@ private module Subpaths { * sinks. */ private predicate flowsTo( - PathNode flowsource, PathNodeSink flowsink, Node source, Node sink, Configuration configuration + PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink, + Configuration configuration ) { flowsource.isSource() and flowsource.getConfiguration() = configuration and - flowsource.(PathNodeImpl).getNodeEx().asNode() = source and + flowsource.getNodeEx().asNode() = source and (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and flowsink.getNodeEx().asNode() = sink } @@ -3504,14 +3518,14 @@ private predicate finalStats( fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and - tuples = count(PathNode pn) + tuples = count(PathNodeImpl pn) or fwd = false and nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and - tuples = count(PathNode pn | reach(pn)) + tuples = count(PathNode pn) } /** diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl2.qll b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl2.qll index b5631b26b0bf..8cd1071d084a 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl2.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl2.qll @@ -2874,54 +2874,16 @@ private class AccessPathCons1 extends AccessPath, TAccessPathCons1 { } } -/** - * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. - * Only those `PathNode`s that are reachable from a source are generated. - */ -class PathNode extends TPathNode { - /** Gets a textual representation of this element. */ - string toString() { none() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - string toStringWithContext() { none() } - - /** - * 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/). - */ - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - none() - } - - /** Gets the underlying `Node`. */ - final Node getNode() { this.(PathNodeImpl).getNodeEx().projectToNode() = result } - +abstract private class PathNodeImpl extends TPathNode { /** Gets the `FlowState` of this node. */ - FlowState getState() { none() } + abstract FlowState getState(); /** Gets the associated configuration. */ - Configuration getConfiguration() { none() } - - /** Gets a successor of this node, if any. */ - final PathNode getASuccessor() { - result = this.(PathNodeImpl).getANonHiddenSuccessor() and - reach(this) and - reach(result) - } + abstract Configuration getConfiguration(); /** Holds if this node is a source. */ - predicate isSource() { none() } -} + abstract predicate isSource(); -abstract private class PathNodeImpl extends PathNode { abstract PathNodeImpl getASuccessorImpl(); private PathNodeImpl getASuccessorIfHidden() { @@ -2967,13 +2929,23 @@ abstract private class PathNodeImpl extends PathNode { result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" } - override string toString() { result = this.getNodeEx().toString() + this.ppAp() } + /** Gets a textual representation of this element. */ + string toString() { result = this.getNodeEx().toString() + this.ppAp() } - override string toStringWithContext() { - result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() - } + /** + * Gets a textual representation of this element, including a textual + * representation of the call context. + */ + string toStringWithContext() { result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() } - override predicate hasLocationInfo( + /** + * 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/). + */ + predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn ) { this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) @@ -2986,14 +2958,59 @@ private predicate directReach(PathNodeImpl n) { } /** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */ -private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) } +private predicate reach(PathNodeImpl n) { directReach(n) or Subpaths::retReach(n) } /** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */ -private predicate pathSucc(PathNodeImpl n1, PathNode n2) { +private predicate pathSucc(PathNodeImpl n1, PathNodeImpl n2) { n1.getANonHiddenSuccessor() = n2 and directReach(n2) } -private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2) +private predicate pathSuccPlus(PathNodeImpl n1, PathNodeImpl n2) = fastTC(pathSucc/2)(n1, n2) + +/** + * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. + * Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated. + */ +class PathNode instanceof PathNodeImpl { + PathNode() { reach(this) } + + /** Gets a textual representation of this element. */ + final string toString() { result = super.toString() } + + /** + * Gets a textual representation of this element, including a textual + * representation of the call context. + */ + final string toStringWithContext() { result = super.toStringWithContext() } + + /** + * 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/). + */ + final predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } + + /** Gets the underlying `Node`. */ + final Node getNode() { super.getNodeEx().projectToNode() = result } + + /** Gets the `FlowState` of this node. */ + final FlowState getState() { result = super.getState() } + + /** Gets the associated configuration. */ + final Configuration getConfiguration() { result = super.getConfiguration() } + + /** Gets a successor of this node, if any. */ + final PathNode getASuccessor() { result = super.getANonHiddenSuccessor() } + + /** Holds if this node is a source. */ + final predicate isSource() { super.isSource() } +} /** * Provides the query predicates needed to include a graph in a path-problem query. @@ -3004,7 +3021,7 @@ module PathGraph { /** Holds if `n` is a node in the graph of data flow path explanations. */ query predicate nodes(PathNode n, string key, string val) { - reach(n) and key = "semmle.label" and val = n.toString() + key = "semmle.label" and val = n.toString() } /** @@ -3013,11 +3030,7 @@ module PathGraph { * `ret -> out` is summarized as the edge `arg -> out`. */ query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) { - Subpaths::subpaths(arg, par, ret, out) and - reach(arg) and - reach(par) and - reach(ret) and - reach(out) + Subpaths::subpaths(arg, par, ret, out) } } @@ -3399,7 +3412,7 @@ private module Subpaths { */ pragma[nomagic] private predicate subpaths02( - PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, + PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, NodeEx out, FlowState sout, AccessPath apout ) { subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and @@ -3407,14 +3420,14 @@ private module Subpaths { } pragma[nomagic] - private Configuration getPathNodeConf(PathNode n) { result = n.getConfiguration() } + private Configuration getPathNodeConf(PathNodeImpl n) { result = n.getConfiguration() } /** * Holds if `(arg, par, ret, out)` forms a subpath-tuple. */ pragma[nomagic] private predicate subpaths03( - PathNode arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout + PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout ) { exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode | subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and @@ -3444,7 +3457,7 @@ private module Subpaths { * a subpath between `par` and `ret` with the connecting edges `arg -> par` and * `ret -> out` is summarized as the edge `arg -> out`. */ - predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) { + predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) { exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 | pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and @@ -3460,7 +3473,7 @@ private module Subpaths { * Holds if `n` can reach a return node in a summarized subpath that can reach a sink. */ predicate retReach(PathNodeImpl n) { - exists(PathNode out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) + exists(PathNodeImpl out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) or exists(PathNodeImpl mid | retReach(mid) and @@ -3477,11 +3490,12 @@ private module Subpaths { * sinks. */ private predicate flowsTo( - PathNode flowsource, PathNodeSink flowsink, Node source, Node sink, Configuration configuration + PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink, + Configuration configuration ) { flowsource.isSource() and flowsource.getConfiguration() = configuration and - flowsource.(PathNodeImpl).getNodeEx().asNode() = source and + flowsource.getNodeEx().asNode() = source and (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and flowsink.getNodeEx().asNode() = sink } @@ -3504,14 +3518,14 @@ private predicate finalStats( fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and - tuples = count(PathNode pn) + tuples = count(PathNodeImpl pn) or fwd = false and nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and - tuples = count(PathNode pn | reach(pn)) + tuples = count(PathNode pn) } /** diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl3.qll b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl3.qll index b5631b26b0bf..8cd1071d084a 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl3.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl3.qll @@ -2874,54 +2874,16 @@ private class AccessPathCons1 extends AccessPath, TAccessPathCons1 { } } -/** - * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. - * Only those `PathNode`s that are reachable from a source are generated. - */ -class PathNode extends TPathNode { - /** Gets a textual representation of this element. */ - string toString() { none() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - string toStringWithContext() { none() } - - /** - * 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/). - */ - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - none() - } - - /** Gets the underlying `Node`. */ - final Node getNode() { this.(PathNodeImpl).getNodeEx().projectToNode() = result } - +abstract private class PathNodeImpl extends TPathNode { /** Gets the `FlowState` of this node. */ - FlowState getState() { none() } + abstract FlowState getState(); /** Gets the associated configuration. */ - Configuration getConfiguration() { none() } - - /** Gets a successor of this node, if any. */ - final PathNode getASuccessor() { - result = this.(PathNodeImpl).getANonHiddenSuccessor() and - reach(this) and - reach(result) - } + abstract Configuration getConfiguration(); /** Holds if this node is a source. */ - predicate isSource() { none() } -} + abstract predicate isSource(); -abstract private class PathNodeImpl extends PathNode { abstract PathNodeImpl getASuccessorImpl(); private PathNodeImpl getASuccessorIfHidden() { @@ -2967,13 +2929,23 @@ abstract private class PathNodeImpl extends PathNode { result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" } - override string toString() { result = this.getNodeEx().toString() + this.ppAp() } + /** Gets a textual representation of this element. */ + string toString() { result = this.getNodeEx().toString() + this.ppAp() } - override string toStringWithContext() { - result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() - } + /** + * Gets a textual representation of this element, including a textual + * representation of the call context. + */ + string toStringWithContext() { result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() } - override predicate hasLocationInfo( + /** + * 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/). + */ + predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn ) { this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) @@ -2986,14 +2958,59 @@ private predicate directReach(PathNodeImpl n) { } /** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */ -private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) } +private predicate reach(PathNodeImpl n) { directReach(n) or Subpaths::retReach(n) } /** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */ -private predicate pathSucc(PathNodeImpl n1, PathNode n2) { +private predicate pathSucc(PathNodeImpl n1, PathNodeImpl n2) { n1.getANonHiddenSuccessor() = n2 and directReach(n2) } -private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2) +private predicate pathSuccPlus(PathNodeImpl n1, PathNodeImpl n2) = fastTC(pathSucc/2)(n1, n2) + +/** + * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. + * Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated. + */ +class PathNode instanceof PathNodeImpl { + PathNode() { reach(this) } + + /** Gets a textual representation of this element. */ + final string toString() { result = super.toString() } + + /** + * Gets a textual representation of this element, including a textual + * representation of the call context. + */ + final string toStringWithContext() { result = super.toStringWithContext() } + + /** + * 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/). + */ + final predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } + + /** Gets the underlying `Node`. */ + final Node getNode() { super.getNodeEx().projectToNode() = result } + + /** Gets the `FlowState` of this node. */ + final FlowState getState() { result = super.getState() } + + /** Gets the associated configuration. */ + final Configuration getConfiguration() { result = super.getConfiguration() } + + /** Gets a successor of this node, if any. */ + final PathNode getASuccessor() { result = super.getANonHiddenSuccessor() } + + /** Holds if this node is a source. */ + final predicate isSource() { super.isSource() } +} /** * Provides the query predicates needed to include a graph in a path-problem query. @@ -3004,7 +3021,7 @@ module PathGraph { /** Holds if `n` is a node in the graph of data flow path explanations. */ query predicate nodes(PathNode n, string key, string val) { - reach(n) and key = "semmle.label" and val = n.toString() + key = "semmle.label" and val = n.toString() } /** @@ -3013,11 +3030,7 @@ module PathGraph { * `ret -> out` is summarized as the edge `arg -> out`. */ query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) { - Subpaths::subpaths(arg, par, ret, out) and - reach(arg) and - reach(par) and - reach(ret) and - reach(out) + Subpaths::subpaths(arg, par, ret, out) } } @@ -3399,7 +3412,7 @@ private module Subpaths { */ pragma[nomagic] private predicate subpaths02( - PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, + PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, NodeEx out, FlowState sout, AccessPath apout ) { subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and @@ -3407,14 +3420,14 @@ private module Subpaths { } pragma[nomagic] - private Configuration getPathNodeConf(PathNode n) { result = n.getConfiguration() } + private Configuration getPathNodeConf(PathNodeImpl n) { result = n.getConfiguration() } /** * Holds if `(arg, par, ret, out)` forms a subpath-tuple. */ pragma[nomagic] private predicate subpaths03( - PathNode arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout + PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout ) { exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode | subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and @@ -3444,7 +3457,7 @@ private module Subpaths { * a subpath between `par` and `ret` with the connecting edges `arg -> par` and * `ret -> out` is summarized as the edge `arg -> out`. */ - predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) { + predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) { exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 | pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and @@ -3460,7 +3473,7 @@ private module Subpaths { * Holds if `n` can reach a return node in a summarized subpath that can reach a sink. */ predicate retReach(PathNodeImpl n) { - exists(PathNode out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) + exists(PathNodeImpl out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) or exists(PathNodeImpl mid | retReach(mid) and @@ -3477,11 +3490,12 @@ private module Subpaths { * sinks. */ private predicate flowsTo( - PathNode flowsource, PathNodeSink flowsink, Node source, Node sink, Configuration configuration + PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink, + Configuration configuration ) { flowsource.isSource() and flowsource.getConfiguration() = configuration and - flowsource.(PathNodeImpl).getNodeEx().asNode() = source and + flowsource.getNodeEx().asNode() = source and (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and flowsink.getNodeEx().asNode() = sink } @@ -3504,14 +3518,14 @@ private predicate finalStats( fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and - tuples = count(PathNode pn) + tuples = count(PathNodeImpl pn) or fwd = false and nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and - tuples = count(PathNode pn | reach(pn)) + tuples = count(PathNode pn) } /** diff --git a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl4.qll b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl4.qll index b5631b26b0bf..8cd1071d084a 100644 --- a/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl4.qll +++ b/python/ql/lib/semmle/python/dataflow/new/internal/DataFlowImpl4.qll @@ -2874,54 +2874,16 @@ private class AccessPathCons1 extends AccessPath, TAccessPathCons1 { } } -/** - * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. - * Only those `PathNode`s that are reachable from a source are generated. - */ -class PathNode extends TPathNode { - /** Gets a textual representation of this element. */ - string toString() { none() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - string toStringWithContext() { none() } - - /** - * 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/). - */ - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - none() - } - - /** Gets the underlying `Node`. */ - final Node getNode() { this.(PathNodeImpl).getNodeEx().projectToNode() = result } - +abstract private class PathNodeImpl extends TPathNode { /** Gets the `FlowState` of this node. */ - FlowState getState() { none() } + abstract FlowState getState(); /** Gets the associated configuration. */ - Configuration getConfiguration() { none() } - - /** Gets a successor of this node, if any. */ - final PathNode getASuccessor() { - result = this.(PathNodeImpl).getANonHiddenSuccessor() and - reach(this) and - reach(result) - } + abstract Configuration getConfiguration(); /** Holds if this node is a source. */ - predicate isSource() { none() } -} + abstract predicate isSource(); -abstract private class PathNodeImpl extends PathNode { abstract PathNodeImpl getASuccessorImpl(); private PathNodeImpl getASuccessorIfHidden() { @@ -2967,13 +2929,23 @@ abstract private class PathNodeImpl extends PathNode { result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" } - override string toString() { result = this.getNodeEx().toString() + this.ppAp() } + /** Gets a textual representation of this element. */ + string toString() { result = this.getNodeEx().toString() + this.ppAp() } - override string toStringWithContext() { - result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() - } + /** + * Gets a textual representation of this element, including a textual + * representation of the call context. + */ + string toStringWithContext() { result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() } - override predicate hasLocationInfo( + /** + * 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/). + */ + predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn ) { this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) @@ -2986,14 +2958,59 @@ private predicate directReach(PathNodeImpl n) { } /** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */ -private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) } +private predicate reach(PathNodeImpl n) { directReach(n) or Subpaths::retReach(n) } /** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */ -private predicate pathSucc(PathNodeImpl n1, PathNode n2) { +private predicate pathSucc(PathNodeImpl n1, PathNodeImpl n2) { n1.getANonHiddenSuccessor() = n2 and directReach(n2) } -private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2) +private predicate pathSuccPlus(PathNodeImpl n1, PathNodeImpl n2) = fastTC(pathSucc/2)(n1, n2) + +/** + * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. + * Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated. + */ +class PathNode instanceof PathNodeImpl { + PathNode() { reach(this) } + + /** Gets a textual representation of this element. */ + final string toString() { result = super.toString() } + + /** + * Gets a textual representation of this element, including a textual + * representation of the call context. + */ + final string toStringWithContext() { result = super.toStringWithContext() } + + /** + * 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/). + */ + final predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } + + /** Gets the underlying `Node`. */ + final Node getNode() { super.getNodeEx().projectToNode() = result } + + /** Gets the `FlowState` of this node. */ + final FlowState getState() { result = super.getState() } + + /** Gets the associated configuration. */ + final Configuration getConfiguration() { result = super.getConfiguration() } + + /** Gets a successor of this node, if any. */ + final PathNode getASuccessor() { result = super.getANonHiddenSuccessor() } + + /** Holds if this node is a source. */ + final predicate isSource() { super.isSource() } +} /** * Provides the query predicates needed to include a graph in a path-problem query. @@ -3004,7 +3021,7 @@ module PathGraph { /** Holds if `n` is a node in the graph of data flow path explanations. */ query predicate nodes(PathNode n, string key, string val) { - reach(n) and key = "semmle.label" and val = n.toString() + key = "semmle.label" and val = n.toString() } /** @@ -3013,11 +3030,7 @@ module PathGraph { * `ret -> out` is summarized as the edge `arg -> out`. */ query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) { - Subpaths::subpaths(arg, par, ret, out) and - reach(arg) and - reach(par) and - reach(ret) and - reach(out) + Subpaths::subpaths(arg, par, ret, out) } } @@ -3399,7 +3412,7 @@ private module Subpaths { */ pragma[nomagic] private predicate subpaths02( - PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, + PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, NodeEx out, FlowState sout, AccessPath apout ) { subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and @@ -3407,14 +3420,14 @@ private module Subpaths { } pragma[nomagic] - private Configuration getPathNodeConf(PathNode n) { result = n.getConfiguration() } + private Configuration getPathNodeConf(PathNodeImpl n) { result = n.getConfiguration() } /** * Holds if `(arg, par, ret, out)` forms a subpath-tuple. */ pragma[nomagic] private predicate subpaths03( - PathNode arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout + PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout ) { exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode | subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and @@ -3444,7 +3457,7 @@ private module Subpaths { * a subpath between `par` and `ret` with the connecting edges `arg -> par` and * `ret -> out` is summarized as the edge `arg -> out`. */ - predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) { + predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) { exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 | pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and @@ -3460,7 +3473,7 @@ private module Subpaths { * Holds if `n` can reach a return node in a summarized subpath that can reach a sink. */ predicate retReach(PathNodeImpl n) { - exists(PathNode out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) + exists(PathNodeImpl out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) or exists(PathNodeImpl mid | retReach(mid) and @@ -3477,11 +3490,12 @@ private module Subpaths { * sinks. */ private predicate flowsTo( - PathNode flowsource, PathNodeSink flowsink, Node source, Node sink, Configuration configuration + PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink, + Configuration configuration ) { flowsource.isSource() and flowsource.getConfiguration() = configuration and - flowsource.(PathNodeImpl).getNodeEx().asNode() = source and + flowsource.getNodeEx().asNode() = source and (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and flowsink.getNodeEx().asNode() = sink } @@ -3504,14 +3518,14 @@ private predicate finalStats( fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and - tuples = count(PathNode pn) + tuples = count(PathNodeImpl pn) or fwd = false and nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and - tuples = count(PathNode pn | reach(pn)) + tuples = count(PathNode pn) } /** diff --git a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl2.qll b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl2.qll index b5631b26b0bf..8cd1071d084a 100644 --- a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl2.qll +++ b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImpl2.qll @@ -2874,54 +2874,16 @@ private class AccessPathCons1 extends AccessPath, TAccessPathCons1 { } } -/** - * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. - * Only those `PathNode`s that are reachable from a source are generated. - */ -class PathNode extends TPathNode { - /** Gets a textual representation of this element. */ - string toString() { none() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - string toStringWithContext() { none() } - - /** - * 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/). - */ - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - none() - } - - /** Gets the underlying `Node`. */ - final Node getNode() { this.(PathNodeImpl).getNodeEx().projectToNode() = result } - +abstract private class PathNodeImpl extends TPathNode { /** Gets the `FlowState` of this node. */ - FlowState getState() { none() } + abstract FlowState getState(); /** Gets the associated configuration. */ - Configuration getConfiguration() { none() } - - /** Gets a successor of this node, if any. */ - final PathNode getASuccessor() { - result = this.(PathNodeImpl).getANonHiddenSuccessor() and - reach(this) and - reach(result) - } + abstract Configuration getConfiguration(); /** Holds if this node is a source. */ - predicate isSource() { none() } -} + abstract predicate isSource(); -abstract private class PathNodeImpl extends PathNode { abstract PathNodeImpl getASuccessorImpl(); private PathNodeImpl getASuccessorIfHidden() { @@ -2967,13 +2929,23 @@ abstract private class PathNodeImpl extends PathNode { result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" } - override string toString() { result = this.getNodeEx().toString() + this.ppAp() } + /** Gets a textual representation of this element. */ + string toString() { result = this.getNodeEx().toString() + this.ppAp() } - override string toStringWithContext() { - result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() - } + /** + * Gets a textual representation of this element, including a textual + * representation of the call context. + */ + string toStringWithContext() { result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() } - override predicate hasLocationInfo( + /** + * 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/). + */ + predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn ) { this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) @@ -2986,14 +2958,59 @@ private predicate directReach(PathNodeImpl n) { } /** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */ -private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) } +private predicate reach(PathNodeImpl n) { directReach(n) or Subpaths::retReach(n) } /** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */ -private predicate pathSucc(PathNodeImpl n1, PathNode n2) { +private predicate pathSucc(PathNodeImpl n1, PathNodeImpl n2) { n1.getANonHiddenSuccessor() = n2 and directReach(n2) } -private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2) +private predicate pathSuccPlus(PathNodeImpl n1, PathNodeImpl n2) = fastTC(pathSucc/2)(n1, n2) + +/** + * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. + * Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated. + */ +class PathNode instanceof PathNodeImpl { + PathNode() { reach(this) } + + /** Gets a textual representation of this element. */ + final string toString() { result = super.toString() } + + /** + * Gets a textual representation of this element, including a textual + * representation of the call context. + */ + final string toStringWithContext() { result = super.toStringWithContext() } + + /** + * 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/). + */ + final predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } + + /** Gets the underlying `Node`. */ + final Node getNode() { super.getNodeEx().projectToNode() = result } + + /** Gets the `FlowState` of this node. */ + final FlowState getState() { result = super.getState() } + + /** Gets the associated configuration. */ + final Configuration getConfiguration() { result = super.getConfiguration() } + + /** Gets a successor of this node, if any. */ + final PathNode getASuccessor() { result = super.getANonHiddenSuccessor() } + + /** Holds if this node is a source. */ + final predicate isSource() { super.isSource() } +} /** * Provides the query predicates needed to include a graph in a path-problem query. @@ -3004,7 +3021,7 @@ module PathGraph { /** Holds if `n` is a node in the graph of data flow path explanations. */ query predicate nodes(PathNode n, string key, string val) { - reach(n) and key = "semmle.label" and val = n.toString() + key = "semmle.label" and val = n.toString() } /** @@ -3013,11 +3030,7 @@ module PathGraph { * `ret -> out` is summarized as the edge `arg -> out`. */ query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) { - Subpaths::subpaths(arg, par, ret, out) and - reach(arg) and - reach(par) and - reach(ret) and - reach(out) + Subpaths::subpaths(arg, par, ret, out) } } @@ -3399,7 +3412,7 @@ private module Subpaths { */ pragma[nomagic] private predicate subpaths02( - PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, + PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, NodeEx out, FlowState sout, AccessPath apout ) { subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and @@ -3407,14 +3420,14 @@ private module Subpaths { } pragma[nomagic] - private Configuration getPathNodeConf(PathNode n) { result = n.getConfiguration() } + private Configuration getPathNodeConf(PathNodeImpl n) { result = n.getConfiguration() } /** * Holds if `(arg, par, ret, out)` forms a subpath-tuple. */ pragma[nomagic] private predicate subpaths03( - PathNode arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout + PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout ) { exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode | subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and @@ -3444,7 +3457,7 @@ private module Subpaths { * a subpath between `par` and `ret` with the connecting edges `arg -> par` and * `ret -> out` is summarized as the edge `arg -> out`. */ - predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) { + predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) { exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 | pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and @@ -3460,7 +3473,7 @@ private module Subpaths { * Holds if `n` can reach a return node in a summarized subpath that can reach a sink. */ predicate retReach(PathNodeImpl n) { - exists(PathNode out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) + exists(PathNodeImpl out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) or exists(PathNodeImpl mid | retReach(mid) and @@ -3477,11 +3490,12 @@ private module Subpaths { * sinks. */ private predicate flowsTo( - PathNode flowsource, PathNodeSink flowsink, Node source, Node sink, Configuration configuration + PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink, + Configuration configuration ) { flowsource.isSource() and flowsource.getConfiguration() = configuration and - flowsource.(PathNodeImpl).getNodeEx().asNode() = source and + flowsource.getNodeEx().asNode() = source and (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and flowsink.getNodeEx().asNode() = sink } @@ -3504,14 +3518,14 @@ private predicate finalStats( fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and - tuples = count(PathNode pn) + tuples = count(PathNodeImpl pn) or fwd = false and nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and - tuples = count(PathNode pn | reach(pn)) + tuples = count(PathNode pn) } /** diff --git a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplForHttpClientLibraries.qll b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplForHttpClientLibraries.qll index b5631b26b0bf..8cd1071d084a 100644 --- a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplForHttpClientLibraries.qll +++ b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplForHttpClientLibraries.qll @@ -2874,54 +2874,16 @@ private class AccessPathCons1 extends AccessPath, TAccessPathCons1 { } } -/** - * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. - * Only those `PathNode`s that are reachable from a source are generated. - */ -class PathNode extends TPathNode { - /** Gets a textual representation of this element. */ - string toString() { none() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - string toStringWithContext() { none() } - - /** - * 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/). - */ - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - none() - } - - /** Gets the underlying `Node`. */ - final Node getNode() { this.(PathNodeImpl).getNodeEx().projectToNode() = result } - +abstract private class PathNodeImpl extends TPathNode { /** Gets the `FlowState` of this node. */ - FlowState getState() { none() } + abstract FlowState getState(); /** Gets the associated configuration. */ - Configuration getConfiguration() { none() } - - /** Gets a successor of this node, if any. */ - final PathNode getASuccessor() { - result = this.(PathNodeImpl).getANonHiddenSuccessor() and - reach(this) and - reach(result) - } + abstract Configuration getConfiguration(); /** Holds if this node is a source. */ - predicate isSource() { none() } -} + abstract predicate isSource(); -abstract private class PathNodeImpl extends PathNode { abstract PathNodeImpl getASuccessorImpl(); private PathNodeImpl getASuccessorIfHidden() { @@ -2967,13 +2929,23 @@ abstract private class PathNodeImpl extends PathNode { result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" } - override string toString() { result = this.getNodeEx().toString() + this.ppAp() } + /** Gets a textual representation of this element. */ + string toString() { result = this.getNodeEx().toString() + this.ppAp() } - override string toStringWithContext() { - result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() - } + /** + * Gets a textual representation of this element, including a textual + * representation of the call context. + */ + string toStringWithContext() { result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() } - override predicate hasLocationInfo( + /** + * 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/). + */ + predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn ) { this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) @@ -2986,14 +2958,59 @@ private predicate directReach(PathNodeImpl n) { } /** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */ -private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) } +private predicate reach(PathNodeImpl n) { directReach(n) or Subpaths::retReach(n) } /** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */ -private predicate pathSucc(PathNodeImpl n1, PathNode n2) { +private predicate pathSucc(PathNodeImpl n1, PathNodeImpl n2) { n1.getANonHiddenSuccessor() = n2 and directReach(n2) } -private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2) +private predicate pathSuccPlus(PathNodeImpl n1, PathNodeImpl n2) = fastTC(pathSucc/2)(n1, n2) + +/** + * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. + * Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated. + */ +class PathNode instanceof PathNodeImpl { + PathNode() { reach(this) } + + /** Gets a textual representation of this element. */ + final string toString() { result = super.toString() } + + /** + * Gets a textual representation of this element, including a textual + * representation of the call context. + */ + final string toStringWithContext() { result = super.toStringWithContext() } + + /** + * 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/). + */ + final predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } + + /** Gets the underlying `Node`. */ + final Node getNode() { super.getNodeEx().projectToNode() = result } + + /** Gets the `FlowState` of this node. */ + final FlowState getState() { result = super.getState() } + + /** Gets the associated configuration. */ + final Configuration getConfiguration() { result = super.getConfiguration() } + + /** Gets a successor of this node, if any. */ + final PathNode getASuccessor() { result = super.getANonHiddenSuccessor() } + + /** Holds if this node is a source. */ + final predicate isSource() { super.isSource() } +} /** * Provides the query predicates needed to include a graph in a path-problem query. @@ -3004,7 +3021,7 @@ module PathGraph { /** Holds if `n` is a node in the graph of data flow path explanations. */ query predicate nodes(PathNode n, string key, string val) { - reach(n) and key = "semmle.label" and val = n.toString() + key = "semmle.label" and val = n.toString() } /** @@ -3013,11 +3030,7 @@ module PathGraph { * `ret -> out` is summarized as the edge `arg -> out`. */ query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) { - Subpaths::subpaths(arg, par, ret, out) and - reach(arg) and - reach(par) and - reach(ret) and - reach(out) + Subpaths::subpaths(arg, par, ret, out) } } @@ -3399,7 +3412,7 @@ private module Subpaths { */ pragma[nomagic] private predicate subpaths02( - PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, + PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, NodeEx out, FlowState sout, AccessPath apout ) { subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and @@ -3407,14 +3420,14 @@ private module Subpaths { } pragma[nomagic] - private Configuration getPathNodeConf(PathNode n) { result = n.getConfiguration() } + private Configuration getPathNodeConf(PathNodeImpl n) { result = n.getConfiguration() } /** * Holds if `(arg, par, ret, out)` forms a subpath-tuple. */ pragma[nomagic] private predicate subpaths03( - PathNode arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout + PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout ) { exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode | subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and @@ -3444,7 +3457,7 @@ private module Subpaths { * a subpath between `par` and `ret` with the connecting edges `arg -> par` and * `ret -> out` is summarized as the edge `arg -> out`. */ - predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) { + predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) { exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 | pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and @@ -3460,7 +3473,7 @@ private module Subpaths { * Holds if `n` can reach a return node in a summarized subpath that can reach a sink. */ predicate retReach(PathNodeImpl n) { - exists(PathNode out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) + exists(PathNodeImpl out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) or exists(PathNodeImpl mid | retReach(mid) and @@ -3477,11 +3490,12 @@ private module Subpaths { * sinks. */ private predicate flowsTo( - PathNode flowsource, PathNodeSink flowsink, Node source, Node sink, Configuration configuration + PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink, + Configuration configuration ) { flowsource.isSource() and flowsource.getConfiguration() = configuration and - flowsource.(PathNodeImpl).getNodeEx().asNode() = source and + flowsource.getNodeEx().asNode() = source and (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and flowsink.getNodeEx().asNode() = sink } @@ -3504,14 +3518,14 @@ private predicate finalStats( fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and - tuples = count(PathNode pn) + tuples = count(PathNodeImpl pn) or fwd = false and nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and - tuples = count(PathNode pn | reach(pn)) + tuples = count(PathNode pn) } /** diff --git a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplForPathname.qll b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplForPathname.qll index b5631b26b0bf..8cd1071d084a 100644 --- a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplForPathname.qll +++ b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplForPathname.qll @@ -2874,54 +2874,16 @@ private class AccessPathCons1 extends AccessPath, TAccessPathCons1 { } } -/** - * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. - * Only those `PathNode`s that are reachable from a source are generated. - */ -class PathNode extends TPathNode { - /** Gets a textual representation of this element. */ - string toString() { none() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - string toStringWithContext() { none() } - - /** - * 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/). - */ - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - none() - } - - /** Gets the underlying `Node`. */ - final Node getNode() { this.(PathNodeImpl).getNodeEx().projectToNode() = result } - +abstract private class PathNodeImpl extends TPathNode { /** Gets the `FlowState` of this node. */ - FlowState getState() { none() } + abstract FlowState getState(); /** Gets the associated configuration. */ - Configuration getConfiguration() { none() } - - /** Gets a successor of this node, if any. */ - final PathNode getASuccessor() { - result = this.(PathNodeImpl).getANonHiddenSuccessor() and - reach(this) and - reach(result) - } + abstract Configuration getConfiguration(); /** Holds if this node is a source. */ - predicate isSource() { none() } -} + abstract predicate isSource(); -abstract private class PathNodeImpl extends PathNode { abstract PathNodeImpl getASuccessorImpl(); private PathNodeImpl getASuccessorIfHidden() { @@ -2967,13 +2929,23 @@ abstract private class PathNodeImpl extends PathNode { result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" } - override string toString() { result = this.getNodeEx().toString() + this.ppAp() } + /** Gets a textual representation of this element. */ + string toString() { result = this.getNodeEx().toString() + this.ppAp() } - override string toStringWithContext() { - result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() - } + /** + * Gets a textual representation of this element, including a textual + * representation of the call context. + */ + string toStringWithContext() { result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() } - override predicate hasLocationInfo( + /** + * 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/). + */ + predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn ) { this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) @@ -2986,14 +2958,59 @@ private predicate directReach(PathNodeImpl n) { } /** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */ -private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) } +private predicate reach(PathNodeImpl n) { directReach(n) or Subpaths::retReach(n) } /** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */ -private predicate pathSucc(PathNodeImpl n1, PathNode n2) { +private predicate pathSucc(PathNodeImpl n1, PathNodeImpl n2) { n1.getANonHiddenSuccessor() = n2 and directReach(n2) } -private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2) +private predicate pathSuccPlus(PathNodeImpl n1, PathNodeImpl n2) = fastTC(pathSucc/2)(n1, n2) + +/** + * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. + * Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated. + */ +class PathNode instanceof PathNodeImpl { + PathNode() { reach(this) } + + /** Gets a textual representation of this element. */ + final string toString() { result = super.toString() } + + /** + * Gets a textual representation of this element, including a textual + * representation of the call context. + */ + final string toStringWithContext() { result = super.toStringWithContext() } + + /** + * 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/). + */ + final predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } + + /** Gets the underlying `Node`. */ + final Node getNode() { super.getNodeEx().projectToNode() = result } + + /** Gets the `FlowState` of this node. */ + final FlowState getState() { result = super.getState() } + + /** Gets the associated configuration. */ + final Configuration getConfiguration() { result = super.getConfiguration() } + + /** Gets a successor of this node, if any. */ + final PathNode getASuccessor() { result = super.getANonHiddenSuccessor() } + + /** Holds if this node is a source. */ + final predicate isSource() { super.isSource() } +} /** * Provides the query predicates needed to include a graph in a path-problem query. @@ -3004,7 +3021,7 @@ module PathGraph { /** Holds if `n` is a node in the graph of data flow path explanations. */ query predicate nodes(PathNode n, string key, string val) { - reach(n) and key = "semmle.label" and val = n.toString() + key = "semmle.label" and val = n.toString() } /** @@ -3013,11 +3030,7 @@ module PathGraph { * `ret -> out` is summarized as the edge `arg -> out`. */ query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) { - Subpaths::subpaths(arg, par, ret, out) and - reach(arg) and - reach(par) and - reach(ret) and - reach(out) + Subpaths::subpaths(arg, par, ret, out) } } @@ -3399,7 +3412,7 @@ private module Subpaths { */ pragma[nomagic] private predicate subpaths02( - PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, + PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, NodeEx out, FlowState sout, AccessPath apout ) { subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and @@ -3407,14 +3420,14 @@ private module Subpaths { } pragma[nomagic] - private Configuration getPathNodeConf(PathNode n) { result = n.getConfiguration() } + private Configuration getPathNodeConf(PathNodeImpl n) { result = n.getConfiguration() } /** * Holds if `(arg, par, ret, out)` forms a subpath-tuple. */ pragma[nomagic] private predicate subpaths03( - PathNode arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout + PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout ) { exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode | subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and @@ -3444,7 +3457,7 @@ private module Subpaths { * a subpath between `par` and `ret` with the connecting edges `arg -> par` and * `ret -> out` is summarized as the edge `arg -> out`. */ - predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) { + predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) { exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 | pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and @@ -3460,7 +3473,7 @@ private module Subpaths { * Holds if `n` can reach a return node in a summarized subpath that can reach a sink. */ predicate retReach(PathNodeImpl n) { - exists(PathNode out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) + exists(PathNodeImpl out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) or exists(PathNodeImpl mid | retReach(mid) and @@ -3477,11 +3490,12 @@ private module Subpaths { * sinks. */ private predicate flowsTo( - PathNode flowsource, PathNodeSink flowsink, Node source, Node sink, Configuration configuration + PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink, + Configuration configuration ) { flowsource.isSource() and flowsource.getConfiguration() = configuration and - flowsource.(PathNodeImpl).getNodeEx().asNode() = source and + flowsource.getNodeEx().asNode() = source and (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and flowsink.getNodeEx().asNode() = sink } @@ -3504,14 +3518,14 @@ private predicate finalStats( fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and - tuples = count(PathNode pn) + tuples = count(PathNodeImpl pn) or fwd = false and nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and - tuples = count(PathNode pn | reach(pn)) + tuples = count(PathNode pn) } /** diff --git a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplForRegExp.qll b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplForRegExp.qll index b5631b26b0bf..8cd1071d084a 100644 --- a/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplForRegExp.qll +++ b/ruby/ql/lib/codeql/ruby/dataflow/internal/DataFlowImplForRegExp.qll @@ -2874,54 +2874,16 @@ private class AccessPathCons1 extends AccessPath, TAccessPathCons1 { } } -/** - * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. - * Only those `PathNode`s that are reachable from a source are generated. - */ -class PathNode extends TPathNode { - /** Gets a textual representation of this element. */ - string toString() { none() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - string toStringWithContext() { none() } - - /** - * 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/). - */ - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - none() - } - - /** Gets the underlying `Node`. */ - final Node getNode() { this.(PathNodeImpl).getNodeEx().projectToNode() = result } - +abstract private class PathNodeImpl extends TPathNode { /** Gets the `FlowState` of this node. */ - FlowState getState() { none() } + abstract FlowState getState(); /** Gets the associated configuration. */ - Configuration getConfiguration() { none() } - - /** Gets a successor of this node, if any. */ - final PathNode getASuccessor() { - result = this.(PathNodeImpl).getANonHiddenSuccessor() and - reach(this) and - reach(result) - } + abstract Configuration getConfiguration(); /** Holds if this node is a source. */ - predicate isSource() { none() } -} + abstract predicate isSource(); -abstract private class PathNodeImpl extends PathNode { abstract PathNodeImpl getASuccessorImpl(); private PathNodeImpl getASuccessorIfHidden() { @@ -2967,13 +2929,23 @@ abstract private class PathNodeImpl extends PathNode { result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" } - override string toString() { result = this.getNodeEx().toString() + this.ppAp() } + /** Gets a textual representation of this element. */ + string toString() { result = this.getNodeEx().toString() + this.ppAp() } - override string toStringWithContext() { - result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() - } + /** + * Gets a textual representation of this element, including a textual + * representation of the call context. + */ + string toStringWithContext() { result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() } - override predicate hasLocationInfo( + /** + * 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/). + */ + predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn ) { this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) @@ -2986,14 +2958,59 @@ private predicate directReach(PathNodeImpl n) { } /** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */ -private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) } +private predicate reach(PathNodeImpl n) { directReach(n) or Subpaths::retReach(n) } /** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */ -private predicate pathSucc(PathNodeImpl n1, PathNode n2) { +private predicate pathSucc(PathNodeImpl n1, PathNodeImpl n2) { n1.getANonHiddenSuccessor() = n2 and directReach(n2) } -private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2) +private predicate pathSuccPlus(PathNodeImpl n1, PathNodeImpl n2) = fastTC(pathSucc/2)(n1, n2) + +/** + * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. + * Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated. + */ +class PathNode instanceof PathNodeImpl { + PathNode() { reach(this) } + + /** Gets a textual representation of this element. */ + final string toString() { result = super.toString() } + + /** + * Gets a textual representation of this element, including a textual + * representation of the call context. + */ + final string toStringWithContext() { result = super.toStringWithContext() } + + /** + * 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/). + */ + final predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } + + /** Gets the underlying `Node`. */ + final Node getNode() { super.getNodeEx().projectToNode() = result } + + /** Gets the `FlowState` of this node. */ + final FlowState getState() { result = super.getState() } + + /** Gets the associated configuration. */ + final Configuration getConfiguration() { result = super.getConfiguration() } + + /** Gets a successor of this node, if any. */ + final PathNode getASuccessor() { result = super.getANonHiddenSuccessor() } + + /** Holds if this node is a source. */ + final predicate isSource() { super.isSource() } +} /** * Provides the query predicates needed to include a graph in a path-problem query. @@ -3004,7 +3021,7 @@ module PathGraph { /** Holds if `n` is a node in the graph of data flow path explanations. */ query predicate nodes(PathNode n, string key, string val) { - reach(n) and key = "semmle.label" and val = n.toString() + key = "semmle.label" and val = n.toString() } /** @@ -3013,11 +3030,7 @@ module PathGraph { * `ret -> out` is summarized as the edge `arg -> out`. */ query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) { - Subpaths::subpaths(arg, par, ret, out) and - reach(arg) and - reach(par) and - reach(ret) and - reach(out) + Subpaths::subpaths(arg, par, ret, out) } } @@ -3399,7 +3412,7 @@ private module Subpaths { */ pragma[nomagic] private predicate subpaths02( - PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, + PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, NodeEx out, FlowState sout, AccessPath apout ) { subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and @@ -3407,14 +3420,14 @@ private module Subpaths { } pragma[nomagic] - private Configuration getPathNodeConf(PathNode n) { result = n.getConfiguration() } + private Configuration getPathNodeConf(PathNodeImpl n) { result = n.getConfiguration() } /** * Holds if `(arg, par, ret, out)` forms a subpath-tuple. */ pragma[nomagic] private predicate subpaths03( - PathNode arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout + PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout ) { exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode | subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and @@ -3444,7 +3457,7 @@ private module Subpaths { * a subpath between `par` and `ret` with the connecting edges `arg -> par` and * `ret -> out` is summarized as the edge `arg -> out`. */ - predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) { + predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) { exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 | pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and @@ -3460,7 +3473,7 @@ private module Subpaths { * Holds if `n` can reach a return node in a summarized subpath that can reach a sink. */ predicate retReach(PathNodeImpl n) { - exists(PathNode out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) + exists(PathNodeImpl out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) or exists(PathNodeImpl mid | retReach(mid) and @@ -3477,11 +3490,12 @@ private module Subpaths { * sinks. */ private predicate flowsTo( - PathNode flowsource, PathNodeSink flowsink, Node source, Node sink, Configuration configuration + PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink, + Configuration configuration ) { flowsource.isSource() and flowsource.getConfiguration() = configuration and - flowsource.(PathNodeImpl).getNodeEx().asNode() = source and + flowsource.getNodeEx().asNode() = source and (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and flowsink.getNodeEx().asNode() = sink } @@ -3504,14 +3518,14 @@ private predicate finalStats( fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and - tuples = count(PathNode pn) + tuples = count(PathNodeImpl pn) or fwd = false and nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and - tuples = count(PathNode pn | reach(pn)) + tuples = count(PathNode pn) } /** diff --git a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImpl.qll b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImpl.qll index b5631b26b0bf..8cd1071d084a 100644 --- a/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImpl.qll +++ b/swift/ql/lib/codeql/swift/dataflow/internal/DataFlowImpl.qll @@ -2874,54 +2874,16 @@ private class AccessPathCons1 extends AccessPath, TAccessPathCons1 { } } -/** - * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. - * Only those `PathNode`s that are reachable from a source are generated. - */ -class PathNode extends TPathNode { - /** Gets a textual representation of this element. */ - string toString() { none() } - - /** - * Gets a textual representation of this element, including a textual - * representation of the call context. - */ - string toStringWithContext() { none() } - - /** - * 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/). - */ - predicate hasLocationInfo( - string filepath, int startline, int startcolumn, int endline, int endcolumn - ) { - none() - } - - /** Gets the underlying `Node`. */ - final Node getNode() { this.(PathNodeImpl).getNodeEx().projectToNode() = result } - +abstract private class PathNodeImpl extends TPathNode { /** Gets the `FlowState` of this node. */ - FlowState getState() { none() } + abstract FlowState getState(); /** Gets the associated configuration. */ - Configuration getConfiguration() { none() } - - /** Gets a successor of this node, if any. */ - final PathNode getASuccessor() { - result = this.(PathNodeImpl).getANonHiddenSuccessor() and - reach(this) and - reach(result) - } + abstract Configuration getConfiguration(); /** Holds if this node is a source. */ - predicate isSource() { none() } -} + abstract predicate isSource(); -abstract private class PathNodeImpl extends PathNode { abstract PathNodeImpl getASuccessorImpl(); private PathNodeImpl getASuccessorIfHidden() { @@ -2967,13 +2929,23 @@ abstract private class PathNodeImpl extends PathNode { result = " <" + this.(PathNodeMid).getCallContext().toString() + ">" } - override string toString() { result = this.getNodeEx().toString() + this.ppAp() } + /** Gets a textual representation of this element. */ + string toString() { result = this.getNodeEx().toString() + this.ppAp() } - override string toStringWithContext() { - result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() - } + /** + * Gets a textual representation of this element, including a textual + * representation of the call context. + */ + string toStringWithContext() { result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() } - override predicate hasLocationInfo( + /** + * 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/). + */ + predicate hasLocationInfo( string filepath, int startline, int startcolumn, int endline, int endcolumn ) { this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) @@ -2986,14 +2958,59 @@ private predicate directReach(PathNodeImpl n) { } /** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */ -private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) } +private predicate reach(PathNodeImpl n) { directReach(n) or Subpaths::retReach(n) } /** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */ -private predicate pathSucc(PathNodeImpl n1, PathNode n2) { +private predicate pathSucc(PathNodeImpl n1, PathNodeImpl n2) { n1.getANonHiddenSuccessor() = n2 and directReach(n2) } -private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2) +private predicate pathSuccPlus(PathNodeImpl n1, PathNodeImpl n2) = fastTC(pathSucc/2)(n1, n2) + +/** + * A `Node` augmented with a call context (except for sinks), an access path, and a configuration. + * Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated. + */ +class PathNode instanceof PathNodeImpl { + PathNode() { reach(this) } + + /** Gets a textual representation of this element. */ + final string toString() { result = super.toString() } + + /** + * Gets a textual representation of this element, including a textual + * representation of the call context. + */ + final string toStringWithContext() { result = super.toStringWithContext() } + + /** + * 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/). + */ + final predicate hasLocationInfo( + string filepath, int startline, int startcolumn, int endline, int endcolumn + ) { + super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn) + } + + /** Gets the underlying `Node`. */ + final Node getNode() { super.getNodeEx().projectToNode() = result } + + /** Gets the `FlowState` of this node. */ + final FlowState getState() { result = super.getState() } + + /** Gets the associated configuration. */ + final Configuration getConfiguration() { result = super.getConfiguration() } + + /** Gets a successor of this node, if any. */ + final PathNode getASuccessor() { result = super.getANonHiddenSuccessor() } + + /** Holds if this node is a source. */ + final predicate isSource() { super.isSource() } +} /** * Provides the query predicates needed to include a graph in a path-problem query. @@ -3004,7 +3021,7 @@ module PathGraph { /** Holds if `n` is a node in the graph of data flow path explanations. */ query predicate nodes(PathNode n, string key, string val) { - reach(n) and key = "semmle.label" and val = n.toString() + key = "semmle.label" and val = n.toString() } /** @@ -3013,11 +3030,7 @@ module PathGraph { * `ret -> out` is summarized as the edge `arg -> out`. */ query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) { - Subpaths::subpaths(arg, par, ret, out) and - reach(arg) and - reach(par) and - reach(ret) and - reach(out) + Subpaths::subpaths(arg, par, ret, out) } } @@ -3399,7 +3412,7 @@ private module Subpaths { */ pragma[nomagic] private predicate subpaths02( - PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, + PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, NodeEx out, FlowState sout, AccessPath apout ) { subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and @@ -3407,14 +3420,14 @@ private module Subpaths { } pragma[nomagic] - private Configuration getPathNodeConf(PathNode n) { result = n.getConfiguration() } + private Configuration getPathNodeConf(PathNodeImpl n) { result = n.getConfiguration() } /** * Holds if `(arg, par, ret, out)` forms a subpath-tuple. */ pragma[nomagic] private predicate subpaths03( - PathNode arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout + PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout ) { exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode | subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and @@ -3444,7 +3457,7 @@ private module Subpaths { * a subpath between `par` and `ret` with the connecting edges `arg -> par` and * `ret -> out` is summarized as the edge `arg -> out`. */ - predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) { + predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) { exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 | pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and @@ -3460,7 +3473,7 @@ private module Subpaths { * Holds if `n` can reach a return node in a summarized subpath that can reach a sink. */ predicate retReach(PathNodeImpl n) { - exists(PathNode out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) + exists(PathNodeImpl out | subpaths(_, _, n, out) | directReach(out) or retReach(out)) or exists(PathNodeImpl mid | retReach(mid) and @@ -3477,11 +3490,12 @@ private module Subpaths { * sinks. */ private predicate flowsTo( - PathNode flowsource, PathNodeSink flowsink, Node source, Node sink, Configuration configuration + PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink, + Configuration configuration ) { flowsource.isSource() and flowsource.getConfiguration() = configuration and - flowsource.(PathNodeImpl).getNodeEx().asNode() = source and + flowsource.getNodeEx().asNode() = source and (flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and flowsink.getNodeEx().asNode() = sink } @@ -3504,14 +3518,14 @@ private predicate finalStats( fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and - tuples = count(PathNode pn) + tuples = count(PathNodeImpl pn) or fwd = false and nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and - tuples = count(PathNode pn | reach(pn)) + tuples = count(PathNode pn) } /** From a533c956406ddce067449d3a4a9a1c33595b1633 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Tue, 1 Nov 2022 10:56:31 +0100 Subject: [PATCH 3/4] C++: Update expected test output --- .../InvalidPointerDeref.expected | 128 ------------------ .../SAMATE/TaintedPath/TaintedPath.expected | 3 - .../CWE-022/semmle/tests/TaintedPath.expected | 3 - .../CWE/CWE-079/semmle/CgiXss/CgiXss.expected | 5 - .../CWE-089/SqlTainted/SqlTainted.expected | 5 - .../UncontrolledProcessOperation.expected | 3 - .../UncontrolledProcessOperation.expected | 22 --- .../semmle/tests/UnboundedWrite.expected | 12 -- .../SAMATE/UncontrolledFormatString.expected | 8 -- .../CWE-134/semmle/argv/argvLocal.expected | 64 --------- .../CWE-134/semmle/funcs/funcsLocal.expected | 20 --- .../UncontrolledFormatString.expected | 6 - ...olledFormatStringThroughGlobalVar.expected | 6 - .../CWE/CWE-134/semmle/ifs/ifs.expected | 33 ----- .../CWE-190/SAMATE/ArithmeticTainted.expected | 1 - .../semmle/tainted/ArithmeticTainted.expected | 6 - .../AuthenticationBypass.expected | 6 - .../TaintedCondition.expected | 1 - 18 files changed, 332 deletions(-) diff --git a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-193/pointer-deref/InvalidPointerDeref.expected b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-193/pointer-deref/InvalidPointerDeref.expected index 6f4912b45ade..05069444c19a 100644 --- a/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-193/pointer-deref/InvalidPointerDeref.expected +++ b/cpp/ql/test/experimental/query-tests/Security/CWE/CWE-193/pointer-deref/InvalidPointerDeref.expected @@ -2,43 +2,21 @@ edges | test.cpp:4:15:4:20 | call to malloc | test.cpp:5:15:5:15 | Load | | test.cpp:5:15:5:15 | Load | test.cpp:5:15:5:22 | ... + ... | | test.cpp:5:15:5:15 | Load | test.cpp:5:15:5:22 | ... + ... | -| test.cpp:5:15:5:15 | Load | test.cpp:5:15:5:22 | ... + ... | -| test.cpp:5:15:5:15 | Load | test.cpp:5:15:5:22 | ... + ... | -| test.cpp:5:15:5:15 | Load | test.cpp:5:15:5:22 | Store | -| test.cpp:5:15:5:15 | Load | test.cpp:5:15:5:22 | Store | | test.cpp:5:15:5:15 | Load | test.cpp:5:15:5:22 | Store | | test.cpp:5:15:5:15 | Load | test.cpp:5:15:5:22 | Store | | test.cpp:5:15:5:15 | Load | test.cpp:6:15:6:15 | Load | | test.cpp:5:15:5:15 | Load | test.cpp:6:15:6:15 | Load | -| test.cpp:5:15:5:15 | Load | test.cpp:6:15:6:15 | Load | -| test.cpp:5:15:5:15 | Load | test.cpp:6:15:6:15 | Load | -| test.cpp:5:15:5:15 | Load | test.cpp:7:16:7:16 | Load | -| test.cpp:5:15:5:15 | Load | test.cpp:7:16:7:16 | Load | | test.cpp:5:15:5:15 | Load | test.cpp:7:16:7:16 | Load | | test.cpp:5:15:5:15 | Load | test.cpp:7:16:7:16 | Load | | test.cpp:5:15:5:15 | Load | test.cpp:8:16:8:16 | Load | | test.cpp:5:15:5:15 | Load | test.cpp:8:16:8:16 | Load | -| test.cpp:5:15:5:15 | Load | test.cpp:8:16:8:16 | Load | -| test.cpp:5:15:5:15 | Load | test.cpp:8:16:8:16 | Load | -| test.cpp:5:15:5:15 | Load | test.cpp:8:16:8:20 | ... + ... | -| test.cpp:5:15:5:15 | Load | test.cpp:8:16:8:20 | ... + ... | | test.cpp:5:15:5:15 | Load | test.cpp:8:16:8:20 | ... + ... | -| test.cpp:5:15:5:15 | Load | test.cpp:8:16:8:20 | ... + ... | -| test.cpp:5:15:5:15 | Load | test.cpp:9:16:9:16 | Load | | test.cpp:5:15:5:15 | Load | test.cpp:9:16:9:16 | Load | | test.cpp:5:15:5:15 | Load | test.cpp:9:16:9:16 | Load | -| test.cpp:5:15:5:15 | Load | test.cpp:9:16:9:16 | Load | -| test.cpp:5:15:5:15 | Load | test.cpp:10:16:10:16 | Load | | test.cpp:5:15:5:15 | Load | test.cpp:10:16:10:16 | Load | | test.cpp:5:15:5:15 | Load | test.cpp:10:16:10:16 | Load | -| test.cpp:5:15:5:15 | Load | test.cpp:10:16:10:16 | Load | -| test.cpp:5:15:5:15 | Load | test.cpp:11:16:11:16 | Load | | test.cpp:5:15:5:15 | Load | test.cpp:11:16:11:16 | Load | | test.cpp:5:15:5:15 | Load | test.cpp:11:16:11:16 | Load | -| test.cpp:5:15:5:15 | Load | test.cpp:11:16:11:16 | Load | -| test.cpp:5:15:5:15 | Load | test.cpp:12:16:12:16 | Load | -| test.cpp:5:15:5:15 | Load | test.cpp:12:16:12:16 | Load | -| test.cpp:5:15:5:15 | Load | test.cpp:12:16:12:16 | Load | | test.cpp:5:15:5:15 | Load | test.cpp:12:16:12:16 | Load | | test.cpp:5:15:5:22 | ... + ... | test.cpp:5:15:5:22 | Store | | test.cpp:5:15:5:22 | ... + ... | test.cpp:5:15:5:22 | Store | @@ -116,7 +94,6 @@ edges | test.cpp:8:16:8:16 | Load | test.cpp:11:16:11:16 | Load | | test.cpp:8:16:8:16 | Load | test.cpp:12:16:12:16 | Load | | test.cpp:8:16:8:20 | ... + ... | test.cpp:8:14:8:21 | Load: * ... | -| test.cpp:8:16:8:20 | ... + ... | test.cpp:8:14:8:21 | Load: * ... | | test.cpp:9:16:9:16 | Load | test.cpp:6:14:6:15 | Load: * ... | | test.cpp:9:16:9:16 | Load | test.cpp:6:14:6:15 | Load: * ... | | test.cpp:9:16:9:16 | Load | test.cpp:8:14:8:21 | Load: * ... | @@ -139,63 +116,31 @@ edges | test.cpp:11:16:11:16 | Load | test.cpp:8:14:8:21 | Load: * ... | | test.cpp:11:16:11:16 | Load | test.cpp:12:16:12:16 | Load | | test.cpp:12:16:12:16 | Load | test.cpp:6:14:6:15 | Load: * ... | -| test.cpp:12:16:12:16 | Load | test.cpp:6:14:6:15 | Load: * ... | -| test.cpp:12:16:12:16 | Load | test.cpp:8:14:8:21 | Load: * ... | | test.cpp:12:16:12:16 | Load | test.cpp:8:14:8:21 | Load: * ... | | test.cpp:16:15:16:20 | call to malloc | test.cpp:17:15:17:15 | Load | | test.cpp:17:15:17:15 | Load | test.cpp:17:15:17:22 | ... + ... | -| test.cpp:17:15:17:15 | Load | test.cpp:17:15:17:22 | ... + ... | -| test.cpp:17:15:17:15 | Load | test.cpp:17:15:17:22 | ... + ... | -| test.cpp:17:15:17:15 | Load | test.cpp:17:15:17:22 | ... + ... | | test.cpp:17:15:17:15 | Load | test.cpp:20:16:20:20 | ... + ... | -| test.cpp:17:15:17:15 | Load | test.cpp:20:16:20:20 | ... + ... | -| test.cpp:17:15:17:15 | Load | test.cpp:20:16:20:20 | ... + ... | -| test.cpp:17:15:17:15 | Load | test.cpp:20:16:20:20 | ... + ... | -| test.cpp:17:15:17:22 | ... + ... | test.cpp:20:14:20:21 | Load: * ... | | test.cpp:17:15:17:22 | ... + ... | test.cpp:20:14:20:21 | Load: * ... | | test.cpp:20:16:20:20 | ... + ... | test.cpp:20:14:20:21 | Load: * ... | -| test.cpp:20:16:20:20 | ... + ... | test.cpp:20:14:20:21 | Load: * ... | | test.cpp:28:15:28:20 | call to malloc | test.cpp:29:15:29:15 | Load | | test.cpp:29:15:29:15 | Load | test.cpp:29:15:29:28 | ... + ... | | test.cpp:29:15:29:15 | Load | test.cpp:29:15:29:28 | ... + ... | -| test.cpp:29:15:29:15 | Load | test.cpp:29:15:29:28 | ... + ... | -| test.cpp:29:15:29:15 | Load | test.cpp:29:15:29:28 | ... + ... | -| test.cpp:29:15:29:15 | Load | test.cpp:29:15:29:28 | Store | | test.cpp:29:15:29:15 | Load | test.cpp:29:15:29:28 | Store | | test.cpp:29:15:29:15 | Load | test.cpp:29:15:29:28 | Store | -| test.cpp:29:15:29:15 | Load | test.cpp:29:15:29:28 | Store | -| test.cpp:29:15:29:15 | Load | test.cpp:30:15:30:15 | Load | | test.cpp:29:15:29:15 | Load | test.cpp:30:15:30:15 | Load | | test.cpp:29:15:29:15 | Load | test.cpp:30:15:30:15 | Load | -| test.cpp:29:15:29:15 | Load | test.cpp:30:15:30:15 | Load | -| test.cpp:29:15:29:15 | Load | test.cpp:31:16:31:16 | Load | | test.cpp:29:15:29:15 | Load | test.cpp:31:16:31:16 | Load | | test.cpp:29:15:29:15 | Load | test.cpp:31:16:31:16 | Load | -| test.cpp:29:15:29:15 | Load | test.cpp:31:16:31:16 | Load | -| test.cpp:29:15:29:15 | Load | test.cpp:32:16:32:16 | Load | | test.cpp:29:15:29:15 | Load | test.cpp:32:16:32:16 | Load | | test.cpp:29:15:29:15 | Load | test.cpp:32:16:32:16 | Load | -| test.cpp:29:15:29:15 | Load | test.cpp:32:16:32:16 | Load | -| test.cpp:29:15:29:15 | Load | test.cpp:32:16:32:20 | ... + ... | | test.cpp:29:15:29:15 | Load | test.cpp:32:16:32:20 | ... + ... | -| test.cpp:29:15:29:15 | Load | test.cpp:32:16:32:20 | ... + ... | -| test.cpp:29:15:29:15 | Load | test.cpp:32:16:32:20 | ... + ... | -| test.cpp:29:15:29:15 | Load | test.cpp:33:16:33:16 | Load | -| test.cpp:29:15:29:15 | Load | test.cpp:33:16:33:16 | Load | | test.cpp:29:15:29:15 | Load | test.cpp:33:16:33:16 | Load | | test.cpp:29:15:29:15 | Load | test.cpp:33:16:33:16 | Load | | test.cpp:29:15:29:15 | Load | test.cpp:34:16:34:16 | Load | | test.cpp:29:15:29:15 | Load | test.cpp:34:16:34:16 | Load | -| test.cpp:29:15:29:15 | Load | test.cpp:34:16:34:16 | Load | -| test.cpp:29:15:29:15 | Load | test.cpp:34:16:34:16 | Load | -| test.cpp:29:15:29:15 | Load | test.cpp:35:16:35:16 | Load | -| test.cpp:29:15:29:15 | Load | test.cpp:35:16:35:16 | Load | | test.cpp:29:15:29:15 | Load | test.cpp:35:16:35:16 | Load | | test.cpp:29:15:29:15 | Load | test.cpp:35:16:35:16 | Load | | test.cpp:29:15:29:15 | Load | test.cpp:36:16:36:16 | Load | -| test.cpp:29:15:29:15 | Load | test.cpp:36:16:36:16 | Load | -| test.cpp:29:15:29:15 | Load | test.cpp:36:16:36:16 | Load | -| test.cpp:29:15:29:15 | Load | test.cpp:36:16:36:16 | Load | | test.cpp:29:15:29:28 | ... + ... | test.cpp:29:15:29:28 | Store | | test.cpp:29:15:29:28 | ... + ... | test.cpp:29:15:29:28 | Store | | test.cpp:29:15:29:28 | ... + ... | test.cpp:30:14:30:15 | Load: * ... | @@ -272,7 +217,6 @@ edges | test.cpp:32:16:32:16 | Load | test.cpp:35:16:35:16 | Load | | test.cpp:32:16:32:16 | Load | test.cpp:36:16:36:16 | Load | | test.cpp:32:16:32:20 | ... + ... | test.cpp:32:14:32:21 | Load: * ... | -| test.cpp:32:16:32:20 | ... + ... | test.cpp:32:14:32:21 | Load: * ... | | test.cpp:33:16:33:16 | Load | test.cpp:30:14:30:15 | Load: * ... | | test.cpp:33:16:33:16 | Load | test.cpp:30:14:30:15 | Load: * ... | | test.cpp:33:16:33:16 | Load | test.cpp:32:14:32:21 | Load: * ... | @@ -295,49 +239,25 @@ edges | test.cpp:35:16:35:16 | Load | test.cpp:32:14:32:21 | Load: * ... | | test.cpp:35:16:35:16 | Load | test.cpp:36:16:36:16 | Load | | test.cpp:36:16:36:16 | Load | test.cpp:30:14:30:15 | Load: * ... | -| test.cpp:36:16:36:16 | Load | test.cpp:30:14:30:15 | Load: * ... | -| test.cpp:36:16:36:16 | Load | test.cpp:32:14:32:21 | Load: * ... | | test.cpp:36:16:36:16 | Load | test.cpp:32:14:32:21 | Load: * ... | | test.cpp:40:15:40:20 | call to malloc | test.cpp:41:15:41:15 | Load | | test.cpp:41:15:41:15 | Load | test.cpp:41:15:41:28 | ... + ... | | test.cpp:41:15:41:15 | Load | test.cpp:41:15:41:28 | ... + ... | -| test.cpp:41:15:41:15 | Load | test.cpp:41:15:41:28 | ... + ... | -| test.cpp:41:15:41:15 | Load | test.cpp:41:15:41:28 | ... + ... | | test.cpp:41:15:41:15 | Load | test.cpp:41:15:41:28 | Store | | test.cpp:41:15:41:15 | Load | test.cpp:41:15:41:28 | Store | -| test.cpp:41:15:41:15 | Load | test.cpp:41:15:41:28 | Store | -| test.cpp:41:15:41:15 | Load | test.cpp:41:15:41:28 | Store | -| test.cpp:41:15:41:15 | Load | test.cpp:42:15:42:15 | Load | -| test.cpp:41:15:41:15 | Load | test.cpp:42:15:42:15 | Load | | test.cpp:41:15:41:15 | Load | test.cpp:42:15:42:15 | Load | | test.cpp:41:15:41:15 | Load | test.cpp:42:15:42:15 | Load | | test.cpp:41:15:41:15 | Load | test.cpp:43:16:43:16 | Load | | test.cpp:41:15:41:15 | Load | test.cpp:43:16:43:16 | Load | -| test.cpp:41:15:41:15 | Load | test.cpp:43:16:43:16 | Load | -| test.cpp:41:15:41:15 | Load | test.cpp:43:16:43:16 | Load | -| test.cpp:41:15:41:15 | Load | test.cpp:44:16:44:16 | Load | -| test.cpp:41:15:41:15 | Load | test.cpp:44:16:44:16 | Load | | test.cpp:41:15:41:15 | Load | test.cpp:44:16:44:16 | Load | | test.cpp:41:15:41:15 | Load | test.cpp:44:16:44:16 | Load | | test.cpp:41:15:41:15 | Load | test.cpp:44:16:44:20 | ... + ... | -| test.cpp:41:15:41:15 | Load | test.cpp:44:16:44:20 | ... + ... | -| test.cpp:41:15:41:15 | Load | test.cpp:44:16:44:20 | ... + ... | -| test.cpp:41:15:41:15 | Load | test.cpp:44:16:44:20 | ... + ... | -| test.cpp:41:15:41:15 | Load | test.cpp:45:16:45:16 | Load | | test.cpp:41:15:41:15 | Load | test.cpp:45:16:45:16 | Load | | test.cpp:41:15:41:15 | Load | test.cpp:45:16:45:16 | Load | -| test.cpp:41:15:41:15 | Load | test.cpp:45:16:45:16 | Load | -| test.cpp:41:15:41:15 | Load | test.cpp:46:16:46:16 | Load | | test.cpp:41:15:41:15 | Load | test.cpp:46:16:46:16 | Load | | test.cpp:41:15:41:15 | Load | test.cpp:46:16:46:16 | Load | -| test.cpp:41:15:41:15 | Load | test.cpp:46:16:46:16 | Load | -| test.cpp:41:15:41:15 | Load | test.cpp:47:16:47:16 | Load | | test.cpp:41:15:41:15 | Load | test.cpp:47:16:47:16 | Load | | test.cpp:41:15:41:15 | Load | test.cpp:47:16:47:16 | Load | -| test.cpp:41:15:41:15 | Load | test.cpp:47:16:47:16 | Load | -| test.cpp:41:15:41:15 | Load | test.cpp:48:16:48:16 | Load | -| test.cpp:41:15:41:15 | Load | test.cpp:48:16:48:16 | Load | -| test.cpp:41:15:41:15 | Load | test.cpp:48:16:48:16 | Load | | test.cpp:41:15:41:15 | Load | test.cpp:48:16:48:16 | Load | | test.cpp:41:15:41:28 | ... + ... | test.cpp:41:15:41:28 | Store | | test.cpp:41:15:41:28 | ... + ... | test.cpp:41:15:41:28 | Store | @@ -415,7 +335,6 @@ edges | test.cpp:44:16:44:16 | Load | test.cpp:47:16:47:16 | Load | | test.cpp:44:16:44:16 | Load | test.cpp:48:16:48:16 | Load | | test.cpp:44:16:44:20 | ... + ... | test.cpp:44:14:44:21 | Load: * ... | -| test.cpp:44:16:44:20 | ... + ... | test.cpp:44:14:44:21 | Load: * ... | | test.cpp:45:16:45:16 | Load | test.cpp:42:14:42:15 | Load: * ... | | test.cpp:45:16:45:16 | Load | test.cpp:42:14:42:15 | Load: * ... | | test.cpp:45:16:45:16 | Load | test.cpp:44:14:44:21 | Load: * ... | @@ -438,8 +357,6 @@ edges | test.cpp:47:16:47:16 | Load | test.cpp:44:14:44:21 | Load: * ... | | test.cpp:47:16:47:16 | Load | test.cpp:48:16:48:16 | Load | | test.cpp:48:16:48:16 | Load | test.cpp:42:14:42:15 | Load: * ... | -| test.cpp:48:16:48:16 | Load | test.cpp:42:14:42:15 | Load: * ... | -| test.cpp:48:16:48:16 | Load | test.cpp:44:14:44:21 | Load: * ... | | test.cpp:48:16:48:16 | Load | test.cpp:44:14:44:21 | Load: * ... | | test.cpp:51:7:51:14 | VariableAddress indirection | test.cpp:62:39:62:39 | Load | | test.cpp:51:7:51:14 | VariableAddress indirection | test.cpp:66:39:66:39 | Load | @@ -449,18 +366,13 @@ edges | test.cpp:52:19:52:24 | call to malloc | test.cpp:53:12:53:16 | Load | | test.cpp:53:5:53:23 | Store | test.cpp:51:33:51:35 | Load indirection | | test.cpp:53:12:53:16 | Load | test.cpp:53:5:53:23 | Store | -| test.cpp:53:12:53:16 | Load | test.cpp:53:5:53:23 | Store | -| test.cpp:53:12:53:16 | Load | test.cpp:53:12:53:23 | ... + ... | | test.cpp:53:12:53:16 | Load | test.cpp:53:12:53:23 | ... + ... | | test.cpp:53:12:53:23 | ... + ... | test.cpp:51:33:51:35 | Load indirection | | test.cpp:60:34:60:37 | mk_array output argument | test.cpp:62:32:62:34 | Load | | test.cpp:60:34:60:37 | mk_array output argument | test.cpp:66:32:66:34 | Load | | test.cpp:60:34:60:37 | mk_array output argument | test.cpp:70:31:70:33 | Load | | test.cpp:62:32:62:34 | Load | test.cpp:67:9:67:14 | Store: ... = ... | -| test.cpp:62:32:62:34 | Load | test.cpp:67:9:67:14 | Store: ... = ... | | test.cpp:66:32:66:34 | Load | test.cpp:67:9:67:14 | Store: ... = ... | -| test.cpp:66:32:66:34 | Load | test.cpp:67:9:67:14 | Store: ... = ... | -| test.cpp:70:31:70:33 | Load | test.cpp:67:9:67:14 | Store: ... = ... | | test.cpp:70:31:70:33 | Load | test.cpp:67:9:67:14 | Store: ... = ... | | test.cpp:80:9:80:16 | VariableAddress indirection [begin] | test.cpp:91:20:91:22 | arr indirection [begin] | | test.cpp:80:9:80:16 | VariableAddress indirection [begin] | test.cpp:95:20:95:22 | arr indirection [begin] | @@ -479,8 +391,6 @@ edges | test.cpp:83:15:83:17 | arr indirection [begin] | test.cpp:83:19:83:23 | begin | | test.cpp:83:15:83:30 | ... + ... | test.cpp:83:5:83:30 | Store | | test.cpp:83:19:83:23 | Load | test.cpp:83:5:83:30 | Store | -| test.cpp:83:19:83:23 | Load | test.cpp:83:5:83:30 | Store | -| test.cpp:83:19:83:23 | Load | test.cpp:83:15:83:30 | ... + ... | | test.cpp:83:19:83:23 | Load | test.cpp:83:15:83:30 | ... + ... | | test.cpp:83:19:83:23 | begin | test.cpp:83:19:83:23 | Load | | test.cpp:91:20:91:22 | arr indirection [begin] | test.cpp:91:24:91:28 | begin | @@ -488,21 +398,18 @@ edges | test.cpp:91:24:91:28 | begin | test.cpp:91:47:91:47 | Load | | test.cpp:91:36:91:38 | arr indirection [end] | test.cpp:91:40:91:42 | end | | test.cpp:91:40:91:42 | Load | test.cpp:96:9:96:14 | Store: ... = ... | -| test.cpp:91:40:91:42 | Load | test.cpp:96:9:96:14 | Store: ... = ... | | test.cpp:91:40:91:42 | end | test.cpp:91:40:91:42 | Load | | test.cpp:95:20:95:22 | arr indirection [begin] | test.cpp:95:24:95:28 | begin | | test.cpp:95:20:95:22 | arr indirection [begin] | test.cpp:95:47:95:47 | Load | | test.cpp:95:24:95:28 | begin | test.cpp:95:47:95:47 | Load | | test.cpp:95:36:95:38 | arr indirection [end] | test.cpp:95:40:95:42 | end | | test.cpp:95:40:95:42 | Load | test.cpp:96:9:96:14 | Store: ... = ... | -| test.cpp:95:40:95:42 | Load | test.cpp:96:9:96:14 | Store: ... = ... | | test.cpp:95:40:95:42 | end | test.cpp:95:40:95:42 | Load | | test.cpp:99:20:99:22 | arr indirection [begin] | test.cpp:99:24:99:28 | begin | | test.cpp:99:20:99:22 | arr indirection [begin] | test.cpp:99:46:99:46 | Load | | test.cpp:99:24:99:28 | begin | test.cpp:99:46:99:46 | Load | | test.cpp:99:35:99:37 | arr indirection [end] | test.cpp:99:39:99:41 | end | | test.cpp:99:39:99:41 | Load | test.cpp:96:9:96:14 | Store: ... = ... | -| test.cpp:99:39:99:41 | Load | test.cpp:96:9:96:14 | Store: ... = ... | | test.cpp:99:39:99:41 | end | test.cpp:99:39:99:41 | Load | | test.cpp:104:27:104:29 | arr [begin] | test.cpp:105:20:105:22 | arr indirection [begin] | | test.cpp:104:27:104:29 | arr [begin] | test.cpp:109:20:109:22 | arr indirection [begin] | @@ -515,21 +422,18 @@ edges | test.cpp:105:24:105:28 | begin | test.cpp:105:47:105:47 | Load | | test.cpp:105:36:105:38 | arr indirection [end] | test.cpp:105:40:105:42 | end | | test.cpp:105:40:105:42 | Load | test.cpp:110:9:110:14 | Store: ... = ... | -| test.cpp:105:40:105:42 | Load | test.cpp:110:9:110:14 | Store: ... = ... | | test.cpp:105:40:105:42 | end | test.cpp:105:40:105:42 | Load | | test.cpp:109:20:109:22 | arr indirection [begin] | test.cpp:109:24:109:28 | begin | | test.cpp:109:20:109:22 | arr indirection [begin] | test.cpp:109:47:109:47 | Load | | test.cpp:109:24:109:28 | begin | test.cpp:109:47:109:47 | Load | | test.cpp:109:36:109:38 | arr indirection [end] | test.cpp:109:40:109:42 | end | | test.cpp:109:40:109:42 | Load | test.cpp:110:9:110:14 | Store: ... = ... | -| test.cpp:109:40:109:42 | Load | test.cpp:110:9:110:14 | Store: ... = ... | | test.cpp:109:40:109:42 | end | test.cpp:109:40:109:42 | Load | | test.cpp:113:20:113:22 | arr indirection [begin] | test.cpp:113:24:113:28 | begin | | test.cpp:113:20:113:22 | arr indirection [begin] | test.cpp:113:46:113:46 | Load | | test.cpp:113:24:113:28 | begin | test.cpp:113:46:113:46 | Load | | test.cpp:113:35:113:37 | arr indirection [end] | test.cpp:113:39:113:41 | end | | test.cpp:113:39:113:41 | Load | test.cpp:110:9:110:14 | Store: ... = ... | -| test.cpp:113:39:113:41 | Load | test.cpp:110:9:110:14 | Store: ... = ... | | test.cpp:113:39:113:41 | end | test.cpp:113:39:113:41 | Load | | test.cpp:119:18:119:25 | call to mk_array [begin] | test.cpp:104:27:104:29 | arr [begin] | | test.cpp:119:18:119:25 | call to mk_array [end] | test.cpp:104:27:104:29 | arr [end] | @@ -558,8 +462,6 @@ edges | test.cpp:144:16:144:18 | Load indirection [begin] | test.cpp:144:21:144:25 | begin | | test.cpp:144:16:144:32 | ... + ... | test.cpp:144:5:144:32 | Store | | test.cpp:144:21:144:25 | Load | test.cpp:144:5:144:32 | Store | -| test.cpp:144:21:144:25 | Load | test.cpp:144:5:144:32 | Store | -| test.cpp:144:21:144:25 | Load | test.cpp:144:16:144:32 | ... + ... | | test.cpp:144:21:144:25 | Load | test.cpp:144:16:144:32 | ... + ... | | test.cpp:144:21:144:25 | begin | test.cpp:144:21:144:25 | Load | | test.cpp:150:20:150:29 | Call indirection [begin] | test.cpp:152:20:152:22 | Load indirection [begin] | @@ -574,7 +476,6 @@ edges | test.cpp:156:25:156:29 | begin | test.cpp:156:49:156:49 | Load | | test.cpp:156:37:156:39 | Load indirection [end] | test.cpp:156:42:156:44 | end | | test.cpp:156:42:156:44 | Load | test.cpp:157:9:157:14 | Store: ... = ... | -| test.cpp:156:42:156:44 | Load | test.cpp:157:9:157:14 | Store: ... = ... | | test.cpp:156:42:156:44 | end | test.cpp:156:42:156:44 | Load | | test.cpp:160:20:160:22 | Load indirection [begin] | test.cpp:160:25:160:29 | begin | | test.cpp:160:20:160:22 | Load indirection [begin] | test.cpp:160:48:160:48 | Load | @@ -590,21 +491,18 @@ edges | test.cpp:166:25:166:29 | begin | test.cpp:166:49:166:49 | Load | | test.cpp:166:37:166:39 | Load indirection [end] | test.cpp:166:42:166:44 | end | | test.cpp:166:42:166:44 | Load | test.cpp:171:9:171:14 | Store: ... = ... | -| test.cpp:166:42:166:44 | Load | test.cpp:171:9:171:14 | Store: ... = ... | | test.cpp:166:42:166:44 | end | test.cpp:166:42:166:44 | Load | | test.cpp:170:20:170:22 | Load indirection [begin] | test.cpp:170:25:170:29 | begin | | test.cpp:170:20:170:22 | Load indirection [begin] | test.cpp:170:49:170:49 | Load | | test.cpp:170:25:170:29 | begin | test.cpp:170:49:170:49 | Load | | test.cpp:170:37:170:39 | Load indirection [end] | test.cpp:170:42:170:44 | end | | test.cpp:170:42:170:44 | Load | test.cpp:171:9:171:14 | Store: ... = ... | -| test.cpp:170:42:170:44 | Load | test.cpp:171:9:171:14 | Store: ... = ... | | test.cpp:170:42:170:44 | end | test.cpp:170:42:170:44 | Load | | test.cpp:174:20:174:22 | Load indirection [begin] | test.cpp:174:25:174:29 | begin | | test.cpp:174:20:174:22 | Load indirection [begin] | test.cpp:174:48:174:48 | Load | | test.cpp:174:25:174:29 | begin | test.cpp:174:48:174:48 | Load | | test.cpp:174:36:174:38 | Load indirection [end] | test.cpp:174:41:174:43 | end | | test.cpp:174:41:174:43 | Load | test.cpp:171:9:171:14 | Store: ... = ... | -| test.cpp:174:41:174:43 | Load | test.cpp:171:9:171:14 | Store: ... = ... | | test.cpp:174:41:174:43 | end | test.cpp:174:41:174:43 | Load | | test.cpp:180:19:180:28 | call to mk_array_p indirection [begin] | test.cpp:165:29:165:31 | arr indirection [begin] | | test.cpp:180:19:180:28 | call to mk_array_p indirection [end] | test.cpp:165:29:165:31 | arr indirection [end] | @@ -614,19 +512,9 @@ edges | test.cpp:194:23:194:28 | call to malloc | test.cpp:201:5:201:5 | Load | | test.cpp:195:17:195:17 | Load | test.cpp:195:17:195:23 | ... + ... | | test.cpp:195:17:195:17 | Load | test.cpp:195:17:195:23 | ... + ... | -| test.cpp:195:17:195:17 | Load | test.cpp:195:17:195:23 | ... + ... | -| test.cpp:195:17:195:17 | Load | test.cpp:195:17:195:23 | ... + ... | | test.cpp:195:17:195:17 | Load | test.cpp:195:17:195:23 | Store | | test.cpp:195:17:195:17 | Load | test.cpp:195:17:195:23 | Store | -| test.cpp:195:17:195:17 | Load | test.cpp:195:17:195:23 | Store | -| test.cpp:195:17:195:17 | Load | test.cpp:195:17:195:23 | Store | -| test.cpp:195:17:195:17 | Load | test.cpp:197:20:197:22 | Load | -| test.cpp:195:17:195:17 | Load | test.cpp:197:20:197:22 | Load | | test.cpp:195:17:195:17 | Load | test.cpp:197:20:197:22 | Load | -| test.cpp:195:17:195:17 | Load | test.cpp:197:20:197:22 | Load | -| test.cpp:195:17:195:17 | Load | test.cpp:201:5:201:12 | access to array | -| test.cpp:195:17:195:17 | Load | test.cpp:201:5:201:12 | access to array | -| test.cpp:195:17:195:17 | Load | test.cpp:201:5:201:12 | access to array | | test.cpp:195:17:195:17 | Load | test.cpp:201:5:201:12 | access to array | | test.cpp:195:17:195:23 | ... + ... | test.cpp:195:17:195:23 | Store | | test.cpp:195:17:195:23 | ... + ... | test.cpp:195:17:195:23 | Store | @@ -637,31 +525,17 @@ edges | test.cpp:195:17:195:23 | Store | test.cpp:201:5:201:19 | Store: ... = ... | | test.cpp:195:17:195:23 | Store | test.cpp:201:5:201:19 | Store: ... = ... | | test.cpp:197:20:197:22 | Load | test.cpp:201:5:201:19 | Store: ... = ... | -| test.cpp:197:20:197:22 | Load | test.cpp:201:5:201:19 | Store: ... = ... | -| test.cpp:201:5:201:12 | access to array | test.cpp:201:5:201:19 | Store: ... = ... | | test.cpp:201:5:201:12 | access to array | test.cpp:201:5:201:19 | Store: ... = ... | | test.cpp:205:23:205:28 | call to malloc | test.cpp:206:17:206:17 | Load | | test.cpp:205:23:205:28 | call to malloc | test.cpp:208:15:208:15 | Load | | test.cpp:206:17:206:17 | Load | test.cpp:206:17:206:23 | ... + ... | | test.cpp:206:17:206:17 | Load | test.cpp:206:17:206:23 | ... + ... | -| test.cpp:206:17:206:17 | Load | test.cpp:206:17:206:23 | ... + ... | -| test.cpp:206:17:206:17 | Load | test.cpp:206:17:206:23 | ... + ... | | test.cpp:206:17:206:17 | Load | test.cpp:206:17:206:23 | Store | | test.cpp:206:17:206:17 | Load | test.cpp:206:17:206:23 | Store | -| test.cpp:206:17:206:17 | Load | test.cpp:206:17:206:23 | Store | -| test.cpp:206:17:206:17 | Load | test.cpp:206:17:206:23 | Store | -| test.cpp:206:17:206:17 | Load | test.cpp:209:12:209:14 | Load | -| test.cpp:206:17:206:17 | Load | test.cpp:209:12:209:14 | Load | | test.cpp:206:17:206:17 | Load | test.cpp:209:12:209:14 | Load | -| test.cpp:206:17:206:17 | Load | test.cpp:209:12:209:14 | Load | -| test.cpp:206:17:206:17 | Load | test.cpp:213:5:213:6 | * ... | -| test.cpp:206:17:206:17 | Load | test.cpp:213:5:213:6 | * ... | -| test.cpp:206:17:206:17 | Load | test.cpp:213:5:213:6 | * ... | | test.cpp:206:17:206:17 | Load | test.cpp:213:5:213:6 | * ... | | test.cpp:206:17:206:17 | Load | test.cpp:213:6:213:6 | Load | | test.cpp:206:17:206:17 | Load | test.cpp:213:6:213:6 | Load | -| test.cpp:206:17:206:17 | Load | test.cpp:213:6:213:6 | Load | -| test.cpp:206:17:206:17 | Load | test.cpp:213:6:213:6 | Load | | test.cpp:206:17:206:23 | ... + ... | test.cpp:206:17:206:23 | Store | | test.cpp:206:17:206:23 | ... + ... | test.cpp:206:17:206:23 | Store | | test.cpp:206:17:206:23 | ... + ... | test.cpp:209:12:209:14 | Load | @@ -671,8 +545,6 @@ edges | test.cpp:206:17:206:23 | Store | test.cpp:213:5:213:13 | Store: ... = ... | | test.cpp:206:17:206:23 | Store | test.cpp:213:5:213:13 | Store: ... = ... | | test.cpp:209:12:209:14 | Load | test.cpp:213:5:213:13 | Store: ... = ... | -| test.cpp:209:12:209:14 | Load | test.cpp:213:5:213:13 | Store: ... = ... | -| test.cpp:213:5:213:6 | * ... | test.cpp:213:5:213:13 | Store: ... = ... | | test.cpp:213:5:213:6 | * ... | test.cpp:213:5:213:13 | Store: ... = ... | | test.cpp:213:6:213:6 | Load | test.cpp:213:5:213:6 | * ... | | test.cpp:213:6:213:6 | Load | test.cpp:213:5:213:13 | Store: ... = ... | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-022/SAMATE/TaintedPath/TaintedPath.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-022/SAMATE/TaintedPath/TaintedPath.expected index 08b6cbbcc8d3..28d9a9c82e8c 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-022/SAMATE/TaintedPath/TaintedPath.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-022/SAMATE/TaintedPath/TaintedPath.expected @@ -12,11 +12,8 @@ nodes | CWE23_Relative_Path_Traversal__char_console_fopen_11.cpp:55:27:55:38 | ... + ... | semmle.label | ... + ... | | CWE23_Relative_Path_Traversal__char_console_fopen_11.cpp:55:27:55:38 | fgets output argument | semmle.label | fgets output argument | | CWE23_Relative_Path_Traversal__char_console_fopen_11.cpp:77:23:77:26 | (const char *)... | semmle.label | (const char *)... | -| CWE23_Relative_Path_Traversal__char_console_fopen_11.cpp:77:23:77:26 | (const char *)... | semmle.label | (const char *)... | -| CWE23_Relative_Path_Traversal__char_console_fopen_11.cpp:77:23:77:26 | data | semmle.label | data | | CWE23_Relative_Path_Traversal__char_console_fopen_11.cpp:77:23:77:26 | data | semmle.label | data | | CWE23_Relative_Path_Traversal__char_console_fopen_11.cpp:77:23:77:26 | data | semmle.label | data | | CWE23_Relative_Path_Traversal__char_console_fopen_11.cpp:77:23:77:26 | data indirection | semmle.label | data indirection | -| CWE23_Relative_Path_Traversal__char_console_fopen_11.cpp:77:23:77:26 | data indirection | semmle.label | data indirection | #select | CWE23_Relative_Path_Traversal__char_console_fopen_11.cpp:77:23:77:26 | data | CWE23_Relative_Path_Traversal__char_console_fopen_11.cpp:55:27:55:38 | ... + ... | CWE23_Relative_Path_Traversal__char_console_fopen_11.cpp:77:23:77:26 | data | This argument to a file access function is derived from $@ and then passed to fopen(filename). | CWE23_Relative_Path_Traversal__char_console_fopen_11.cpp:55:27:55:38 | ... + ... | user input (fgets) | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-022/semmle/tests/TaintedPath.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-022/semmle/tests/TaintedPath.expected index 42ce35c90e73..51cfc800db68 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-022/semmle/tests/TaintedPath.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-022/semmle/tests/TaintedPath.expected @@ -12,11 +12,8 @@ nodes | test.c:9:23:9:26 | argv | semmle.label | argv | | test.c:9:23:9:26 | argv | semmle.label | argv | | test.c:17:11:17:18 | (const char *)... | semmle.label | (const char *)... | -| test.c:17:11:17:18 | (const char *)... | semmle.label | (const char *)... | -| test.c:17:11:17:18 | fileName | semmle.label | fileName | | test.c:17:11:17:18 | fileName | semmle.label | fileName | | test.c:17:11:17:18 | fileName | semmle.label | fileName | | test.c:17:11:17:18 | fileName indirection | semmle.label | fileName indirection | -| test.c:17:11:17:18 | fileName indirection | semmle.label | fileName indirection | #select | test.c:17:11:17:18 | fileName | test.c:9:23:9:26 | argv | test.c:17:11:17:18 | fileName | This argument to a file access function is derived from $@ and then passed to fopen(filename). | test.c:9:23:9:26 | argv | user input (argv) | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-079/semmle/CgiXss/CgiXss.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-079/semmle/CgiXss/CgiXss.expected index 76a02feb6c94..54caba5b5217 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-079/semmle/CgiXss/CgiXss.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-079/semmle/CgiXss/CgiXss.expected @@ -29,18 +29,13 @@ nodes | search.c:14:24:14:28 | *query | semmle.label | *query | | search.c:14:24:14:28 | query | semmle.label | query | | search.c:17:8:17:12 | (const char *)... | semmle.label | (const char *)... | -| search.c:17:8:17:12 | (const char *)... | semmle.label | (const char *)... | -| search.c:17:8:17:12 | query | semmle.label | query | | search.c:17:8:17:12 | query | semmle.label | query | | search.c:17:8:17:12 | query | semmle.label | query | | search.c:17:8:17:12 | query indirection | semmle.label | query indirection | -| search.c:17:8:17:12 | query indirection | semmle.label | query indirection | | search.c:22:24:22:28 | *query | semmle.label | *query | | search.c:22:24:22:28 | query | semmle.label | query | | search.c:23:39:23:43 | query | semmle.label | query | | search.c:23:39:23:43 | query | semmle.label | query | -| search.c:23:39:23:43 | query | semmle.label | query | -| search.c:23:39:23:43 | query indirection | semmle.label | query indirection | | search.c:23:39:23:43 | query indirection | semmle.label | query indirection | | search.c:51:21:51:26 | call to getenv | semmle.label | call to getenv | | search.c:51:21:51:26 | call to getenv | semmle.label | call to getenv | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-089/SqlTainted/SqlTainted.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-089/SqlTainted/SqlTainted.expected index 8f53392ded25..369abfe39f3c 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-089/SqlTainted/SqlTainted.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-089/SqlTainted/SqlTainted.expected @@ -18,18 +18,13 @@ nodes | test.c:15:20:15:23 | argv | semmle.label | argv | | test.c:15:20:15:23 | argv | semmle.label | argv | | test.c:21:18:21:23 | (const char *)... | semmle.label | (const char *)... | -| test.c:21:18:21:23 | (const char *)... | semmle.label | (const char *)... | | test.c:21:18:21:23 | query1 | semmle.label | query1 | | test.c:21:18:21:23 | query1 indirection | semmle.label | query1 indirection | -| test.c:21:18:21:23 | query1 indirection | semmle.label | query1 indirection | | test.cpp:43:27:43:30 | argv | semmle.label | argv | | test.cpp:43:27:43:30 | argv | semmle.label | argv | | test.cpp:43:27:43:33 | (const char *)... | semmle.label | (const char *)... | -| test.cpp:43:27:43:33 | (const char *)... | semmle.label | (const char *)... | | test.cpp:43:27:43:33 | access to array | semmle.label | access to array | | test.cpp:43:27:43:33 | access to array | semmle.label | access to array | -| test.cpp:43:27:43:33 | access to array | semmle.label | access to array | -| test.cpp:43:27:43:33 | access to array indirection | semmle.label | access to array indirection | | test.cpp:43:27:43:33 | access to array indirection | semmle.label | access to array indirection | #select | test.c:21:18:21:23 | query1 | test.c:15:20:15:23 | argv | test.c:21:18:21:23 | query1 | This argument to a SQL query function is derived from $@ and then passed to mysql_query(sqlArg). | test.c:15:20:15:23 | argv | user input (argv) | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-114/SAMATE/UncontrolledProcessOperation/UncontrolledProcessOperation.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-114/SAMATE/UncontrolledProcessOperation/UncontrolledProcessOperation.expected index a5f823b9cccb..e940d554fa9c 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-114/SAMATE/UncontrolledProcessOperation/UncontrolledProcessOperation.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-114/SAMATE/UncontrolledProcessOperation/UncontrolledProcessOperation.expected @@ -17,12 +17,9 @@ nodes | test.cpp:37:73:37:76 | *data | semmle.label | *data | | test.cpp:37:73:37:76 | data | semmle.label | data | | test.cpp:43:32:43:35 | (LPCSTR)... | semmle.label | (LPCSTR)... | -| test.cpp:43:32:43:35 | (LPCSTR)... | semmle.label | (LPCSTR)... | -| test.cpp:43:32:43:35 | data | semmle.label | data | | test.cpp:43:32:43:35 | data | semmle.label | data | | test.cpp:43:32:43:35 | data | semmle.label | data | | test.cpp:43:32:43:35 | data indirection | semmle.label | data indirection | -| test.cpp:43:32:43:35 | data indirection | semmle.label | data indirection | | test.cpp:64:30:64:35 | call to getenv | semmle.label | call to getenv | | test.cpp:64:30:64:35 | call to getenv | semmle.label | call to getenv | | test.cpp:73:24:73:27 | data | semmle.label | data | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-114/semmle/UncontrolledProcessOperation/UncontrolledProcessOperation.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-114/semmle/UncontrolledProcessOperation/UncontrolledProcessOperation.expected index db65ba73477f..3e371efddd59 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-114/semmle/UncontrolledProcessOperation/UncontrolledProcessOperation.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-114/semmle/UncontrolledProcessOperation/UncontrolledProcessOperation.expected @@ -79,15 +79,11 @@ nodes | test.cpp:24:30:24:36 | command | semmle.label | command | | test.cpp:26:10:26:16 | command | semmle.label | command | | test.cpp:26:10:26:16 | command | semmle.label | command | -| test.cpp:26:10:26:16 | command | semmle.label | command | -| test.cpp:26:10:26:16 | command indirection | semmle.label | command indirection | | test.cpp:26:10:26:16 | command indirection | semmle.label | command indirection | | test.cpp:29:30:29:36 | *command | semmle.label | *command | | test.cpp:29:30:29:36 | command | semmle.label | command | | test.cpp:31:10:31:16 | command | semmle.label | command | | test.cpp:31:10:31:16 | command | semmle.label | command | -| test.cpp:31:10:31:16 | command | semmle.label | command | -| test.cpp:31:10:31:16 | command indirection | semmle.label | command indirection | | test.cpp:31:10:31:16 | command indirection | semmle.label | command indirection | | test.cpp:42:18:42:23 | call to getenv | semmle.label | call to getenv | | test.cpp:42:18:42:34 | (const char *)... | semmle.label | (const char *)... | @@ -100,54 +96,36 @@ nodes | test.cpp:56:12:56:17 | buffer | semmle.label | buffer | | test.cpp:56:12:56:17 | fgets output argument | semmle.label | fgets output argument | | test.cpp:62:10:62:15 | (const char *)... | semmle.label | (const char *)... | -| test.cpp:62:10:62:15 | (const char *)... | semmle.label | (const char *)... | | test.cpp:62:10:62:15 | buffer | semmle.label | buffer | | test.cpp:62:10:62:15 | buffer indirection | semmle.label | buffer indirection | -| test.cpp:62:10:62:15 | buffer indirection | semmle.label | buffer indirection | | test.cpp:63:10:63:13 | (const char *)... | semmle.label | (const char *)... | -| test.cpp:63:10:63:13 | (const char *)... | semmle.label | (const char *)... | -| test.cpp:63:10:63:13 | data | semmle.label | data | | test.cpp:63:10:63:13 | data | semmle.label | data | | test.cpp:63:10:63:13 | data | semmle.label | data | | test.cpp:63:10:63:13 | data indirection | semmle.label | data indirection | -| test.cpp:63:10:63:13 | data indirection | semmle.label | data indirection | | test.cpp:64:10:64:16 | (const char *)... | semmle.label | (const char *)... | -| test.cpp:64:10:64:16 | (const char *)... | semmle.label | (const char *)... | -| test.cpp:64:10:64:16 | (reference dereference) | semmle.label | (reference dereference) | | test.cpp:64:10:64:16 | (reference dereference) | semmle.label | (reference dereference) | | test.cpp:64:10:64:16 | dataref | semmle.label | dataref | | test.cpp:64:10:64:16 | dataref | semmle.label | dataref | -| test.cpp:64:10:64:16 | dataref | semmle.label | dataref | -| test.cpp:64:10:64:16 | dataref indirection | semmle.label | dataref indirection | | test.cpp:64:10:64:16 | dataref indirection | semmle.label | dataref indirection | | test.cpp:65:10:65:14 | (const char *)... | semmle.label | (const char *)... | -| test.cpp:65:10:65:14 | (const char *)... | semmle.label | (const char *)... | | test.cpp:65:10:65:14 | data2 | semmle.label | data2 | | test.cpp:65:10:65:14 | data2 | semmle.label | data2 | -| test.cpp:65:10:65:14 | data2 | semmle.label | data2 | -| test.cpp:65:10:65:14 | data2 indirection | semmle.label | data2 indirection | | test.cpp:65:10:65:14 | data2 indirection | semmle.label | data2 indirection | | test.cpp:76:12:76:17 | buffer | semmle.label | buffer | | test.cpp:76:12:76:17 | fgets output argument | semmle.label | fgets output argument | | test.cpp:78:10:78:15 | (const char *)... | semmle.label | (const char *)... | -| test.cpp:78:10:78:15 | (const char *)... | semmle.label | (const char *)... | | test.cpp:78:10:78:15 | buffer | semmle.label | buffer | | test.cpp:78:10:78:15 | buffer indirection | semmle.label | buffer indirection | -| test.cpp:78:10:78:15 | buffer indirection | semmle.label | buffer indirection | | test.cpp:98:17:98:22 | buffer | semmle.label | buffer | | test.cpp:98:17:98:22 | recv output argument | semmle.label | recv output argument | | test.cpp:99:15:99:20 | (const char *)... | semmle.label | (const char *)... | -| test.cpp:99:15:99:20 | (const char *)... | semmle.label | (const char *)... | | test.cpp:99:15:99:20 | buffer | semmle.label | buffer | | test.cpp:99:15:99:20 | buffer indirection | semmle.label | buffer indirection | -| test.cpp:99:15:99:20 | buffer indirection | semmle.label | buffer indirection | | test.cpp:106:17:106:22 | buffer | semmle.label | buffer | | test.cpp:106:17:106:22 | recv output argument | semmle.label | recv output argument | | test.cpp:107:15:107:20 | (const char *)... | semmle.label | (const char *)... | -| test.cpp:107:15:107:20 | (const char *)... | semmle.label | (const char *)... | | test.cpp:107:15:107:20 | buffer | semmle.label | buffer | | test.cpp:107:15:107:20 | buffer indirection | semmle.label | buffer indirection | -| test.cpp:107:15:107:20 | buffer indirection | semmle.label | buffer indirection | #select | test.cpp:26:10:26:16 | command | test.cpp:42:18:42:23 | call to getenv | test.cpp:26:10:26:16 | command | The value of this argument may come from $@ and is being passed to system. | test.cpp:42:18:42:23 | call to getenv | call to getenv | | test.cpp:31:10:31:16 | command | test.cpp:43:18:43:23 | call to getenv | test.cpp:31:10:31:16 | command | The value of this argument may come from $@ and is being passed to system. | test.cpp:43:18:43:23 | call to getenv | call to getenv | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-120/semmle/tests/UnboundedWrite.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-120/semmle/tests/UnboundedWrite.expected index 53344b776af5..2c3e9243cf10 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-120/semmle/tests/UnboundedWrite.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-120/semmle/tests/UnboundedWrite.expected @@ -56,43 +56,31 @@ nodes | tests.c:28:22:28:25 | argv | semmle.label | argv | | tests.c:28:22:28:25 | argv | semmle.label | argv | | tests.c:28:22:28:28 | (const char *)... | semmle.label | (const char *)... | -| tests.c:28:22:28:28 | (const char *)... | semmle.label | (const char *)... | -| tests.c:28:22:28:28 | access to array | semmle.label | access to array | | tests.c:28:22:28:28 | access to array | semmle.label | access to array | | tests.c:28:22:28:28 | access to array | semmle.label | access to array | | tests.c:28:22:28:28 | access to array indirection | semmle.label | access to array indirection | -| tests.c:28:22:28:28 | access to array indirection | semmle.label | access to array indirection | | tests.c:29:28:29:31 | argv | semmle.label | argv | | tests.c:29:28:29:31 | argv | semmle.label | argv | | tests.c:29:28:29:34 | access to array | semmle.label | access to array | | tests.c:29:28:29:34 | access to array | semmle.label | access to array | -| tests.c:29:28:29:34 | access to array | semmle.label | access to array | -| tests.c:29:28:29:34 | access to array indirection | semmle.label | access to array indirection | | tests.c:29:28:29:34 | access to array indirection | semmle.label | access to array indirection | | tests.c:31:15:31:23 | array to pointer conversion | semmle.label | array to pointer conversion | | tests.c:31:15:31:23 | array to pointer conversion | semmle.label | array to pointer conversion | | tests.c:31:15:31:23 | buffer100 | semmle.label | buffer100 | | tests.c:31:15:31:23 | buffer100 | semmle.label | buffer100 | -| tests.c:31:15:31:23 | buffer100 | semmle.label | buffer100 | -| tests.c:31:15:31:23 | buffer100 indirection | semmle.label | buffer100 indirection | | tests.c:31:15:31:23 | buffer100 indirection | semmle.label | buffer100 indirection | | tests.c:31:15:31:23 | scanf output argument | semmle.label | scanf output argument | | tests.c:33:21:33:29 | array to pointer conversion | semmle.label | array to pointer conversion | | tests.c:33:21:33:29 | array to pointer conversion | semmle.label | array to pointer conversion | | tests.c:33:21:33:29 | buffer100 | semmle.label | buffer100 | | tests.c:33:21:33:29 | buffer100 | semmle.label | buffer100 | -| tests.c:33:21:33:29 | buffer100 | semmle.label | buffer100 | -| tests.c:33:21:33:29 | buffer100 indirection | semmle.label | buffer100 indirection | | tests.c:33:21:33:29 | buffer100 indirection | semmle.label | buffer100 indirection | | tests.c:34:10:34:13 | argv | semmle.label | argv | | tests.c:34:10:34:13 | argv | semmle.label | argv | | tests.c:34:10:34:16 | (const char *)... | semmle.label | (const char *)... | -| tests.c:34:10:34:16 | (const char *)... | semmle.label | (const char *)... | -| tests.c:34:10:34:16 | access to array | semmle.label | access to array | | tests.c:34:10:34:16 | access to array | semmle.label | access to array | | tests.c:34:10:34:16 | access to array | semmle.label | access to array | | tests.c:34:10:34:16 | access to array indirection | semmle.label | access to array indirection | -| tests.c:34:10:34:16 | access to array indirection | semmle.label | access to array indirection | #select | tests.c:28:3:28:9 | call to sprintf | tests.c:28:22:28:25 | argv | tests.c:28:22:28:28 | access to array | This 'call to sprintf' with input from $@ may overflow the destination. | tests.c:28:22:28:25 | argv | argv | | tests.c:29:3:29:9 | call to sprintf | tests.c:29:28:29:31 | argv | tests.c:29:28:29:34 | access to array | This 'call to sprintf' with input from $@ may overflow the destination. | tests.c:29:28:29:31 | argv | argv | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-134/SAMATE/UncontrolledFormatString.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-134/SAMATE/UncontrolledFormatString.expected index f68462862260..aa09038581e4 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-134/SAMATE/UncontrolledFormatString.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-134/SAMATE/UncontrolledFormatString.expected @@ -27,26 +27,18 @@ nodes | char_connect_socket_w32_vsnprintf_01_bad.c:94:55:94:68 | ... + ... | semmle.label | ... + ... | | char_connect_socket_w32_vsnprintf_01_bad.c:125:15:125:18 | data | semmle.label | data | | char_connect_socket_w32_vsnprintf_01_bad.c:125:15:125:18 | data | semmle.label | data | -| char_connect_socket_w32_vsnprintf_01_bad.c:125:15:125:18 | data | semmle.label | data | -| char_connect_socket_w32_vsnprintf_01_bad.c:125:15:125:18 | data indirection | semmle.label | data indirection | | char_connect_socket_w32_vsnprintf_01_bad.c:125:15:125:18 | data indirection | semmle.label | data indirection | | char_console_fprintf_01_bad.c:30:23:30:35 | ... + ... | semmle.label | ... + ... | | char_console_fprintf_01_bad.c:30:23:30:35 | fgets output argument | semmle.label | fgets output argument | | char_console_fprintf_01_bad.c:49:21:49:24 | (const char *)... | semmle.label | (const char *)... | -| char_console_fprintf_01_bad.c:49:21:49:24 | (const char *)... | semmle.label | (const char *)... | -| char_console_fprintf_01_bad.c:49:21:49:24 | data | semmle.label | data | | char_console_fprintf_01_bad.c:49:21:49:24 | data | semmle.label | data | | char_console_fprintf_01_bad.c:49:21:49:24 | data | semmle.label | data | | char_console_fprintf_01_bad.c:49:21:49:24 | data indirection | semmle.label | data indirection | -| char_console_fprintf_01_bad.c:49:21:49:24 | data indirection | semmle.label | data indirection | | char_environment_fprintf_01_bad.c:27:30:27:35 | call to getenv | semmle.label | call to getenv | | char_environment_fprintf_01_bad.c:27:30:27:35 | call to getenv | semmle.label | call to getenv | | char_environment_fprintf_01_bad.c:36:21:36:24 | (const char *)... | semmle.label | (const char *)... | -| char_environment_fprintf_01_bad.c:36:21:36:24 | (const char *)... | semmle.label | (const char *)... | | char_environment_fprintf_01_bad.c:36:21:36:24 | data | semmle.label | data | | char_environment_fprintf_01_bad.c:36:21:36:24 | data | semmle.label | data | -| char_environment_fprintf_01_bad.c:36:21:36:24 | data | semmle.label | data | -| char_environment_fprintf_01_bad.c:36:21:36:24 | data indirection | semmle.label | data indirection | | char_environment_fprintf_01_bad.c:36:21:36:24 | data indirection | semmle.label | data indirection | #select | char_connect_socket_w32_vsnprintf_01_bad.c:125:15:125:18 | data | char_connect_socket_w32_vsnprintf_01_bad.c:94:55:94:68 | ... + ... | char_connect_socket_w32_vsnprintf_01_bad.c:125:15:125:18 | data | The value of this argument may come from $@ and is being used as a formatting argument to badVaSink(data), which calls vsnprintf(format). | char_connect_socket_w32_vsnprintf_01_bad.c:94:55:94:68 | ... + ... | recv | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/argv/argvLocal.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/argv/argvLocal.expected index 9dcad8009a8b..84d1f56fab5e 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/argv/argvLocal.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/argv/argvLocal.expected @@ -272,192 +272,128 @@ nodes | argvLocal.c:95:9:95:12 | argv | semmle.label | argv | | argvLocal.c:95:9:95:12 | argv | semmle.label | argv | | argvLocal.c:95:9:95:15 | (const char *)... | semmle.label | (const char *)... | -| argvLocal.c:95:9:95:15 | (const char *)... | semmle.label | (const char *)... | -| argvLocal.c:95:9:95:15 | access to array | semmle.label | access to array | | argvLocal.c:95:9:95:15 | access to array | semmle.label | access to array | | argvLocal.c:95:9:95:15 | access to array | semmle.label | access to array | | argvLocal.c:95:9:95:15 | access to array indirection | semmle.label | access to array indirection | -| argvLocal.c:95:9:95:15 | access to array indirection | semmle.label | access to array indirection | | argvLocal.c:96:15:96:18 | argv | semmle.label | argv | | argvLocal.c:96:15:96:18 | argv | semmle.label | argv | | argvLocal.c:96:15:96:21 | access to array | semmle.label | access to array | | argvLocal.c:96:15:96:21 | access to array | semmle.label | access to array | -| argvLocal.c:96:15:96:21 | access to array | semmle.label | access to array | -| argvLocal.c:96:15:96:21 | access to array indirection | semmle.label | access to array indirection | | argvLocal.c:96:15:96:21 | access to array indirection | semmle.label | access to array indirection | | argvLocal.c:100:7:100:10 | argv | semmle.label | argv | | argvLocal.c:100:7:100:10 | argv | semmle.label | argv | | argvLocal.c:101:9:101:10 | (const char *)... | semmle.label | (const char *)... | -| argvLocal.c:101:9:101:10 | (const char *)... | semmle.label | (const char *)... | | argvLocal.c:101:9:101:10 | i1 | semmle.label | i1 | | argvLocal.c:101:9:101:10 | i1 | semmle.label | i1 | -| argvLocal.c:101:9:101:10 | i1 | semmle.label | i1 | -| argvLocal.c:101:9:101:10 | i1 indirection | semmle.label | i1 indirection | | argvLocal.c:101:9:101:10 | i1 indirection | semmle.label | i1 indirection | | argvLocal.c:102:15:102:16 | i1 | semmle.label | i1 | | argvLocal.c:102:15:102:16 | i1 | semmle.label | i1 | -| argvLocal.c:102:15:102:16 | i1 | semmle.label | i1 | | argvLocal.c:102:15:102:16 | i1 indirection | semmle.label | i1 indirection | | argvLocal.c:102:15:102:16 | i1 indirection | semmle.label | i1 indirection | | argvLocal.c:102:15:102:16 | printWrapper output argument | semmle.label | printWrapper output argument | | argvLocal.c:105:14:105:17 | argv | semmle.label | argv | | argvLocal.c:105:14:105:17 | argv | semmle.label | argv | | argvLocal.c:106:9:106:13 | (const char *)... | semmle.label | (const char *)... | -| argvLocal.c:106:9:106:13 | (const char *)... | semmle.label | (const char *)... | | argvLocal.c:106:9:106:13 | access to array | semmle.label | access to array | | argvLocal.c:106:9:106:13 | access to array | semmle.label | access to array | -| argvLocal.c:106:9:106:13 | access to array | semmle.label | access to array | -| argvLocal.c:106:9:106:13 | access to array indirection | semmle.label | access to array indirection | | argvLocal.c:106:9:106:13 | access to array indirection | semmle.label | access to array indirection | | argvLocal.c:107:15:107:19 | access to array | semmle.label | access to array | | argvLocal.c:107:15:107:19 | access to array | semmle.label | access to array | -| argvLocal.c:107:15:107:19 | access to array | semmle.label | access to array | | argvLocal.c:107:15:107:19 | access to array indirection | semmle.label | access to array indirection | | argvLocal.c:107:15:107:19 | access to array indirection | semmle.label | access to array indirection | | argvLocal.c:107:15:107:19 | printWrapper output argument | semmle.label | printWrapper output argument | | argvLocal.c:110:9:110:11 | (const char *)... | semmle.label | (const char *)... | -| argvLocal.c:110:9:110:11 | (const char *)... | semmle.label | (const char *)... | | argvLocal.c:110:9:110:11 | * ... | semmle.label | * ... | | argvLocal.c:110:9:110:11 | * ... | semmle.label | * ... | -| argvLocal.c:110:9:110:11 | * ... | semmle.label | * ... | -| argvLocal.c:110:9:110:11 | * ... indirection | semmle.label | * ... indirection | | argvLocal.c:110:9:110:11 | * ... indirection | semmle.label | * ... indirection | | argvLocal.c:111:15:111:17 | * ... | semmle.label | * ... | | argvLocal.c:111:15:111:17 | * ... | semmle.label | * ... | -| argvLocal.c:111:15:111:17 | * ... | semmle.label | * ... | -| argvLocal.c:111:15:111:17 | * ... indirection | semmle.label | * ... indirection | | argvLocal.c:111:15:111:17 | * ... indirection | semmle.label | * ... indirection | | argvLocal.c:115:13:115:16 | argv | semmle.label | argv | | argvLocal.c:115:13:115:16 | argv | semmle.label | argv | | argvLocal.c:116:9:116:10 | (const char *)... | semmle.label | (const char *)... | -| argvLocal.c:116:9:116:10 | (const char *)... | semmle.label | (const char *)... | | argvLocal.c:116:9:116:10 | i3 | semmle.label | i3 | | argvLocal.c:116:9:116:10 | i3 indirection | semmle.label | i3 indirection | -| argvLocal.c:116:9:116:10 | i3 indirection | semmle.label | i3 indirection | -| argvLocal.c:117:15:117:16 | array to pointer conversion | semmle.label | array to pointer conversion | | argvLocal.c:117:15:117:16 | array to pointer conversion | semmle.label | array to pointer conversion | | argvLocal.c:117:15:117:16 | i3 | semmle.label | i3 | | argvLocal.c:117:15:117:16 | i3 indirection | semmle.label | i3 indirection | | argvLocal.c:117:15:117:16 | i3 indirection | semmle.label | i3 indirection | | argvLocal.c:117:15:117:16 | printWrapper output argument | semmle.label | printWrapper output argument | | argvLocal.c:121:9:121:10 | (const char *)... | semmle.label | (const char *)... | -| argvLocal.c:121:9:121:10 | (const char *)... | semmle.label | (const char *)... | | argvLocal.c:121:9:121:10 | i4 | semmle.label | i4 | | argvLocal.c:121:9:121:10 | i4 | semmle.label | i4 | -| argvLocal.c:121:9:121:10 | i4 | semmle.label | i4 | -| argvLocal.c:121:9:121:10 | i4 indirection | semmle.label | i4 indirection | | argvLocal.c:121:9:121:10 | i4 indirection | semmle.label | i4 indirection | | argvLocal.c:122:15:122:16 | i4 | semmle.label | i4 | | argvLocal.c:122:15:122:16 | i4 | semmle.label | i4 | -| argvLocal.c:122:15:122:16 | i4 | semmle.label | i4 | | argvLocal.c:122:15:122:16 | i4 indirection | semmle.label | i4 indirection | | argvLocal.c:122:15:122:16 | i4 indirection | semmle.label | i4 indirection | | argvLocal.c:122:15:122:16 | printWrapper output argument | semmle.label | printWrapper output argument | | argvLocal.c:126:10:126:13 | argv | semmle.label | argv | | argvLocal.c:126:10:126:13 | argv | semmle.label | argv | | argvLocal.c:127:9:127:10 | (const char *)... | semmle.label | (const char *)... | -| argvLocal.c:127:9:127:10 | (const char *)... | semmle.label | (const char *)... | | argvLocal.c:127:9:127:10 | i5 | semmle.label | i5 | | argvLocal.c:127:9:127:10 | i5 indirection | semmle.label | i5 indirection | -| argvLocal.c:127:9:127:10 | i5 indirection | semmle.label | i5 indirection | -| argvLocal.c:128:15:128:16 | array to pointer conversion | semmle.label | array to pointer conversion | | argvLocal.c:128:15:128:16 | array to pointer conversion | semmle.label | array to pointer conversion | | argvLocal.c:128:15:128:16 | i5 | semmle.label | i5 | | argvLocal.c:128:15:128:16 | i5 indirection | semmle.label | i5 indirection | | argvLocal.c:128:15:128:16 | i5 indirection | semmle.label | i5 indirection | | argvLocal.c:128:15:128:16 | printWrapper output argument | semmle.label | printWrapper output argument | | argvLocal.c:131:9:131:14 | (const char *)... | semmle.label | (const char *)... | -| argvLocal.c:131:9:131:14 | (const char *)... | semmle.label | (const char *)... | | argvLocal.c:131:9:131:14 | ... + ... | semmle.label | ... + ... | | argvLocal.c:131:9:131:14 | ... + ... indirection | semmle.label | ... + ... indirection | -| argvLocal.c:131:9:131:14 | ... + ... indirection | semmle.label | ... + ... indirection | | argvLocal.c:132:15:132:20 | ... + ... | semmle.label | ... + ... | | argvLocal.c:132:15:132:20 | ... + ... | semmle.label | ... + ... | -| argvLocal.c:132:15:132:20 | ... + ... | semmle.label | ... + ... | -| argvLocal.c:132:15:132:20 | ... + ... indirection | semmle.label | ... + ... indirection | | argvLocal.c:132:15:132:20 | ... + ... indirection | semmle.label | ... + ... indirection | | argvLocal.c:135:9:135:10 | i4 | semmle.label | i4 | -| argvLocal.c:135:9:135:10 | i4 | semmle.label | i4 | -| argvLocal.c:135:9:135:12 | (const char *)... | semmle.label | (const char *)... | | argvLocal.c:135:9:135:12 | (const char *)... | semmle.label | (const char *)... | | argvLocal.c:135:9:135:12 | ... ++ | semmle.label | ... ++ | | argvLocal.c:135:9:135:12 | ... ++ | semmle.label | ... ++ | -| argvLocal.c:135:9:135:12 | ... ++ | semmle.label | ... ++ | -| argvLocal.c:135:9:135:12 | ... ++ indirection | semmle.label | ... ++ indirection | | argvLocal.c:135:9:135:12 | ... ++ indirection | semmle.label | ... ++ indirection | | argvLocal.c:136:15:136:18 | -- ... | semmle.label | -- ... | | argvLocal.c:136:15:136:18 | -- ... | semmle.label | -- ... | -| argvLocal.c:136:15:136:18 | -- ... | semmle.label | -- ... | -| argvLocal.c:136:15:136:18 | -- ... indirection | semmle.label | -- ... indirection | | argvLocal.c:136:15:136:18 | -- ... indirection | semmle.label | -- ... indirection | | argvLocal.c:136:17:136:18 | i4 | semmle.label | i4 | -| argvLocal.c:136:17:136:18 | i4 | semmle.label | i4 | -| argvLocal.c:144:9:144:10 | (const char *)... | semmle.label | (const char *)... | | argvLocal.c:144:9:144:10 | (const char *)... | semmle.label | (const char *)... | | argvLocal.c:144:9:144:10 | i7 | semmle.label | i7 | | argvLocal.c:144:9:144:10 | i7 | semmle.label | i7 | -| argvLocal.c:144:9:144:10 | i7 | semmle.label | i7 | -| argvLocal.c:144:9:144:10 | i7 indirection | semmle.label | i7 indirection | | argvLocal.c:144:9:144:10 | i7 indirection | semmle.label | i7 indirection | | argvLocal.c:145:15:145:16 | i7 | semmle.label | i7 | | argvLocal.c:145:15:145:16 | i7 | semmle.label | i7 | -| argvLocal.c:145:15:145:16 | i7 | semmle.label | i7 | -| argvLocal.c:145:15:145:16 | i7 indirection | semmle.label | i7 indirection | | argvLocal.c:145:15:145:16 | i7 indirection | semmle.label | i7 indirection | | argvLocal.c:149:11:149:14 | argv | semmle.label | argv | | argvLocal.c:149:11:149:14 | argv | semmle.label | argv | | argvLocal.c:150:9:150:10 | (const char *)... | semmle.label | (const char *)... | -| argvLocal.c:150:9:150:10 | (const char *)... | semmle.label | (const char *)... | -| argvLocal.c:150:9:150:10 | i8 | semmle.label | i8 | | argvLocal.c:150:9:150:10 | i8 | semmle.label | i8 | | argvLocal.c:150:9:150:10 | i8 | semmle.label | i8 | | argvLocal.c:150:9:150:10 | i8 indirection | semmle.label | i8 indirection | -| argvLocal.c:150:9:150:10 | i8 indirection | semmle.label | i8 indirection | -| argvLocal.c:151:15:151:16 | i8 | semmle.label | i8 | | argvLocal.c:151:15:151:16 | i8 | semmle.label | i8 | | argvLocal.c:151:15:151:16 | i8 | semmle.label | i8 | | argvLocal.c:151:15:151:16 | i8 indirection | semmle.label | i8 indirection | -| argvLocal.c:151:15:151:16 | i8 indirection | semmle.label | i8 indirection | | argvLocal.c:156:23:156:26 | argv | semmle.label | argv | | argvLocal.c:156:23:156:26 | argv | semmle.label | argv | | argvLocal.c:157:9:157:10 | (const char *)... | semmle.label | (const char *)... | -| argvLocal.c:157:9:157:10 | (const char *)... | semmle.label | (const char *)... | | argvLocal.c:157:9:157:10 | i9 | semmle.label | i9 | | argvLocal.c:157:9:157:10 | i9 indirection | semmle.label | i9 indirection | -| argvLocal.c:157:9:157:10 | i9 indirection | semmle.label | i9 indirection | -| argvLocal.c:158:15:158:16 | i9 | semmle.label | i9 | | argvLocal.c:158:15:158:16 | i9 | semmle.label | i9 | | argvLocal.c:158:15:158:16 | i9 | semmle.label | i9 | | argvLocal.c:158:15:158:16 | i9 indirection | semmle.label | i9 indirection | -| argvLocal.c:158:15:158:16 | i9 indirection | semmle.label | i9 indirection | | argvLocal.c:163:22:163:25 | argv | semmle.label | argv | | argvLocal.c:163:22:163:25 | argv | semmle.label | argv | | argvLocal.c:164:9:164:11 | (const char *)... | semmle.label | (const char *)... | -| argvLocal.c:164:9:164:11 | (const char *)... | semmle.label | (const char *)... | | argvLocal.c:164:9:164:11 | i91 | semmle.label | i91 | | argvLocal.c:164:9:164:11 | i91 indirection | semmle.label | i91 indirection | -| argvLocal.c:164:9:164:11 | i91 indirection | semmle.label | i91 indirection | -| argvLocal.c:165:15:165:17 | i91 | semmle.label | i91 | | argvLocal.c:165:15:165:17 | i91 | semmle.label | i91 | | argvLocal.c:165:15:165:17 | i91 | semmle.label | i91 | | argvLocal.c:165:15:165:17 | i91 indirection | semmle.label | i91 indirection | -| argvLocal.c:165:15:165:17 | i91 indirection | semmle.label | i91 indirection | | argvLocal.c:168:18:168:21 | argv | semmle.label | argv | | argvLocal.c:168:18:168:21 | argv | semmle.label | argv | | argvLocal.c:169:9:169:20 | (char *)... | semmle.label | (char *)... | -| argvLocal.c:169:9:169:20 | (char *)... | semmle.label | (char *)... | | argvLocal.c:169:9:169:20 | (const char *)... | semmle.label | (const char *)... | -| argvLocal.c:169:9:169:20 | (const char *)... | semmle.label | (const char *)... | -| argvLocal.c:169:9:169:20 | i10 indirection | semmle.label | i10 indirection | | argvLocal.c:169:9:169:20 | i10 indirection | semmle.label | i10 indirection | | argvLocal.c:169:18:169:20 | i10 | semmle.label | i10 | | argvLocal.c:169:18:169:20 | i10 | semmle.label | i10 | -| argvLocal.c:169:18:169:20 | i10 | semmle.label | i10 | -| argvLocal.c:170:15:170:26 | (char *)... | semmle.label | (char *)... | | argvLocal.c:170:15:170:26 | (char *)... | semmle.label | (char *)... | | argvLocal.c:170:15:170:26 | i10 indirection | semmle.label | i10 indirection | -| argvLocal.c:170:15:170:26 | i10 indirection | semmle.label | i10 indirection | -| argvLocal.c:170:24:170:26 | i10 | semmle.label | i10 | | argvLocal.c:170:24:170:26 | i10 | semmle.label | i10 | | argvLocal.c:170:24:170:26 | i10 | semmle.label | i10 | #select diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/funcs/funcsLocal.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/funcs/funcsLocal.expected index 3d3f13b78cf0..ce1443696957 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/funcs/funcsLocal.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/funcs/funcsLocal.expected @@ -83,70 +83,50 @@ nodes | funcsLocal.c:16:8:16:9 | fread output argument | semmle.label | fread output argument | | funcsLocal.c:16:8:16:9 | i1 | semmle.label | i1 | | funcsLocal.c:17:9:17:10 | (const char *)... | semmle.label | (const char *)... | -| funcsLocal.c:17:9:17:10 | (const char *)... | semmle.label | (const char *)... | | funcsLocal.c:17:9:17:10 | i1 | semmle.label | i1 | | funcsLocal.c:17:9:17:10 | i1 indirection | semmle.label | i1 indirection | -| funcsLocal.c:17:9:17:10 | i1 indirection | semmle.label | i1 indirection | | funcsLocal.c:26:8:26:9 | fgets output argument | semmle.label | fgets output argument | | funcsLocal.c:26:8:26:9 | i3 | semmle.label | i3 | | funcsLocal.c:27:9:27:10 | (const char *)... | semmle.label | (const char *)... | -| funcsLocal.c:27:9:27:10 | (const char *)... | semmle.label | (const char *)... | | funcsLocal.c:27:9:27:10 | i3 | semmle.label | i3 | | funcsLocal.c:27:9:27:10 | i3 indirection | semmle.label | i3 indirection | -| funcsLocal.c:27:9:27:10 | i3 indirection | semmle.label | i3 indirection | | funcsLocal.c:31:13:31:17 | call to fgets | semmle.label | call to fgets | | funcsLocal.c:31:13:31:17 | call to fgets | semmle.label | call to fgets | | funcsLocal.c:31:19:31:21 | fgets output argument | semmle.label | fgets output argument | | funcsLocal.c:31:19:31:21 | i41 | semmle.label | i41 | | funcsLocal.c:32:9:32:10 | (const char *)... | semmle.label | (const char *)... | -| funcsLocal.c:32:9:32:10 | (const char *)... | semmle.label | (const char *)... | | funcsLocal.c:32:9:32:10 | i4 | semmle.label | i4 | | funcsLocal.c:32:9:32:10 | i4 | semmle.label | i4 | -| funcsLocal.c:32:9:32:10 | i4 | semmle.label | i4 | -| funcsLocal.c:32:9:32:10 | i4 indirection | semmle.label | i4 indirection | | funcsLocal.c:32:9:32:10 | i4 indirection | semmle.label | i4 indirection | | funcsLocal.c:36:7:36:8 | gets output argument | semmle.label | gets output argument | | funcsLocal.c:36:7:36:8 | i5 | semmle.label | i5 | | funcsLocal.c:37:9:37:10 | (const char *)... | semmle.label | (const char *)... | -| funcsLocal.c:37:9:37:10 | (const char *)... | semmle.label | (const char *)... | | funcsLocal.c:37:9:37:10 | i5 | semmle.label | i5 | | funcsLocal.c:37:9:37:10 | i5 indirection | semmle.label | i5 indirection | -| funcsLocal.c:37:9:37:10 | i5 indirection | semmle.label | i5 indirection | | funcsLocal.c:41:13:41:16 | call to gets | semmle.label | call to gets | | funcsLocal.c:41:13:41:16 | call to gets | semmle.label | call to gets | | funcsLocal.c:41:18:41:20 | gets output argument | semmle.label | gets output argument | | funcsLocal.c:41:18:41:20 | i61 | semmle.label | i61 | | funcsLocal.c:42:9:42:10 | (const char *)... | semmle.label | (const char *)... | -| funcsLocal.c:42:9:42:10 | (const char *)... | semmle.label | (const char *)... | | funcsLocal.c:42:9:42:10 | i6 | semmle.label | i6 | | funcsLocal.c:42:9:42:10 | i6 | semmle.label | i6 | -| funcsLocal.c:42:9:42:10 | i6 | semmle.label | i6 | -| funcsLocal.c:42:9:42:10 | i6 indirection | semmle.label | i6 indirection | | funcsLocal.c:42:9:42:10 | i6 indirection | semmle.label | i6 indirection | | funcsLocal.c:46:7:46:9 | * ... | semmle.label | * ... | | funcsLocal.c:46:7:46:9 | * ... | semmle.label | * ... | | funcsLocal.c:46:7:46:9 | gets output argument | semmle.label | gets output argument | | funcsLocal.c:47:9:47:11 | (const char *)... | semmle.label | (const char *)... | -| funcsLocal.c:47:9:47:11 | (const char *)... | semmle.label | (const char *)... | | funcsLocal.c:47:9:47:11 | * ... | semmle.label | * ... | | funcsLocal.c:47:9:47:11 | * ... | semmle.label | * ... | -| funcsLocal.c:47:9:47:11 | * ... | semmle.label | * ... | -| funcsLocal.c:47:9:47:11 | * ... indirection | semmle.label | * ... indirection | | funcsLocal.c:47:9:47:11 | * ... indirection | semmle.label | * ... indirection | | funcsLocal.c:52:8:52:11 | call to gets | semmle.label | call to gets | | funcsLocal.c:52:8:52:11 | call to gets | semmle.label | call to gets | | funcsLocal.c:53:9:53:11 | (const char *)... | semmle.label | (const char *)... | -| funcsLocal.c:53:9:53:11 | (const char *)... | semmle.label | (const char *)... | -| funcsLocal.c:53:9:53:11 | * ... | semmle.label | * ... | | funcsLocal.c:53:9:53:11 | * ... | semmle.label | * ... | | funcsLocal.c:53:9:53:11 | * ... | semmle.label | * ... | | funcsLocal.c:53:9:53:11 | * ... indirection | semmle.label | * ... indirection | -| funcsLocal.c:53:9:53:11 | * ... indirection | semmle.label | * ... indirection | -| funcsLocal.c:58:9:58:10 | (const char *)... | semmle.label | (const char *)... | | funcsLocal.c:58:9:58:10 | (const char *)... | semmle.label | (const char *)... | | funcsLocal.c:58:9:58:10 | e1 | semmle.label | e1 | | funcsLocal.c:58:9:58:10 | e1 indirection | semmle.label | e1 indirection | -| funcsLocal.c:58:9:58:10 | e1 indirection | semmle.label | e1 indirection | #select | funcsLocal.c:17:9:17:10 | i1 | funcsLocal.c:16:8:16:9 | i1 | funcsLocal.c:17:9:17:10 | i1 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format). | funcsLocal.c:16:8:16:9 | i1 | fread | | funcsLocal.c:27:9:27:10 | i3 | funcsLocal.c:26:8:26:9 | i3 | funcsLocal.c:27:9:27:10 | i3 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format). | funcsLocal.c:26:8:26:9 | i3 | fgets | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/globalVars/UncontrolledFormatString.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/globalVars/UncontrolledFormatString.expected index 911a6cf35e7f..90743a711787 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/globalVars/UncontrolledFormatString.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/globalVars/UncontrolledFormatString.expected @@ -90,12 +90,10 @@ nodes | globalVars.c:24:11:24:14 | argv | semmle.label | argv | | globalVars.c:24:11:24:14 | argv indirection | semmle.label | argv indirection | | globalVars.c:27:9:27:12 | (const char *)... | semmle.label | (const char *)... | -| globalVars.c:27:9:27:12 | (const char *)... | semmle.label | (const char *)... | | globalVars.c:27:9:27:12 | copy | semmle.label | copy | | globalVars.c:27:9:27:12 | copy | semmle.label | copy | | globalVars.c:27:9:27:12 | copy | semmle.label | copy | | globalVars.c:27:9:27:12 | copy indirection | semmle.label | copy indirection | -| globalVars.c:27:9:27:12 | copy indirection | semmle.label | copy indirection | | globalVars.c:30:15:30:18 | copy | semmle.label | copy | | globalVars.c:30:15:30:18 | copy | semmle.label | copy | | globalVars.c:30:15:30:18 | copy | semmle.label | copy | @@ -106,12 +104,10 @@ nodes | globalVars.c:35:11:35:14 | copy | semmle.label | copy | | globalVars.c:35:11:35:14 | copy | semmle.label | copy | | globalVars.c:38:9:38:13 | (const char *)... | semmle.label | (const char *)... | -| globalVars.c:38:9:38:13 | (const char *)... | semmle.label | (const char *)... | | globalVars.c:38:9:38:13 | copy2 | semmle.label | copy2 | | globalVars.c:38:9:38:13 | copy2 | semmle.label | copy2 | | globalVars.c:38:9:38:13 | copy2 | semmle.label | copy2 | | globalVars.c:38:9:38:13 | copy2 indirection | semmle.label | copy2 indirection | -| globalVars.c:38:9:38:13 | copy2 indirection | semmle.label | copy2 indirection | | globalVars.c:41:15:41:19 | copy2 | semmle.label | copy2 | | globalVars.c:41:15:41:19 | copy2 | semmle.label | copy2 | | globalVars.c:41:15:41:19 | copy2 | semmle.label | copy2 | @@ -120,12 +116,10 @@ nodes | globalVars.c:41:15:41:19 | printWrapper output argument | semmle.label | printWrapper output argument | | globalVars.c:44:15:44:19 | copy2 | semmle.label | copy2 | | globalVars.c:50:9:50:13 | (const char *)... | semmle.label | (const char *)... | -| globalVars.c:50:9:50:13 | (const char *)... | semmle.label | (const char *)... | | globalVars.c:50:9:50:13 | copy2 | semmle.label | copy2 | | globalVars.c:50:9:50:13 | copy2 | semmle.label | copy2 | | globalVars.c:50:9:50:13 | copy2 | semmle.label | copy2 | | globalVars.c:50:9:50:13 | copy2 indirection | semmle.label | copy2 indirection | -| globalVars.c:50:9:50:13 | copy2 indirection | semmle.label | copy2 indirection | #select | globalVars.c:27:9:27:12 | copy | globalVars.c:24:11:24:14 | argv | globalVars.c:27:9:27:12 | copy | The value of this argument may come from $@ and is being used as a formatting argument to printf(format). | globalVars.c:24:11:24:14 | argv | argv | | globalVars.c:30:15:30:18 | copy | globalVars.c:24:11:24:14 | argv | globalVars.c:30:15:30:18 | copy | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(str), which calls printf(format). | globalVars.c:24:11:24:14 | argv | argv | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/globalVars/UncontrolledFormatStringThroughGlobalVar.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/globalVars/UncontrolledFormatStringThroughGlobalVar.expected index 911a6cf35e7f..90743a711787 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/globalVars/UncontrolledFormatStringThroughGlobalVar.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/globalVars/UncontrolledFormatStringThroughGlobalVar.expected @@ -90,12 +90,10 @@ nodes | globalVars.c:24:11:24:14 | argv | semmle.label | argv | | globalVars.c:24:11:24:14 | argv indirection | semmle.label | argv indirection | | globalVars.c:27:9:27:12 | (const char *)... | semmle.label | (const char *)... | -| globalVars.c:27:9:27:12 | (const char *)... | semmle.label | (const char *)... | | globalVars.c:27:9:27:12 | copy | semmle.label | copy | | globalVars.c:27:9:27:12 | copy | semmle.label | copy | | globalVars.c:27:9:27:12 | copy | semmle.label | copy | | globalVars.c:27:9:27:12 | copy indirection | semmle.label | copy indirection | -| globalVars.c:27:9:27:12 | copy indirection | semmle.label | copy indirection | | globalVars.c:30:15:30:18 | copy | semmle.label | copy | | globalVars.c:30:15:30:18 | copy | semmle.label | copy | | globalVars.c:30:15:30:18 | copy | semmle.label | copy | @@ -106,12 +104,10 @@ nodes | globalVars.c:35:11:35:14 | copy | semmle.label | copy | | globalVars.c:35:11:35:14 | copy | semmle.label | copy | | globalVars.c:38:9:38:13 | (const char *)... | semmle.label | (const char *)... | -| globalVars.c:38:9:38:13 | (const char *)... | semmle.label | (const char *)... | | globalVars.c:38:9:38:13 | copy2 | semmle.label | copy2 | | globalVars.c:38:9:38:13 | copy2 | semmle.label | copy2 | | globalVars.c:38:9:38:13 | copy2 | semmle.label | copy2 | | globalVars.c:38:9:38:13 | copy2 indirection | semmle.label | copy2 indirection | -| globalVars.c:38:9:38:13 | copy2 indirection | semmle.label | copy2 indirection | | globalVars.c:41:15:41:19 | copy2 | semmle.label | copy2 | | globalVars.c:41:15:41:19 | copy2 | semmle.label | copy2 | | globalVars.c:41:15:41:19 | copy2 | semmle.label | copy2 | @@ -120,12 +116,10 @@ nodes | globalVars.c:41:15:41:19 | printWrapper output argument | semmle.label | printWrapper output argument | | globalVars.c:44:15:44:19 | copy2 | semmle.label | copy2 | | globalVars.c:50:9:50:13 | (const char *)... | semmle.label | (const char *)... | -| globalVars.c:50:9:50:13 | (const char *)... | semmle.label | (const char *)... | | globalVars.c:50:9:50:13 | copy2 | semmle.label | copy2 | | globalVars.c:50:9:50:13 | copy2 | semmle.label | copy2 | | globalVars.c:50:9:50:13 | copy2 | semmle.label | copy2 | | globalVars.c:50:9:50:13 | copy2 indirection | semmle.label | copy2 indirection | -| globalVars.c:50:9:50:13 | copy2 indirection | semmle.label | copy2 indirection | #select | globalVars.c:27:9:27:12 | copy | globalVars.c:24:11:24:14 | argv | globalVars.c:27:9:27:12 | copy | The value of this argument may come from $@ and is being used as a formatting argument to printf(format). | globalVars.c:24:11:24:14 | argv | argv | | globalVars.c:30:15:30:18 | copy | globalVars.c:24:11:24:14 | argv | globalVars.c:30:15:30:18 | copy | The value of this argument may come from $@ and is being used as a formatting argument to printWrapper(str), which calls printf(format). | globalVars.c:24:11:24:14 | argv | argv | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/ifs/ifs.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/ifs/ifs.expected index d831e8df115f..cc1fde25ef58 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/ifs/ifs.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-134/semmle/ifs/ifs.expected @@ -92,101 +92,68 @@ nodes | ifs.c:61:8:61:11 | argv | semmle.label | argv | | ifs.c:61:8:61:11 | argv | semmle.label | argv | | ifs.c:62:9:62:10 | (const char *)... | semmle.label | (const char *)... | -| ifs.c:62:9:62:10 | (const char *)... | semmle.label | (const char *)... | -| ifs.c:62:9:62:10 | c7 | semmle.label | c7 | | ifs.c:62:9:62:10 | c7 | semmle.label | c7 | | ifs.c:62:9:62:10 | c7 | semmle.label | c7 | | ifs.c:62:9:62:10 | c7 indirection | semmle.label | c7 indirection | -| ifs.c:62:9:62:10 | c7 indirection | semmle.label | c7 indirection | | ifs.c:68:8:68:11 | argv | semmle.label | argv | | ifs.c:68:8:68:11 | argv | semmle.label | argv | | ifs.c:69:9:69:10 | (const char *)... | semmle.label | (const char *)... | -| ifs.c:69:9:69:10 | (const char *)... | semmle.label | (const char *)... | -| ifs.c:69:9:69:10 | c8 | semmle.label | c8 | | ifs.c:69:9:69:10 | c8 | semmle.label | c8 | | ifs.c:69:9:69:10 | c8 | semmle.label | c8 | | ifs.c:69:9:69:10 | c8 indirection | semmle.label | c8 indirection | -| ifs.c:69:9:69:10 | c8 indirection | semmle.label | c8 indirection | | ifs.c:74:8:74:11 | argv | semmle.label | argv | | ifs.c:74:8:74:11 | argv | semmle.label | argv | | ifs.c:75:9:75:10 | (const char *)... | semmle.label | (const char *)... | -| ifs.c:75:9:75:10 | (const char *)... | semmle.label | (const char *)... | | ifs.c:75:9:75:10 | i1 | semmle.label | i1 | | ifs.c:75:9:75:10 | i1 | semmle.label | i1 | -| ifs.c:75:9:75:10 | i1 | semmle.label | i1 | -| ifs.c:75:9:75:10 | i1 indirection | semmle.label | i1 indirection | | ifs.c:75:9:75:10 | i1 indirection | semmle.label | i1 indirection | | ifs.c:80:8:80:11 | argv | semmle.label | argv | | ifs.c:80:8:80:11 | argv | semmle.label | argv | | ifs.c:81:9:81:10 | (const char *)... | semmle.label | (const char *)... | -| ifs.c:81:9:81:10 | (const char *)... | semmle.label | (const char *)... | -| ifs.c:81:9:81:10 | i2 | semmle.label | i2 | | ifs.c:81:9:81:10 | i2 | semmle.label | i2 | | ifs.c:81:9:81:10 | i2 | semmle.label | i2 | | ifs.c:81:9:81:10 | i2 indirection | semmle.label | i2 indirection | -| ifs.c:81:9:81:10 | i2 indirection | semmle.label | i2 indirection | | ifs.c:86:8:86:11 | argv | semmle.label | argv | | ifs.c:86:8:86:11 | argv | semmle.label | argv | | ifs.c:87:9:87:10 | (const char *)... | semmle.label | (const char *)... | -| ifs.c:87:9:87:10 | (const char *)... | semmle.label | (const char *)... | | ifs.c:87:9:87:10 | i3 | semmle.label | i3 | | ifs.c:87:9:87:10 | i3 | semmle.label | i3 | -| ifs.c:87:9:87:10 | i3 | semmle.label | i3 | -| ifs.c:87:9:87:10 | i3 indirection | semmle.label | i3 indirection | | ifs.c:87:9:87:10 | i3 indirection | semmle.label | i3 indirection | | ifs.c:92:8:92:11 | argv | semmle.label | argv | | ifs.c:92:8:92:11 | argv | semmle.label | argv | | ifs.c:93:9:93:10 | (const char *)... | semmle.label | (const char *)... | -| ifs.c:93:9:93:10 | (const char *)... | semmle.label | (const char *)... | -| ifs.c:93:9:93:10 | i4 | semmle.label | i4 | | ifs.c:93:9:93:10 | i4 | semmle.label | i4 | | ifs.c:93:9:93:10 | i4 | semmle.label | i4 | | ifs.c:93:9:93:10 | i4 indirection | semmle.label | i4 indirection | -| ifs.c:93:9:93:10 | i4 indirection | semmle.label | i4 indirection | | ifs.c:98:8:98:11 | argv | semmle.label | argv | | ifs.c:98:8:98:11 | argv | semmle.label | argv | | ifs.c:99:9:99:10 | (const char *)... | semmle.label | (const char *)... | -| ifs.c:99:9:99:10 | (const char *)... | semmle.label | (const char *)... | | ifs.c:99:9:99:10 | i5 | semmle.label | i5 | | ifs.c:99:9:99:10 | i5 | semmle.label | i5 | -| ifs.c:99:9:99:10 | i5 | semmle.label | i5 | -| ifs.c:99:9:99:10 | i5 indirection | semmle.label | i5 indirection | | ifs.c:99:9:99:10 | i5 indirection | semmle.label | i5 indirection | | ifs.c:105:8:105:11 | argv | semmle.label | argv | | ifs.c:105:8:105:11 | argv | semmle.label | argv | | ifs.c:106:9:106:10 | (const char *)... | semmle.label | (const char *)... | -| ifs.c:106:9:106:10 | (const char *)... | semmle.label | (const char *)... | -| ifs.c:106:9:106:10 | i6 | semmle.label | i6 | | ifs.c:106:9:106:10 | i6 | semmle.label | i6 | | ifs.c:106:9:106:10 | i6 | semmle.label | i6 | | ifs.c:106:9:106:10 | i6 indirection | semmle.label | i6 indirection | -| ifs.c:106:9:106:10 | i6 indirection | semmle.label | i6 indirection | | ifs.c:111:8:111:11 | argv | semmle.label | argv | | ifs.c:111:8:111:11 | argv | semmle.label | argv | | ifs.c:112:9:112:10 | (const char *)... | semmle.label | (const char *)... | -| ifs.c:112:9:112:10 | (const char *)... | semmle.label | (const char *)... | | ifs.c:112:9:112:10 | i7 | semmle.label | i7 | | ifs.c:112:9:112:10 | i7 | semmle.label | i7 | -| ifs.c:112:9:112:10 | i7 | semmle.label | i7 | -| ifs.c:112:9:112:10 | i7 indirection | semmle.label | i7 indirection | | ifs.c:112:9:112:10 | i7 indirection | semmle.label | i7 indirection | | ifs.c:117:8:117:11 | argv | semmle.label | argv | | ifs.c:117:8:117:11 | argv | semmle.label | argv | | ifs.c:118:9:118:10 | (const char *)... | semmle.label | (const char *)... | -| ifs.c:118:9:118:10 | (const char *)... | semmle.label | (const char *)... | -| ifs.c:118:9:118:10 | i8 | semmle.label | i8 | | ifs.c:118:9:118:10 | i8 | semmle.label | i8 | | ifs.c:118:9:118:10 | i8 | semmle.label | i8 | | ifs.c:118:9:118:10 | i8 indirection | semmle.label | i8 indirection | -| ifs.c:118:9:118:10 | i8 indirection | semmle.label | i8 indirection | | ifs.c:123:8:123:11 | argv | semmle.label | argv | | ifs.c:123:8:123:11 | argv | semmle.label | argv | | ifs.c:124:9:124:10 | (const char *)... | semmle.label | (const char *)... | -| ifs.c:124:9:124:10 | (const char *)... | semmle.label | (const char *)... | | ifs.c:124:9:124:10 | i9 | semmle.label | i9 | | ifs.c:124:9:124:10 | i9 | semmle.label | i9 | -| ifs.c:124:9:124:10 | i9 | semmle.label | i9 | -| ifs.c:124:9:124:10 | i9 indirection | semmle.label | i9 indirection | | ifs.c:124:9:124:10 | i9 indirection | semmle.label | i9 indirection | #select | ifs.c:62:9:62:10 | c7 | ifs.c:61:8:61:11 | argv | ifs.c:62:9:62:10 | c7 | The value of this argument may come from $@ and is being used as a formatting argument to printf(format). | ifs.c:61:8:61:11 | argv | argv | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-190/SAMATE/ArithmeticTainted.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-190/SAMATE/ArithmeticTainted.expected index 6d943043d3cd..b86b85a91ebc 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-190/SAMATE/ArithmeticTainted.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-190/SAMATE/ArithmeticTainted.expected @@ -9,6 +9,5 @@ nodes | examples.cpp:63:26:63:30 | fscanf output argument | semmle.label | fscanf output argument | | examples.cpp:66:11:66:14 | data | semmle.label | data | | examples.cpp:66:11:66:14 | data | semmle.label | data | -| examples.cpp:66:11:66:14 | data | semmle.label | data | #select | examples.cpp:66:11:66:14 | data | examples.cpp:63:26:63:30 | & ... | examples.cpp:66:11:66:14 | data | $@ flows to an operand of an arithmetic expression, potentially causing an underflow. | examples.cpp:63:26:63:30 | & ... | User-provided value | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/tainted/ArithmeticTainted.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/tainted/ArithmeticTainted.expected index 1b40c09b3b06..be5a4ab812f4 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/tainted/ArithmeticTainted.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-190/semmle/tainted/ArithmeticTainted.expected @@ -28,7 +28,6 @@ nodes | test2.cpp:12:21:12:21 | v | semmle.label | v | | test2.cpp:14:11:14:11 | v | semmle.label | v | | test2.cpp:14:11:14:11 | v | semmle.label | v | -| test2.cpp:14:11:14:11 | v | semmle.label | v | | test2.cpp:25:22:25:23 | & ... | semmle.label | & ... | | test2.cpp:25:22:25:23 | fscanf output argument | semmle.label | fscanf output argument | | test2.cpp:27:13:27:13 | v | semmle.label | v | @@ -37,26 +36,21 @@ nodes | test5.cpp:9:7:9:9 | gets output argument | semmle.label | gets output argument | | test5.cpp:17:6:17:18 | call to getTaintedInt | semmle.label | call to getTaintedInt | | test5.cpp:17:6:17:18 | call to getTaintedInt | semmle.label | call to getTaintedInt | -| test5.cpp:17:6:17:18 | call to getTaintedInt | semmle.label | call to getTaintedInt | | test5.cpp:18:6:18:18 | call to getTaintedInt | semmle.label | call to getTaintedInt | | test5.cpp:19:6:19:6 | y | semmle.label | y | | test5.cpp:19:6:19:6 | y | semmle.label | y | -| test5.cpp:19:6:19:6 | y | semmle.label | y | | test.c:11:29:11:32 | argv | semmle.label | argv | | test.c:11:29:11:32 | argv | semmle.label | argv | | test.c:14:15:14:28 | maxConnections | semmle.label | maxConnections | | test.c:14:15:14:28 | maxConnections | semmle.label | maxConnections | -| test.c:14:15:14:28 | maxConnections | semmle.label | maxConnections | | test.c:41:17:41:20 | argv | semmle.label | argv | | test.c:41:17:41:20 | argv | semmle.label | argv | | test.c:44:7:44:10 | len2 | semmle.label | len2 | | test.c:44:7:44:10 | len2 | semmle.label | len2 | -| test.c:44:7:44:10 | len2 | semmle.label | len2 | | test.c:51:17:51:20 | argv | semmle.label | argv | | test.c:51:17:51:20 | argv | semmle.label | argv | | test.c:54:7:54:10 | len3 | semmle.label | len3 | | test.c:54:7:54:10 | len3 | semmle.label | len3 | -| test.c:54:7:54:10 | len3 | semmle.label | len3 | #select | test2.cpp:14:11:14:11 | v | test2.cpp:25:22:25:23 | & ... | test2.cpp:14:11:14:11 | v | $@ flows to an operand of an arithmetic expression, potentially causing an overflow. | test2.cpp:25:22:25:23 | & ... | User-provided value | | test2.cpp:14:11:14:11 | v | test2.cpp:25:22:25:23 | & ... | test2.cpp:14:11:14:11 | v | $@ flows to an operand of an arithmetic expression, potentially causing an underflow. | test2.cpp:25:22:25:23 | & ... | User-provided value | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-290/semmle/AuthenticationBypass/AuthenticationBypass.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-290/semmle/AuthenticationBypass/AuthenticationBypass.expected index 360ced041448..ef28e08058da 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-290/semmle/AuthenticationBypass/AuthenticationBypass.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-290/semmle/AuthenticationBypass/AuthenticationBypass.expected @@ -23,22 +23,16 @@ nodes | test.cpp:16:25:16:42 | (const char *)... | semmle.label | (const char *)... | | test.cpp:20:14:20:20 | address | semmle.label | address | | test.cpp:20:14:20:20 | address | semmle.label | address | -| test.cpp:20:14:20:20 | address | semmle.label | address | -| test.cpp:20:14:20:20 | address indirection | semmle.label | address indirection | | test.cpp:20:14:20:20 | address indirection | semmle.label | address indirection | | test.cpp:27:25:27:30 | call to getenv | semmle.label | call to getenv | | test.cpp:27:25:27:42 | (const char *)... | semmle.label | (const char *)... | | test.cpp:31:14:31:20 | address | semmle.label | address | | test.cpp:31:14:31:20 | address | semmle.label | address | -| test.cpp:31:14:31:20 | address | semmle.label | address | -| test.cpp:31:14:31:20 | address indirection | semmle.label | address indirection | | test.cpp:31:14:31:20 | address indirection | semmle.label | address indirection | | test.cpp:38:25:38:30 | call to getenv | semmle.label | call to getenv | | test.cpp:38:25:38:42 | (const char *)... | semmle.label | (const char *)... | | test.cpp:42:14:42:20 | address | semmle.label | address | | test.cpp:42:14:42:20 | address | semmle.label | address | -| test.cpp:42:14:42:20 | address | semmle.label | address | -| test.cpp:42:14:42:20 | address indirection | semmle.label | address indirection | | test.cpp:42:14:42:20 | address indirection | semmle.label | address indirection | #select | test.cpp:20:7:20:12 | call to strcmp | test.cpp:16:25:16:30 | call to getenv | test.cpp:20:14:20:20 | address | Untrusted input $@ might be vulnerable to a spoofing attack. | test.cpp:16:25:16:30 | call to getenv | call to getenv | diff --git a/cpp/ql/test/query-tests/Security/CWE/CWE-807/semmle/TaintedCondition/TaintedCondition.expected b/cpp/ql/test/query-tests/Security/CWE/CWE-807/semmle/TaintedCondition/TaintedCondition.expected index f00ccba83b2b..f0011ddbbd8b 100644 --- a/cpp/ql/test/query-tests/Security/CWE/CWE-807/semmle/TaintedCondition/TaintedCondition.expected +++ b/cpp/ql/test/query-tests/Security/CWE/CWE-807/semmle/TaintedCondition/TaintedCondition.expected @@ -9,6 +9,5 @@ nodes | test.cpp:20:29:20:47 | (const char *)... | semmle.label | (const char *)... | | test.cpp:24:10:24:35 | ! ... | semmle.label | ! ... | | test.cpp:24:11:24:16 | call to strcmp | semmle.label | call to strcmp | -| test.cpp:24:11:24:16 | call to strcmp | semmle.label | call to strcmp | #select | test.cpp:24:10:24:35 | ! ... | test.cpp:20:29:20:34 | call to getenv | test.cpp:24:10:24:35 | ! ... | Reliance on untrusted input $@ to raise privilege at $@. | test.cpp:20:29:20:34 | call to getenv | call to getenv | test.cpp:25:9:25:27 | ... = ... | ... = ... | From 1711efcc47a00dc62db0c7e4b61999d8d94a46a4 Mon Sep 17 00:00:00 2001 From: Tom Hvitved Date: Tue, 1 Nov 2022 13:31:05 +0100 Subject: [PATCH 4/4] C#: Update expected test output --- .../DangerousNativeFunctionCall.expected | 2 +- .../backdoor/PotentialTimeBomb.expected | 34 ++++++++----------- .../Security Features/backdoor/test.cs | 15 ++++---- 3 files changed, 23 insertions(+), 28 deletions(-) diff --git a/csharp/ql/test/experimental/Security Features/backdoor/DangerousNativeFunctionCall.expected b/csharp/ql/test/experimental/Security Features/backdoor/DangerousNativeFunctionCall.expected index f890a8447785..efbdcb3dd56b 100644 --- a/csharp/ql/test/experimental/Security Features/backdoor/DangerousNativeFunctionCall.expected +++ b/csharp/ql/test/experimental/Security Features/backdoor/DangerousNativeFunctionCall.expected @@ -1 +1 @@ -| test.cs:31:9:31:74 | call to method InitiateSystemShutdownExW | Call to an external method 'InitiateSystemShutdownExW'. | +| test.cs:32:9:32:74 | call to method InitiateSystemShutdownExW | Call to an external method 'InitiateSystemShutdownExW'. | diff --git a/csharp/ql/test/experimental/Security Features/backdoor/PotentialTimeBomb.expected b/csharp/ql/test/experimental/Security Features/backdoor/PotentialTimeBomb.expected index 4eef156a2928..142d342726d0 100644 --- a/csharp/ql/test/experimental/Security Features/backdoor/PotentialTimeBomb.expected +++ b/csharp/ql/test/experimental/Security Features/backdoor/PotentialTimeBomb.expected @@ -1,23 +1,17 @@ edges -| test.cs:68:34:68:76 | call to method GetLastWriteTime : DateTime | test.cs:70:36:70:48 | access to local variable lastWriteTime | -| test.cs:70:13:70:71 | call to method CompareTo : Int32 | test.cs:70:13:70:76 | ... >= ... | -| test.cs:70:36:70:48 | access to local variable lastWriteTime | test.cs:70:36:70:70 | call to method AddHours | -| test.cs:70:36:70:48 | access to local variable lastWriteTime | test.cs:70:36:70:70 | call to method AddHours : DateTime | -| test.cs:70:36:70:48 | access to local variable lastWriteTime : DateTime | test.cs:70:36:70:70 | call to method AddHours | -| test.cs:70:36:70:48 | access to local variable lastWriteTime : DateTime | test.cs:70:36:70:70 | call to method AddHours : DateTime | -| test.cs:70:36:70:70 | call to method AddHours | test.cs:70:13:70:71 | call to method CompareTo | -| test.cs:70:36:70:70 | call to method AddHours | test.cs:70:13:70:71 | call to method CompareTo : Int32 | -| test.cs:70:36:70:70 | call to method AddHours : DateTime | test.cs:70:13:70:71 | call to method CompareTo | -| test.cs:70:36:70:70 | call to method AddHours : DateTime | test.cs:70:13:70:71 | call to method CompareTo : Int32 | +| test.cs:69:34:69:76 | call to method GetLastWriteTime : DateTime | test.cs:71:36:71:48 | access to local variable lastWriteTime | +| test.cs:71:13:71:71 | call to method CompareTo : Int32 | test.cs:71:13:71:76 | ... >= ... | +| test.cs:71:36:71:48 | access to local variable lastWriteTime | test.cs:71:36:71:70 | call to method AddHours | +| test.cs:71:36:71:70 | call to method AddHours | test.cs:71:13:71:71 | call to method CompareTo | +| test.cs:71:36:71:70 | call to method AddHours | test.cs:71:13:71:71 | call to method CompareTo : Int32 | #select -| test.cs:70:9:73:9 | if (...) ... | test.cs:68:34:68:76 | call to method GetLastWriteTime : DateTime | test.cs:70:13:70:71 | call to method CompareTo | Possible TimeBomb logic triggered by an $@ that takes into account $@ from the $@ as part of the potential trigger. | test.cs:70:13:70:71 | call to method CompareTo | call to method CompareTo | test.cs:70:36:70:70 | call to method AddHours | offset | test.cs:68:34:68:76 | call to method GetLastWriteTime | last modification time of a file | -| test.cs:70:9:73:9 | if (...) ... | test.cs:68:34:68:76 | call to method GetLastWriteTime : DateTime | test.cs:70:13:70:71 | call to method CompareTo : Int32 | Possible TimeBomb logic triggered by an $@ that takes into account $@ from the $@ as part of the potential trigger. | test.cs:70:13:70:71 | call to method CompareTo | call to method CompareTo | test.cs:70:36:70:70 | call to method AddHours | offset | test.cs:68:34:68:76 | call to method GetLastWriteTime | last modification time of a file | -| test.cs:70:9:73:9 | if (...) ... | test.cs:68:34:68:76 | call to method GetLastWriteTime : DateTime | test.cs:70:13:70:76 | ... >= ... | Possible TimeBomb logic triggered by an $@ that takes into account $@ from the $@ as part of the potential trigger. | test.cs:70:13:70:71 | call to method CompareTo | call to method CompareTo | test.cs:70:36:70:70 | call to method AddHours | offset | test.cs:68:34:68:76 | call to method GetLastWriteTime | last modification time of a file | -| test.cs:70:9:73:9 | if (...) ... | test.cs:68:34:68:76 | call to method GetLastWriteTime : DateTime | test.cs:70:13:70:76 | ... >= ... : Boolean | Possible TimeBomb logic triggered by an $@ that takes into account $@ from the $@ as part of the potential trigger. | test.cs:70:13:70:71 | call to method CompareTo | call to method CompareTo | test.cs:70:36:70:70 | call to method AddHours | offset | test.cs:68:34:68:76 | call to method GetLastWriteTime | last modification time of a file | +| test.cs:71:9:74:9 | if (...) ... | test.cs:69:34:69:76 | call to method GetLastWriteTime : DateTime | test.cs:71:13:71:71 | call to method CompareTo | Possible TimeBomb logic triggered by an $@ that takes into account $@ from the $@ as part of the potential trigger. | test.cs:71:13:71:71 | call to method CompareTo | call to method CompareTo | test.cs:71:36:71:70 | call to method AddHours | offset | test.cs:69:34:69:76 | call to method GetLastWriteTime | last modification time of a file | +| test.cs:71:9:74:9 | if (...) ... | test.cs:69:34:69:76 | call to method GetLastWriteTime : DateTime | test.cs:71:13:71:71 | call to method CompareTo : Int32 | Possible TimeBomb logic triggered by an $@ that takes into account $@ from the $@ as part of the potential trigger. | test.cs:71:13:71:71 | call to method CompareTo | call to method CompareTo | test.cs:71:36:71:70 | call to method AddHours | offset | test.cs:69:34:69:76 | call to method GetLastWriteTime | last modification time of a file | +| test.cs:71:9:74:9 | if (...) ... | test.cs:69:34:69:76 | call to method GetLastWriteTime : DateTime | test.cs:71:13:71:76 | ... >= ... | Possible TimeBomb logic triggered by an $@ that takes into account $@ from the $@ as part of the potential trigger. | test.cs:71:13:71:71 | call to method CompareTo | call to method CompareTo | test.cs:71:36:71:70 | call to method AddHours | offset | test.cs:69:34:69:76 | call to method GetLastWriteTime | last modification time of a file | nodes -| test.cs:68:34:68:76 | call to method GetLastWriteTime : DateTime | semmle.label | call to method GetLastWriteTime : DateTime | -| test.cs:70:13:70:71 | call to method CompareTo | semmle.label | call to method CompareTo | -| test.cs:70:13:70:71 | call to method CompareTo : Int32 | semmle.label | call to method CompareTo : Int32 | -| test.cs:70:13:70:76 | ... >= ... | semmle.label | ... >= ... | -| test.cs:70:36:70:48 | access to local variable lastWriteTime | semmle.label | access to local variable lastWriteTime | -| test.cs:70:36:70:70 | call to method AddHours | semmle.label | call to method AddHours | +| test.cs:69:34:69:76 | call to method GetLastWriteTime : DateTime | semmle.label | call to method GetLastWriteTime : DateTime | +| test.cs:71:13:71:71 | call to method CompareTo | semmle.label | call to method CompareTo | +| test.cs:71:13:71:71 | call to method CompareTo : Int32 | semmle.label | call to method CompareTo : Int32 | +| test.cs:71:13:71:76 | ... >= ... | semmle.label | ... >= ... | +| test.cs:71:36:71:48 | access to local variable lastWriteTime | semmle.label | access to local variable lastWriteTime | +| test.cs:71:36:71:70 | call to method AddHours | semmle.label | call to method AddHours | diff --git a/csharp/ql/test/experimental/Security Features/backdoor/test.cs b/csharp/ql/test/experimental/Security Features/backdoor/test.cs index aea058184230..1aecc80aa83f 100644 --- a/csharp/ql/test/experimental/Security Features/backdoor/test.cs +++ b/csharp/ql/test/experimental/Security Features/backdoor/test.cs @@ -21,7 +21,8 @@ public class Process } } -class External { +class External +{ [DllImport("advapi32.dll", CharSet = CharSet.Unicode, SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] public static extern bool InitiateSystemShutdownExW([In] string lpMachineName, [In] string lpMessage, [In] uint dwTimeout, [MarshalAs(UnmanagedType.Bool)][In] bool bForceAppsClosed, [MarshalAs(UnmanagedType.Bool)][In] bool bRebootAfterShutdown, [In] uint dwReason); @@ -46,28 +47,28 @@ ulong GetFvnHash(string s) { } // regular FVN - return num; + return num; } - void IndirectTestProcessNameToHashTaintFlow( string s) + void IndirectTestProcessNameToHashTaintFlow(string s) { GetFvnHash(s); // BUG : ProcessNameToHashTaintFlow } void TestProcessNameToHashTaintFlow() { - GetFvnHash( System.Diagnostics.Process.GetCurrentProcess() ); // BUG : ProcessNameToHashTaintFlow + GetFvnHash(System.Diagnostics.Process.GetCurrentProcess()); // BUG : ProcessNameToHashTaintFlow string proc = System.Diagnostics.Process.GetCurrentProcess(); - IndirectTestProcessNameToHashTaintFlow( proc ); + IndirectTestProcessNameToHashTaintFlow(proc); } - void TestTimeBomb() + void TestTimeBomb() { DateTime lastWriteTime = System.IO.File.GetLastWriteTime("someFile"); int num = new Random().Next(288, 336); - if (DateTime.Now.CompareTo(lastWriteTime.AddHours((double)num)) >= 0) // BUG : Potential time bomb + if (DateTime.Now.CompareTo(lastWriteTime.AddHours((double)num)) >= 0) // BUG : Potential time bomb, currently not detected { // Some code here }