Skip to content

Commit 587e673

Browse files
authored
Merge pull request #11060 from hvitved/dataflow/path-node-reach-charpred
Data flow: Restrict public `PathNode`s to those that may reach a sink
2 parents 331b8c0 + 1711efc commit 587e673

File tree

58 files changed

+2946
-2765
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

58 files changed

+2946
-2765
lines changed

cpp/ql/lib/experimental/semmle/code/cpp/ir/dataflow/internal/DataFlowImpl.qll

Lines changed: 79 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -2874,54 +2874,16 @@ private class AccessPathCons1 extends AccessPath, TAccessPathCons1 {
28742874
}
28752875
}
28762876

2877-
/**
2878-
* A `Node` augmented with a call context (except for sinks), an access path, and a configuration.
2879-
* Only those `PathNode`s that are reachable from a source are generated.
2880-
*/
2881-
class PathNode extends TPathNode {
2882-
/** Gets a textual representation of this element. */
2883-
string toString() { none() }
2884-
2885-
/**
2886-
* Gets a textual representation of this element, including a textual
2887-
* representation of the call context.
2888-
*/
2889-
string toStringWithContext() { none() }
2890-
2891-
/**
2892-
* Holds if this element is at the specified location.
2893-
* The location spans column `startcolumn` of line `startline` to
2894-
* column `endcolumn` of line `endline` in file `filepath`.
2895-
* For more information, see
2896-
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
2897-
*/
2898-
predicate hasLocationInfo(
2899-
string filepath, int startline, int startcolumn, int endline, int endcolumn
2900-
) {
2901-
none()
2902-
}
2903-
2904-
/** Gets the underlying `Node`. */
2905-
final Node getNode() { this.(PathNodeImpl).getNodeEx().projectToNode() = result }
2906-
2877+
abstract private class PathNodeImpl extends TPathNode {
29072878
/** Gets the `FlowState` of this node. */
2908-
FlowState getState() { none() }
2879+
abstract FlowState getState();
29092880

29102881
/** Gets the associated configuration. */
2911-
Configuration getConfiguration() { none() }
2912-
2913-
/** Gets a successor of this node, if any. */
2914-
final PathNode getASuccessor() {
2915-
result = this.(PathNodeImpl).getANonHiddenSuccessor() and
2916-
reach(this) and
2917-
reach(result)
2918-
}
2882+
abstract Configuration getConfiguration();
29192883

29202884
/** Holds if this node is a source. */
2921-
predicate isSource() { none() }
2922-
}
2885+
abstract predicate isSource();
29232886

2924-
abstract private class PathNodeImpl extends PathNode {
29252887
abstract PathNodeImpl getASuccessorImpl();
29262888

29272889
private PathNodeImpl getASuccessorIfHidden() {
@@ -2967,13 +2929,23 @@ abstract private class PathNodeImpl extends PathNode {
29672929
result = " <" + this.(PathNodeMid).getCallContext().toString() + ">"
29682930
}
29692931

2970-
override string toString() { result = this.getNodeEx().toString() + this.ppAp() }
2932+
/** Gets a textual representation of this element. */
2933+
string toString() { result = this.getNodeEx().toString() + this.ppAp() }
29712934

2972-
override string toStringWithContext() {
2973-
result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx()
2974-
}
2935+
/**
2936+
* Gets a textual representation of this element, including a textual
2937+
* representation of the call context.
2938+
*/
2939+
string toStringWithContext() { result = this.getNodeEx().toString() + this.ppAp() + this.ppCtx() }
29752940

2976-
override predicate hasLocationInfo(
2941+
/**
2942+
* Holds if this element is at the specified location.
2943+
* The location spans column `startcolumn` of line `startline` to
2944+
* column `endcolumn` of line `endline` in file `filepath`.
2945+
* For more information, see
2946+
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
2947+
*/
2948+
predicate hasLocationInfo(
29772949
string filepath, int startline, int startcolumn, int endline, int endcolumn
29782950
) {
29792951
this.getNodeEx().hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
@@ -2986,14 +2958,59 @@ private predicate directReach(PathNodeImpl n) {
29862958
}
29872959

29882960
/** Holds if `n` can reach a sink or is used in a subpath that can reach a sink. */
2989-
private predicate reach(PathNode n) { directReach(n) or Subpaths::retReach(n) }
2961+
private predicate reach(PathNodeImpl n) { directReach(n) or Subpaths::retReach(n) }
29902962

29912963
/** Holds if `n1.getASuccessor() = n2` and `n2` can reach a sink. */
2992-
private predicate pathSucc(PathNodeImpl n1, PathNode n2) {
2964+
private predicate pathSucc(PathNodeImpl n1, PathNodeImpl n2) {
29932965
n1.getANonHiddenSuccessor() = n2 and directReach(n2)
29942966
}
29952967

2996-
private predicate pathSuccPlus(PathNode n1, PathNode n2) = fastTC(pathSucc/2)(n1, n2)
2968+
private predicate pathSuccPlus(PathNodeImpl n1, PathNodeImpl n2) = fastTC(pathSucc/2)(n1, n2)
2969+
2970+
/**
2971+
* A `Node` augmented with a call context (except for sinks), an access path, and a configuration.
2972+
* Only those `PathNode`s that are reachable from a source, and which can reach a sink, are generated.
2973+
*/
2974+
class PathNode instanceof PathNodeImpl {
2975+
PathNode() { reach(this) }
2976+
2977+
/** Gets a textual representation of this element. */
2978+
final string toString() { result = super.toString() }
2979+
2980+
/**
2981+
* Gets a textual representation of this element, including a textual
2982+
* representation of the call context.
2983+
*/
2984+
final string toStringWithContext() { result = super.toStringWithContext() }
2985+
2986+
/**
2987+
* Holds if this element is at the specified location.
2988+
* The location spans column `startcolumn` of line `startline` to
2989+
* column `endcolumn` of line `endline` in file `filepath`.
2990+
* For more information, see
2991+
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
2992+
*/
2993+
final predicate hasLocationInfo(
2994+
string filepath, int startline, int startcolumn, int endline, int endcolumn
2995+
) {
2996+
super.hasLocationInfo(filepath, startline, startcolumn, endline, endcolumn)
2997+
}
2998+
2999+
/** Gets the underlying `Node`. */
3000+
final Node getNode() { super.getNodeEx().projectToNode() = result }
3001+
3002+
/** Gets the `FlowState` of this node. */
3003+
final FlowState getState() { result = super.getState() }
3004+
3005+
/** Gets the associated configuration. */
3006+
final Configuration getConfiguration() { result = super.getConfiguration() }
3007+
3008+
/** Gets a successor of this node, if any. */
3009+
final PathNode getASuccessor() { result = super.getANonHiddenSuccessor() }
3010+
3011+
/** Holds if this node is a source. */
3012+
final predicate isSource() { super.isSource() }
3013+
}
29973014

29983015
/**
29993016
* Provides the query predicates needed to include a graph in a path-problem query.
@@ -3004,7 +3021,7 @@ module PathGraph {
30043021

30053022
/** Holds if `n` is a node in the graph of data flow path explanations. */
30063023
query predicate nodes(PathNode n, string key, string val) {
3007-
reach(n) and key = "semmle.label" and val = n.toString()
3024+
key = "semmle.label" and val = n.toString()
30083025
}
30093026

30103027
/**
@@ -3013,11 +3030,7 @@ module PathGraph {
30133030
* `ret -> out` is summarized as the edge `arg -> out`.
30143031
*/
30153032
query predicate subpaths(PathNode arg, PathNode par, PathNode ret, PathNode out) {
3016-
Subpaths::subpaths(arg, par, ret, out) and
3017-
reach(arg) and
3018-
reach(par) and
3019-
reach(ret) and
3020-
reach(out)
3033+
Subpaths::subpaths(arg, par, ret, out)
30213034
}
30223035
}
30233036

@@ -3399,22 +3412,22 @@ private module Subpaths {
33993412
*/
34003413
pragma[nomagic]
34013414
private predicate subpaths02(
3402-
PathNode arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
3415+
PathNodeImpl arg, ParamNodeEx par, SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind,
34033416
NodeEx out, FlowState sout, AccessPath apout
34043417
) {
34053418
subpaths01(arg, par, sc, innercc, kind, out, sout, apout) and
34063419
out.asNode() = kind.getAnOutNode(_)
34073420
}
34083421

34093422
pragma[nomagic]
3410-
private Configuration getPathNodeConf(PathNode n) { result = n.getConfiguration() }
3423+
private Configuration getPathNodeConf(PathNodeImpl n) { result = n.getConfiguration() }
34113424

34123425
/**
34133426
* Holds if `(arg, par, ret, out)` forms a subpath-tuple.
34143427
*/
34153428
pragma[nomagic]
34163429
private predicate subpaths03(
3417-
PathNode arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout
3430+
PathNodeImpl arg, ParamNodeEx par, PathNodeMid ret, NodeEx out, FlowState sout, AccessPath apout
34183431
) {
34193432
exists(SummaryCtxSome sc, CallContext innercc, ReturnKindExt kind, RetNodeEx retnode |
34203433
subpaths02(arg, par, sc, innercc, kind, out, sout, apout) and
@@ -3444,7 +3457,7 @@ private module Subpaths {
34443457
* a subpath between `par` and `ret` with the connecting edges `arg -> par` and
34453458
* `ret -> out` is summarized as the edge `arg -> out`.
34463459
*/
3447-
predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNode out) {
3460+
predicate subpaths(PathNodeImpl arg, PathNodeImpl par, PathNodeImpl ret, PathNodeImpl out) {
34483461
exists(ParamNodeEx p, NodeEx o, FlowState sout, AccessPath apout, PathNodeMid out0 |
34493462
pragma[only_bind_into](arg).getANonHiddenSuccessor() = pragma[only_bind_into](out0) and
34503463
subpaths03(pragma[only_bind_into](arg), p, localStepToHidden*(ret), o, sout, apout) and
@@ -3460,7 +3473,7 @@ private module Subpaths {
34603473
* Holds if `n` can reach a return node in a summarized subpath that can reach a sink.
34613474
*/
34623475
predicate retReach(PathNodeImpl n) {
3463-
exists(PathNode out | subpaths(_, _, n, out) | directReach(out) or retReach(out))
3476+
exists(PathNodeImpl out | subpaths(_, _, n, out) | directReach(out) or retReach(out))
34643477
or
34653478
exists(PathNodeImpl mid |
34663479
retReach(mid) and
@@ -3477,11 +3490,12 @@ private module Subpaths {
34773490
* sinks.
34783491
*/
34793492
private predicate flowsTo(
3480-
PathNode flowsource, PathNodeSink flowsink, Node source, Node sink, Configuration configuration
3493+
PathNodeImpl flowsource, PathNodeSink flowsink, Node source, Node sink,
3494+
Configuration configuration
34813495
) {
34823496
flowsource.isSource() and
34833497
flowsource.getConfiguration() = configuration and
3484-
flowsource.(PathNodeImpl).getNodeEx().asNode() = source and
3498+
flowsource.getNodeEx().asNode() = source and
34853499
(flowsource = flowsink or pathSuccPlus(flowsource, flowsink)) and
34863500
flowsink.getNodeEx().asNode() = sink
34873501
}
@@ -3504,14 +3518,14 @@ private predicate finalStats(
35043518
fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0)) and
35053519
conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap)) and
35063520
states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state)) and
3507-
tuples = count(PathNode pn)
3521+
tuples = count(PathNodeImpl pn)
35083522
or
35093523
fwd = false and
35103524
nodes = count(NodeEx n0 | exists(PathNodeImpl pn | pn.getNodeEx() = n0 and reach(pn))) and
35113525
fields = count(TypedContent f0 | exists(PathNodeMid pn | pn.getAp().getHead() = f0 and reach(pn))) and
35123526
conscand = count(AccessPath ap | exists(PathNodeMid pn | pn.getAp() = ap and reach(pn))) and
35133527
states = count(FlowState state | exists(PathNodeMid pn | pn.getState() = state and reach(pn))) and
3514-
tuples = count(PathNode pn | reach(pn))
3528+
tuples = count(PathNode pn)
35153529
}
35163530

35173531
/**

0 commit comments

Comments
 (0)