13
13
14
14
import cpp
15
15
16
- /** Holds if the release can occur twice. in the current block of catch and above in the block of try or other block catch . */
16
+ /** Holds if `vr` may be released in the `try` block associated with `cb`, or in a `catch` block prior to `cb` . */
17
17
pragma [ inline]
18
18
predicate doubleCallDelete ( CatchAnyBlock cb , Variable vr ) {
19
19
// Search for exceptions after freeing memory.
20
20
exists ( Expr e1 |
21
+ // `e1` is a delete of `vr`
21
22
(
22
23
e1 = vr .getAnAccess ( ) .getEnclosingStmt ( ) .( ExprStmt ) .getExpr ( ) .( DeleteArrayExpr ) or
23
24
e1 = vr .getAnAccess ( ) .getEnclosingStmt ( ) .( ExprStmt ) .getExpr ( ) .( DeleteExpr )
24
25
) and
25
26
e1 .getEnclosingFunction ( ) = cb .getEnclosingFunction ( ) and
26
27
(
28
+ // `e1` occurs in the `try` block associated with `cb`
27
29
e1 .getEnclosingStmt ( ) .getParentStmt * ( ) = cb .getTryStmt ( ) .getStmt ( ) and
30
+ // `e2` is a `throw` (or a function call that may throw) that occurs in the `try` block after `e1`
28
31
exists ( Expr e2 , ThrowExpr th |
29
32
(
30
33
e2 = th or
@@ -33,6 +36,7 @@ predicate doubleCallDelete(CatchAnyBlock cb, Variable vr) {
33
36
e2 .getEnclosingStmt ( ) .getParentStmt * ( ) = cb .getTryStmt ( ) .getStmt ( ) and
34
37
e1 .getASuccessor + ( ) = e2
35
38
) and
39
+ // there is no assignment `vr = 0` in the `try` block after `e1`
36
40
not exists ( AssignExpr ae |
37
41
ae .getLValue ( ) .( VariableAccess ) .getTarget ( ) = vr and
38
42
ae .getRValue ( ) .getValue ( ) = "0" and
@@ -44,12 +48,14 @@ predicate doubleCallDelete(CatchAnyBlock cb, Variable vr) {
44
48
exists ( CatchBlock cbt , Expr e2 , ThrowExpr th |
45
49
e1 .getEnclosingStmt ( ) .getParentStmt * ( ) = cbt and
46
50
exists ( cbt .getParameter ( ) ) and
51
+ // `e2` is a `throw` (or a function call that may throw) that occurs in the `catch` block after `e1`
47
52
(
48
53
e2 = th or
49
54
e2 = th .getEnclosingFunction ( ) .getACallToThisFunction ( )
50
55
) and
51
56
e2 .getEnclosingStmt ( ) .getParentStmt * ( ) = cbt and
52
57
e1 .getASuccessor + ( ) = e2 and
58
+ // there is no assignment `vr = 0` in the `catch` block after `e1`
53
59
not exists ( AssignExpr ae |
54
60
ae .getLValue ( ) .( VariableAccess ) .getTarget ( ) = vr and
55
61
ae .getRValue ( ) .getValue ( ) = "0" and
@@ -71,6 +77,7 @@ predicate pointerDereference(CatchAnyBlock cb, Variable vr, Variable vro) {
71
77
// Search exceptions before allocating memory.
72
78
exists ( Expr e0 , Expr e1 |
73
79
(
80
+ // `e0` is a `new` expression (or equivalent function call) assigned to `vro`
74
81
exists ( AssignExpr ase |
75
82
ase = vro .getAnAccess ( ) .getEnclosingStmt ( ) .( ExprStmt ) .getExpr ( ) .( AssignExpr ) and
76
83
(
@@ -90,6 +97,7 @@ predicate pointerDereference(CatchAnyBlock cb, Variable vr, Variable vro) {
90
97
vro = ase .getLValue ( ) .getAPredecessor ( ) .( VariableAccess ) .getTarget ( )
91
98
)
92
99
) and
100
+ // `e1` is a `new` expression (or equivalent function call) assigned to `vr`
93
101
exists ( AssignExpr ase |
94
102
ase = vr .getAnAccess ( ) .getEnclosingStmt ( ) .( ExprStmt ) .getExpr ( ) .( AssignExpr ) and
95
103
(
@@ -101,6 +109,7 @@ predicate pointerDereference(CatchAnyBlock cb, Variable vr, Variable vro) {
101
109
e0 .getASuccessor * ( ) = e1 and
102
110
e0 .getEnclosingStmt ( ) .getParentStmt * ( ) = cb .getTryStmt ( ) .getStmt ( ) and
103
111
e1 .getEnclosingStmt ( ) .getParentStmt * ( ) = cb .getTryStmt ( ) .getStmt ( ) and
112
+ // `e2` is a `throw` (or a function call that may throw) that occurs in the `try` block before `e0`
104
113
exists ( Expr e2 , ThrowExpr th |
105
114
(
106
115
e2 = th or
@@ -159,7 +168,7 @@ where
159
168
) and
160
169
doubleCallDelete ( cb , vr ) and
161
170
msg =
162
- "perhaps a situation of uncertainty due to the repeated call of the delete function for the variable "
171
+ "This allocation may have been released in the try block or a previous catch block. "
163
172
+ vr .getName ( )
164
173
)
165
174
select cb , msg
0 commit comments