@@ -2,20 +2,6 @@ import cpp
2
2
import semmle.code.cpp.dataflow.new.DataFlow
3
3
private import semmle.code.cpp.ir.IR
4
4
5
- /**
6
- * Signature for a predicate that holds if `n.asExpr() = e` and `n` is a sink in
7
- * the `FlowFromFreeConfig` module.
8
- */
9
- private signature predicate isSinkSig ( DataFlow:: Node n , Expr e ) ;
10
-
11
- /**
12
- * Holds if `dealloc` is a deallocation expression and `e` is an expression such
13
- * that `isFree(_, e)` holds for some `isFree` predicate satisfying `isSinkSig`,
14
- * and this source-sink pair should be excluded from the analysis.
15
- */
16
- bindingset [ dealloc, e]
17
- private signature predicate isExcludedSig ( DeallocationExpr dealloc , Expr e ) ;
18
-
19
5
/**
20
6
* Holds if `(b1, i1)` strictly post-dominates `(b2, i2)`
21
7
*/
@@ -38,27 +24,38 @@ predicate strictlyDominates(IRBlock b1, int i1, IRBlock b2, int i2) {
38
24
b1 .strictlyDominates ( b2 )
39
25
}
40
26
41
- predicate sinkStrictlyPostDominatesSource ( DataFlow:: Node source , DataFlow:: Node sink ) {
42
- exists ( IRBlock b1 , int i1 , IRBlock b2 , int i2 |
43
- source .hasIndexInBlock ( b1 , i1 ) and
44
- sink .hasIndexInBlock ( b2 , i2 ) and
45
- strictlyPostDominates ( b2 , i2 , b1 , i1 )
46
- )
47
- }
27
+ signature module FlowFromFreeParamSig {
28
+ /**
29
+ * Signature for a predicate that holds if `n.asExpr() = e` and `n` is a sink in
30
+ * the `FlowFromFreeConfig` module.
31
+ */
32
+ predicate isSink ( DataFlow:: Node n , Expr e ) ;
48
33
49
- predicate sourceStrictlyDominatesSink ( DataFlow:: Node source , DataFlow:: Node sink ) {
50
- exists ( IRBlock b1 , int i1 , IRBlock b2 , int i2 |
51
- source .hasIndexInBlock ( b1 , i1 ) and
52
- sink .hasIndexInBlock ( b2 , i2 ) and
53
- strictlyDominates ( b1 , i1 , b2 , i2 )
54
- )
34
+ /**
35
+ * Holds if `dealloc` is a deallocation expression and `e` is an expression such
36
+ * that `isFree(_, e)` holds for some `isFree` predicate satisfying `isSinkSig`,
37
+ * and this source-sink pair should be excluded from the analysis.
38
+ */
39
+ bindingset [ dealloc, e]
40
+ predicate isExcluded ( DeallocationExpr dealloc , Expr e ) ;
41
+
42
+ /**
43
+ * Holds if `sink` should be considered a `sink` when the source of flow is `source`.
44
+ */
45
+ bindingset [ source, sink]
46
+ default predicate sourceSinkIsRelated ( DataFlow:: Node source , DataFlow:: Node sink ) { any ( ) }
55
47
}
56
48
57
49
/**
58
50
* Constructs a `FlowFromFreeConfig` module that can be used to find flow between
59
51
* a pointer being freed by some deallocation function, and a user-specified sink.
52
+ *
53
+ * In order to reduce false positives, the set of sinks is restricted to only those
54
+ * that satisfy at least one of the following two criteria:
55
+ * 1. The source dominates the sink, or
56
+ * 2. The sink post-dominates the source.
60
57
*/
61
- module FlowFromFree< isSinkSig / 2 isASink , isExcludedSig / 2 isExcluded > {
58
+ module FlowFromFree< FlowFromFreeParamSig P > {
62
59
module FlowFromFreeConfig implements DataFlow:: StateConfigSig {
63
60
class FlowState instanceof Expr {
64
61
FlowState ( ) { isFree ( _, _, this , _) }
@@ -70,11 +67,12 @@ module FlowFromFree<isSinkSig/2 isASink, isExcludedSig/2 isExcluded> {
70
67
71
68
pragma [ inline]
72
69
predicate isSink ( DataFlow:: Node sink , FlowState state ) {
73
- exists ( Expr e , DeallocationExpr dealloc |
74
- isASink ( sink , e ) and
75
- isFree ( _ , _, state , dealloc ) and
70
+ exists ( Expr e , DataFlow :: Node source , DeallocationExpr dealloc |
71
+ P :: isSink ( sink , e ) and
72
+ isFree ( source , _, state , dealloc ) and
76
73
e != state and
77
- not isExcluded ( dealloc , e )
74
+ not P:: isExcluded ( dealloc , e ) and
75
+ P:: sourceSinkIsRelated ( source , sink )
78
76
)
79
77
}
80
78
@@ -129,3 +127,19 @@ predicate isExFreePoolCall(FunctionCall fc, Expr e) {
129
127
fc .getTarget ( ) .hasGlobalName ( "ExFreePool" )
130
128
)
131
129
}
130
+
131
+ /**
132
+ * Holds if either `source` strictly dominates `sink`, or `sink` strictly
133
+ * post-dominates `source`.
134
+ */
135
+ bindingset [ source, sink]
136
+ predicate defaultSourceSinkIsRelated ( DataFlow:: Node source , DataFlow:: Node sink ) {
137
+ exists ( IRBlock b1 , int i1 , IRBlock b2 , int i2 |
138
+ source .hasIndexInBlock ( b1 , i1 ) and
139
+ sink .hasIndexInBlock ( b2 , i2 )
140
+ |
141
+ strictlyDominates ( b1 , i1 , b2 , i2 )
142
+ or
143
+ strictlyPostDominates ( b2 , i2 , b1 , i1 )
144
+ )
145
+ }
0 commit comments