mirror of
https://github.com/github/codeql.git
synced 2025-12-24 04:36:35 +01:00
Merge pull request #11060 from hvitved/dataflow/path-node-reach-charpred
Data flow: Restrict public `PathNode`s to those that may reach a sink
This commit is contained in:
@@ -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)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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,62 +116,30 @@ 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 |
|
||||
@@ -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,29 +525,15 @@ 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 |
|
||||
@@ -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: ... = ... |
|
||||
|
||||
@@ -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) |
|
||||
|
||||
@@ -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) |
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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) |
|
||||
|
||||
@@ -17,11 +17,8 @@ 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 |
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -56,42 +56,30 @@ 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 |
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -272,29 +272,20 @@ 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 |
|
||||
@@ -303,51 +294,35 @@ nodes
|
||||
| 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 |
|
||||
@@ -356,108 +331,69 @@ nodes
|
||||
| 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
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -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 | ... = ... | ... = ... |
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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'. |
|
||||
|
||||
@@ -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 |
|
||||
|
||||
@@ -21,7 +21,8 @@ namespace System.Diagnostics
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
@@ -67,7 +68,7 @@ class External {
|
||||
{
|
||||
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
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user