1010 * external/cwe/cwe-404
1111 */
1212import cpp
13+ import Critical.NewDelete
1314
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+ )
3439}
3540
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+ )
4076}
4177
4278/**
@@ -52,35 +88,23 @@ Expr exprOrDereference(Expr e) {
5288 * Holds if the expression `e` releases expression `released`, whether directly
5389 * or via one or more function call(s).
5490 */
55- private predicate exprReleases ( Expr e , Expr released , string releaseType ) {
91+ private predicate exprReleases ( Expr e , Expr released , string kind ) {
5692 (
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 )
6995 ) or exists ( Function f , int arg |
7096 // `e` is a call to a function that releases one of it's parameters,
7197 // and `released` is the corresponding argument
7298 e .( FunctionCall ) .getTarget ( ) = f and
7399 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 |
76102 // `e` is a call to a method that releases `this`, and `released`
77103 // is the object that is called
78104 e .( FunctionCall ) .getTarget ( ) = f and
79105 e .( FunctionCall ) .getQualifier ( ) = exprOrDereference ( released ) and
80106 innerThis .getEnclosingFunction ( ) = f and
81- exprReleases ( _, innerThis , releaseType ) and
82- innerThis instanceof ThisExpr and
83- releaseType = "delete"
107+ exprReleases ( _, innerThis , kind )
84108 )
85109}
86110
@@ -109,28 +133,17 @@ class Resource extends MemberVariable {
109133 )
110134 }
111135
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
114139 // Should be in this class, but *any* member method will do
115- this .inSameClass ( acquire ) and
140+ this .inSameClass ( acquireAssign ) and
116141 // 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 )
130143 }
131144
132- Expr getAReleaseExpr ( string releaseName ) {
133- exprReleases ( result , this .getAnAccess ( ) , releaseName )
145+ Expr getAReleaseExpr ( string kind ) {
146+ exprReleases ( result , this .getAnAccess ( ) , kind )
134147 }
135148}
136149
0 commit comments