10
10
* external/cwe/cwe-404
11
11
*/
12
12
import cpp
13
+ import Critical.NewDelete
13
14
14
- // List pairs of functions that do resource acquisition/release
15
- // Extend this to add custom function pairs. As written the query
16
- // will only apply if the resource is the *return value* of the
17
- // first call and a *parameter* to the second. Other cases should
18
- // be handled differently.
19
- predicate resourceManagementPair ( string acquire , string release ) {
20
-
21
- ( acquire = "fopen" and release = "fclose" )
22
- or
23
- ( acquire = "open" and release = "close" )
24
- or
25
- ( acquire = "socket" and release = "close" )
26
-
27
- }
28
-
29
- // List functions that return malloc-allocated memory. Customize
30
- // to list your own functions there
31
- predicate mallocFunction ( Function malloc ) {
32
- malloc .hasName ( "malloc" ) or malloc .hasName ( "calloc" ) or // Not realloc: doesn't acquire it, really
33
- malloc .hasName ( "strdup" )
15
+ /**
16
+ * An expression that acquires a resource, and the kind of resource that is acquired. The
17
+ * kind of a resource indicates which acquisition/release expressions can be paired.
18
+ */
19
+ predicate acquireExpr ( Expr acquire , string kind ) {
20
+ exists ( FunctionCall fc , Function f , string name |
21
+ fc = acquire and
22
+ f = fc .getTarget ( ) and
23
+ name = f .getName ( ) and
24
+ (
25
+ (
26
+ name = "fopen" and
27
+ kind = "file"
28
+ ) or (
29
+ name = "open" and
30
+ kind = "file descriptor"
31
+ ) or (
32
+ name = "socket" and
33
+ kind = "file descriptor"
34
+ )
35
+ )
36
+ ) or (
37
+ allocExpr ( acquire , kind )
38
+ )
34
39
}
35
40
36
- private predicate isRelease ( string release ) {
37
- resourceManagementPair ( _, release ) or
38
- release = "free" or
39
- release = "delete"
41
+ /**
42
+ * An expression that releases a resource, and the kind of resource that is released. The
43
+ * kind of a resource indicates which acquisition/release expressions can be paired.
44
+ */
45
+ predicate releaseExpr ( Expr release , Expr resource , string kind ) {
46
+ exists ( FunctionCall fc , Function f , string name |
47
+ fc = release and
48
+ f = fc .getTarget ( ) and
49
+ name = f .getName ( ) and
50
+ (
51
+ (
52
+ name = "fclose" and
53
+ resource = fc .getArgument ( 0 ) and
54
+ kind = "file"
55
+ ) or (
56
+ name = "close" and
57
+ resource = fc .getArgument ( 0 ) and
58
+ kind = "file descriptor"
59
+ )
60
+ )
61
+ ) or exists ( string releaseKind |
62
+ freeExpr ( release , resource , releaseKind ) and
63
+ (
64
+ (
65
+ kind = "malloc" and
66
+ releaseKind = "free"
67
+ ) or (
68
+ kind = "new" and
69
+ releaseKind = "delete"
70
+ ) or (
71
+ kind = "new[]" and
72
+ releaseKind = "delete[]"
73
+ )
74
+ )
75
+ )
40
76
}
41
77
42
78
/**
@@ -52,35 +88,23 @@ Expr exprOrDereference(Expr e) {
52
88
* Holds if the expression `e` releases expression `released`, whether directly
53
89
* or via one or more function call(s).
54
90
*/
55
- private predicate exprReleases ( Expr e , Expr released , string releaseType ) {
91
+ private predicate exprReleases ( Expr e , Expr released , string kind ) {
56
92
(
57
- // `e` is a call to a release function and `released` is any argument
58
- e .( FunctionCall ) .getTarget ( ) .getName ( ) = releaseType and
59
- isRelease ( releaseType ) and
60
- e .( FunctionCall ) .getAnArgument ( ) = released
61
- ) or (
62
- // `e` is a call to `delete` and `released` is the target
63
- e .( DeleteExpr ) .getExpr ( ) = released and
64
- releaseType = "delete"
65
- ) or (
66
- // `e` is a call to `delete[]` and `released` is the target
67
- e .( DeleteArrayExpr ) .getExpr ( ) = released and
68
- releaseType = "delete"
93
+ // `e` is a call to a release function and `released` is the released argument
94
+ releaseExpr ( e , released , kind )
69
95
) or exists ( Function f , int arg |
70
96
// `e` is a call to a function that releases one of it's parameters,
71
97
// and `released` is the corresponding argument
72
98
e .( FunctionCall ) .getTarget ( ) = f and
73
99
e .( FunctionCall ) .getArgument ( arg ) = released and
74
- exprReleases ( _, exprOrDereference ( f .getParameter ( arg ) .getAnAccess ( ) ) , releaseType )
75
- ) or exists ( Function f , Expr innerThis |
100
+ exprReleases ( _, exprOrDereference ( f .getParameter ( arg ) .getAnAccess ( ) ) , kind )
101
+ ) or exists ( Function f , ThisExpr innerThis |
76
102
// `e` is a call to a method that releases `this`, and `released`
77
103
// is the object that is called
78
104
e .( FunctionCall ) .getTarget ( ) = f and
79
105
e .( FunctionCall ) .getQualifier ( ) = exprOrDereference ( released ) and
80
106
innerThis .getEnclosingFunction ( ) = f and
81
- exprReleases ( _, innerThis , releaseType ) and
82
- innerThis instanceof ThisExpr and
83
- releaseType = "delete"
107
+ exprReleases ( _, innerThis , kind )
84
108
)
85
109
}
86
110
@@ -109,28 +133,17 @@ class Resource extends MemberVariable {
109
133
)
110
134
}
111
135
112
- predicate acquisitionWithRequiredRelease ( Expr acquire , string releaseName ) {
113
- acquire .( Assignment ) .getLValue ( ) = this .getAnAccess ( ) and
136
+ predicate acquisitionWithRequiredRelease ( Assignment acquireAssign , string kind ) {
137
+ // acquireAssign is an assignment to this resource
138
+ acquireAssign .( Assignment ) .getLValue ( ) = this .getAnAccess ( ) and
114
139
// Should be in this class, but *any* member method will do
115
- this .inSameClass ( acquire ) and
140
+ this .inSameClass ( acquireAssign ) and
116
141
// Check that it is an acquisition function and return the corresponding free
117
- (
118
- exists ( Function f | f = acquire .( Assignment ) .getRValue ( ) .( FunctionCall ) .getTarget ( ) and
119
- ( resourceManagementPair ( f .getName ( ) , releaseName ) or ( mallocFunction ( f ) and ( releaseName = "free" or releaseName = "delete" ) ) )
120
- )
121
- or
122
- ( acquire = this .getANew ( ) and releaseName = "delete" )
123
- )
124
- }
125
-
126
- private Assignment getANew ( ) {
127
- result .getLValue ( ) = this .getAnAccess ( ) and
128
- ( result .getRValue ( ) instanceof NewExpr or result .getRValue ( ) instanceof NewArrayExpr ) and
129
- this .inSameClass ( result )
142
+ acquireExpr ( acquireAssign .getRValue ( ) , kind )
130
143
}
131
144
132
- Expr getAReleaseExpr ( string releaseName ) {
133
- exprReleases ( result , this .getAnAccess ( ) , releaseName )
145
+ Expr getAReleaseExpr ( string kind ) {
146
+ exprReleases ( result , this .getAnAccess ( ) , kind )
134
147
}
135
148
}
136
149
0 commit comments