Skip to content

Commit 9f4b725

Browse files
authored
Add files via upload
1 parent 10f6cab commit 9f4b725

File tree

3 files changed

+250
-0
lines changed

3 files changed

+250
-0
lines changed
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
...
2+
fs = socket(AF_UNIX, SOCK_STREAM, 0)
3+
...
4+
close(fs);
5+
fs = -1; // GOOD
6+
...
7+
8+
...
9+
fs = socket(AF_UNIX, SOCK_STREAM, 0)
10+
...
11+
close(fs);
12+
if(fs) close(fs); // BAD
13+
...
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<!DOCTYPE qhelp PUBLIC
2+
"-//Semmle//qhelp//EN"
3+
"qhelp.dtd">
4+
<qhelp>
5+
<overview>
6+
<p>Double release of the descriptor can lead to a crash of the program. Requires the attention of developers.</p>
7+
8+
</overview>
9+
<recommendation>
10+
<p>We recommend that you exclude situations of possible double release.</p>
11+
12+
</recommendation>
13+
<example>
14+
<p>The following example demonstrates an erroneous and corrected use of descriptor deallocation.</p>
15+
<sample src="DoubleFree.c" />
16+
17+
</example>
18+
<references>
19+
20+
<li>
21+
CERT C Coding Standard:
22+
<a href="https://wiki.sei.cmu.edu/confluence/display/c/FIO46-C.+Do+not+access+a+closed+file">FIO46-C. Do not access a closed file</a>.
23+
</li>
24+
25+
</references>
26+
</qhelp>
Lines changed: 211 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,211 @@
1+
/**
2+
* @name Errors When Double Release
3+
* @description Double release of the descriptor can lead to a crash of the program.
4+
* @kind problem
5+
* @id cpp/double-release
6+
* @problem.severity warning
7+
* @precision medium
8+
* @tags security
9+
* external/cwe/cwe-675
10+
* external/cwe/cwe-666
11+
*/
12+
13+
import cpp
14+
import semmle.code.cpp.commons.File
15+
import semmle.code.cpp.valuenumbering.GlobalValueNumbering
16+
import semmle.code.cpp.valuenumbering.HashCons
17+
18+
/**
19+
* A function call that potentially does not return (such as `exit`).
20+
*/
21+
class CallMayNotReturn extends FunctionCall {
22+
CallMayNotReturn() {
23+
// call that is known to not return
24+
not exists(this.(ControlFlowNode).getASuccessor())
25+
or
26+
// call to another function that may not return
27+
exists(CallMayNotReturn exit | getTarget() = exit.getEnclosingFunction())
28+
or
29+
exists(ThrowExpr tex | tex = this.(ControlFlowNode).getASuccessor())
30+
}
31+
}
32+
33+
/** Holds if there are no assignment expressions to the function argument. */
34+
pragma[inline]
35+
predicate checkChangeVariable(FunctionCall fc0, FunctionCall fc1, FunctionCall fc2) {
36+
not exists(Expr exptmp |
37+
(
38+
exptmp = fc0.getArgument(0).(VariableAccess).getTarget().getAnAssignedValue() or
39+
exptmp.(AddressOfExpr).getOperand() =
40+
fc0.getArgument(0).(VariableAccess).getTarget().getAnAccess()
41+
) and
42+
exptmp = fc1.getASuccessor*() and
43+
exptmp = fc2.getAPredecessor*()
44+
) and
45+
(
46+
(
47+
not fc0.getArgument(0) instanceof PointerFieldAccess and
48+
not fc0.getArgument(0) instanceof ValueFieldAccess
49+
or
50+
fc0.getArgument(0).(VariableAccess).getQualifier() instanceof ThisExpr
51+
)
52+
or
53+
not exists(Expr exptmp |
54+
(
55+
exptmp =
56+
fc0.getArgument(0)
57+
.(VariableAccess)
58+
.getQualifier()
59+
.(VariableAccess)
60+
.getTarget()
61+
.getAnAssignedValue() or
62+
exptmp.(AddressOfExpr).getOperand() =
63+
fc0.getArgument(0)
64+
.(VariableAccess)
65+
.getQualifier()
66+
.(VariableAccess)
67+
.getTarget()
68+
.getAnAccess()
69+
) and
70+
exptmp = fc1.getASuccessor*() and
71+
exptmp = fc2.getAPredecessor*()
72+
)
73+
)
74+
}
75+
76+
/** Holds if the underlying expression is a call to the close function. Provided that the function parameter does not change after the call. */
77+
predicate closeReturn(FunctionCall fc) {
78+
fcloseCall(fc, _) and
79+
not exists(Expr exptmp |
80+
(
81+
exptmp = fc.getArgument(0).(VariableAccess).getTarget().getAnAssignedValue() or
82+
exptmp.(AddressOfExpr).getOperand() =
83+
fc.getArgument(0).(VariableAccess).getTarget().getAnAccess()
84+
) and
85+
exptmp = fc.getASuccessor*()
86+
) and
87+
(
88+
(
89+
not fc.getArgument(0) instanceof PointerFieldAccess and
90+
not fc.getArgument(0) instanceof ValueFieldAccess
91+
or
92+
fc.getArgument(0).(VariableAccess).getQualifier() instanceof ThisExpr
93+
)
94+
or
95+
not exists(Expr exptmp |
96+
(
97+
exptmp =
98+
fc.getArgument(0)
99+
.(VariableAccess)
100+
.getQualifier()
101+
.(VariableAccess)
102+
.getTarget()
103+
.getAnAssignedValue() or
104+
exptmp.(AddressOfExpr).getOperand() =
105+
fc.getArgument(0)
106+
.(VariableAccess)
107+
.getQualifier()
108+
.(VariableAccess)
109+
.getTarget()
110+
.getAnAccess()
111+
) and
112+
exptmp = fc.getASuccessor*()
113+
)
114+
)
115+
}
116+
117+
/** Holds if the underlying expression is a call to the close function. Provided that the function parameter does not change before the call. */
118+
predicate closeWithoutChangeBefore(FunctionCall fc) {
119+
fcloseCall(fc, _) and
120+
not exists(Expr exptmp |
121+
(
122+
exptmp = fc.getArgument(0).(VariableAccess).getTarget().getAnAssignedValue() or
123+
exptmp.(AddressOfExpr).getOperand() =
124+
fc.getArgument(0).(VariableAccess).getTarget().getAnAccess()
125+
) and
126+
exptmp = fc.getAPredecessor*()
127+
) and
128+
(
129+
(
130+
not fc.getArgument(0) instanceof PointerFieldAccess and
131+
not fc.getArgument(0) instanceof ValueFieldAccess
132+
or
133+
fc.getArgument(0).(VariableAccess).getQualifier() instanceof ThisExpr
134+
)
135+
or
136+
not exists(Expr exptmp |
137+
(
138+
exptmp =
139+
fc.getArgument(0)
140+
.(VariableAccess)
141+
.getQualifier()
142+
.(VariableAccess)
143+
.getTarget()
144+
.getAnAssignedValue() or
145+
exptmp.(AddressOfExpr).getOperand() =
146+
fc.getArgument(0)
147+
.(VariableAccess)
148+
.getQualifier()
149+
.(VariableAccess)
150+
.getTarget()
151+
.getAnAccess()
152+
) and
153+
exptmp = fc.getAPredecessor*()
154+
)
155+
)
156+
}
157+
158+
/** Holds, if a sequential call of the specified functions is possible, via a higher-level function call. */
159+
predicate callInOtherFunctions(FunctionCall fc, FunctionCall fc1) {
160+
exists(FunctionCall fec1, FunctionCall fec2 |
161+
// fec1.getTarget() != fec2.getTarget() and
162+
fc.getEnclosingFunction() != fc1.getEnclosingFunction() and
163+
fec1 = fc.getEnclosingFunction().getACallToThisFunction() and
164+
fec2 = fc1.getEnclosingFunction().getACallToThisFunction() and
165+
fec1.getASuccessor*() = fec2 and
166+
checkChangeVariable(fc, fec1, fec2)
167+
)
168+
}
169+
170+
/** Holds if successive calls to close functions are possible. */
171+
predicate interDoubleCloseFunctions(FunctionCall fc, FunctionCall fc1) {
172+
fcloseCall(fc, _) and
173+
fcloseCall(fc1, _) and
174+
fc != fc1 and
175+
fc.getASuccessor*() = fc1 and
176+
checkChangeVariable(fc, fc, fc1)
177+
}
178+
179+
/** Holds if the first arguments of the two functions are similar. */
180+
predicate similarArguments(FunctionCall fc, FunctionCall fc1) {
181+
globalValueNumber(fc.getArgument(0)) = globalValueNumber(fc1.getArgument(0))
182+
or
183+
fc.getArgument(0).(VariableAccess).getTarget() = fc1.getArgument(0).(VariableAccess).getTarget() and
184+
(
185+
not fc.getArgument(0) instanceof PointerFieldAccess and
186+
not fc.getArgument(0) instanceof ValueFieldAccess
187+
or
188+
fc.getArgument(0).(VariableAccess).getQualifier() instanceof ThisExpr
189+
)
190+
or
191+
fc.getArgument(0).(VariableAccess).getTarget() = fc1.getArgument(0).(VariableAccess).getTarget() and
192+
(
193+
fc.getArgument(0) instanceof PointerFieldAccess or
194+
fc.getArgument(0) instanceof ValueFieldAccess
195+
) and
196+
hashCons(fc.getArgument(0)) = hashCons(fc1.getArgument(0))
197+
}
198+
199+
from FunctionCall fc, FunctionCall fc1
200+
where
201+
not exists(CallMayNotReturn fctmp | fctmp = fc.getASuccessor*()) and
202+
not exists(IfStmt ifs | ifs.getCondition().getAChild*() = fc) and
203+
(
204+
closeReturn(fc) and
205+
closeWithoutChangeBefore(fc1) and
206+
callInOtherFunctions(fc, fc1)
207+
or
208+
interDoubleCloseFunctions(fc, fc1)
209+
) and
210+
similarArguments(fc, fc1)
211+
select fc, "Second call to the $@ function is possible.", fc1, fc1.getTarget().getName()

0 commit comments

Comments
 (0)