@@ -2,20 +2,6 @@ import cpp
22import semmle.code.cpp.dataflow.new.DataFlow
33private import semmle.code.cpp.ir.IR
44
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-
195/**
206 * Holds if `(b1, i1)` strictly post-dominates `(b2, i2)`
217 */
@@ -38,27 +24,38 @@ predicate strictlyDominates(IRBlock b1, int i1, IRBlock b2, int i2) {
3824 b1 .strictlyDominates ( b2 )
3925}
4026
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 ) ;
4833
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 ( ) }
5547}
5648
5749/**
5850 * Constructs a `FlowFromFreeConfig` module that can be used to find flow between
5951 * 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.
6057 */
61- module FlowFromFree< isSinkSig / 2 isASink , isExcludedSig / 2 isExcluded > {
58+ module FlowFromFree< FlowFromFreeParamSig P > {
6259 module FlowFromFreeConfig implements DataFlow:: StateConfigSig {
6360 class FlowState instanceof Expr {
6461 FlowState ( ) { isFree ( _, _, this , _) }
@@ -70,11 +67,12 @@ module FlowFromFree<isSinkSig/2 isASink, isExcludedSig/2 isExcluded> {
7067
7168 pragma [ inline]
7269 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
7673 e != state and
77- not isExcluded ( dealloc , e )
74+ not P:: isExcluded ( dealloc , e ) and
75+ P:: sourceSinkIsRelated ( source , sink )
7876 )
7977 }
8078
@@ -129,3 +127,19 @@ predicate isExFreePoolCall(FunctionCall fc, Expr e) {
129127 fc .getTarget ( ) .hasGlobalName ( "ExFreePool" )
130128 )
131129}
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