Skip to content

Commit 0257011

Browse files
authored
Add files via upload
1 parent 3d1f4d5 commit 0257011

File tree

3 files changed

+235
-0
lines changed

3 files changed

+235
-0
lines changed
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
...
2+
try {
3+
if (chackValue) throw exception();
4+
valData->bufMyData = new myData*[valData->sizeInt];
5+
6+
}
7+
catch (...)
8+
{
9+
for (size_t i = 0; i < valData->sizeInt; i++)
10+
{
11+
delete[] valData->bufMyData[i]->buffer; // BAD
12+
delete valData->bufMyData[i];
13+
}
14+
...
15+
try {
16+
if (chackValue) throw exception();
17+
valData->bufMyData = new myData*[valData->sizeInt];
18+
19+
}
20+
catch (...)
21+
{
22+
for (size_t i = 0; i < valData->sizeInt; i++)
23+
{
24+
if(delete valData->bufMyData[i])
25+
{
26+
delete[] valData->bufMyData[i]->buffer; // GOOD
27+
delete valData->bufMyData[i];
28+
}
29+
}
30+
31+
...
32+
catch (const exception &) {
33+
delete valData;
34+
throw;
35+
}
36+
catch (...)
37+
{
38+
delete valData; // BAD
39+
...
40+
catch (const exception &) {
41+
delete valData;
42+
valData = NULL;
43+
throw;
44+
}
45+
catch (...)
46+
{
47+
delete valData; // GOOD
48+
...
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
<!DOCTYPE qhelp PUBLIC
2+
"-//Semmle//qhelp//EN"
3+
"qhelp.dtd">
4+
<qhelp>
5+
<overview>
6+
<p>When clearing the data in the catch block, you must be sure that the memory was allocated before the exception.</p>
7+
8+
</overview>
9+
10+
<example>
11+
<p>The following example shows erroneous and fixed ways to use exception handling.</p>
12+
<sample src="DangerousUseOfExceptionBlocks.cpp" />
13+
14+
</example>
15+
<references>
16+
17+
<li>
18+
CERT C Coding Standard:
19+
<a href="https://wiki.sei.cmu.edu/confluence/display/c/EXP34-C.+Do+not+dereference+null+pointers">EXP34-C. Do not dereference null pointers</a>.
20+
</li>
21+
22+
</references>
23+
</qhelp>
Lines changed: 164 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,164 @@
1+
/**
2+
* @name Dangerous use of exception blocks.
3+
* @description When clearing the data in the catch block, you must be sure that the memory was allocated before the exception.
4+
* @kind problem
5+
* @id cpp/dangerous-use-of-exception-blocks
6+
* @problem.severity warning
7+
* @precision medium
8+
* @tags correctness
9+
* security
10+
* external/cwe/cwe-476
11+
*/
12+
13+
import cpp
14+
15+
/** 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+
pragma[inline]
17+
predicate doubleCallDelete(CatchAnyBlock cb, Variable vr) {
18+
// Search for exceptions after freeing memory.
19+
exists(Expr e1 |
20+
(
21+
e1 = vr.getAnAccess().getEnclosingStmt().(ExprStmt).getExpr().(DeleteArrayExpr) or
22+
e1 = vr.getAnAccess().getEnclosingStmt().(ExprStmt).getExpr().(DeleteExpr)
23+
) and
24+
e1.getEnclosingFunction() = cb.getEnclosingFunction() and
25+
(
26+
e1.getEnclosingStmt().getParentStmt*() = cb.getTryStmt().getStmt() and
27+
exists(Expr e2, ThrowExpr th |
28+
(
29+
e2 = th or
30+
e2 = th.getEnclosingFunction().getACallToThisFunction()
31+
) and
32+
e2.getEnclosingStmt().getParentStmt*() = cb.getTryStmt().getStmt() and
33+
e1.getASuccessor+() = e2
34+
) and
35+
not exists(AssignExpr ae |
36+
ae.getLValue().(VariableAccess).getTarget() = vr and
37+
ae.getRValue().getValue() = "0" and
38+
e1.getASuccessor+() = ae and
39+
ae.getEnclosingStmt().getParentStmt*() = cb.getTryStmt().getStmt()
40+
)
41+
or
42+
// Search for a situation when there is a higher catch block that also frees memory.
43+
exists(CatchBlock cbt, Expr e2, ThrowExpr th |
44+
e1.getEnclosingStmt().getParentStmt*() = cbt and
45+
exists(cbt.getParameter()) and
46+
(
47+
e2 = th or
48+
e2 = th.getEnclosingFunction().getACallToThisFunction()
49+
) and
50+
e2.getEnclosingStmt().getParentStmt*() = cbt and
51+
e1.getASuccessor+() = e2 and
52+
not exists(AssignExpr ae |
53+
ae.getLValue().(VariableAccess).getTarget() = vr and
54+
ae.getRValue().getValue() = "0" and
55+
e1.getASuccessor+() = ae and
56+
ae.getEnclosingStmt().getParentStmt*() = cbt
57+
)
58+
)
59+
) and
60+
// Exclude the presence of a check in catch block.
61+
not exists(IfStmt ifst |
62+
ifst.getEnclosingStmt().getParentStmt*() = cb.getAStmt()
63+
)
64+
)
65+
}
66+
67+
/** Holds if an exception can be thrown before the memory is allocated, and when the exception is handled, an attempt is made to access unallocated memory in the catch block. */
68+
pragma[inline]
69+
predicate pointerDereference(CatchAnyBlock cb, Variable vr, Variable vro) {
70+
// Search exceptions before allocating memory.
71+
exists(Expr e0, Expr e1 |
72+
(
73+
exists(AssignExpr ase |
74+
ase = vro.getAnAccess().getEnclosingStmt().(ExprStmt).getExpr().(AssignExpr) and
75+
(
76+
e0 = ase.getRValue().(NewOrNewArrayExpr) or
77+
e0 = ase.getRValue().(NewOrNewArrayExpr).getEnclosingFunction().getACallToThisFunction()
78+
) and
79+
vro = ase.getLValue().(VariableAccess).getTarget()
80+
)
81+
or
82+
exists(AssignExpr ase |
83+
ase = vro.getAnAccess().(Qualifier).getEnclosingStmt().(ExprStmt).getExpr().(AssignExpr) and
84+
(
85+
e0 = ase.getRValue().(NewOrNewArrayExpr) or
86+
e0 = ase.getRValue().(NewOrNewArrayExpr).getEnclosingFunction().getACallToThisFunction()
87+
) and
88+
not ase.getLValue() instanceof VariableAccess and
89+
vro = ase.getLValue().getAPredecessor().(VariableAccess).getTarget()
90+
)
91+
) and
92+
exists(AssignExpr ase |
93+
ase = vr.getAnAccess().getEnclosingStmt().(ExprStmt).getExpr().(AssignExpr) and
94+
(
95+
e1 = ase.getRValue().(NewOrNewArrayExpr) or
96+
e1 = ase.getRValue().(NewOrNewArrayExpr).getEnclosingFunction().getACallToThisFunction()
97+
) and
98+
vr = ase.getLValue().(VariableAccess).getTarget()
99+
) and
100+
e0.getASuccessor*() = e1 and
101+
e0.getEnclosingStmt().getParentStmt*() = cb.getTryStmt().getStmt() and
102+
e1.getEnclosingStmt().getParentStmt*() = cb.getTryStmt().getStmt() and
103+
exists(Expr e2, ThrowExpr th |
104+
(
105+
e2 = th or
106+
e2 = th.getEnclosingFunction().getACallToThisFunction()
107+
) and
108+
e2.getEnclosingStmt().getParentStmt*() = cb.getTryStmt().getStmt() and
109+
e2.getASuccessor+() = e0
110+
)
111+
) and
112+
// We exclude checking the value of a variable or its parent in the catch block.
113+
not exists(IfStmt ifst |
114+
ifst.getEnclosingStmt().getParentStmt*() = cb.getAStmt() and
115+
(
116+
ifst.getCondition().getAChild*().(VariableAccess).getTarget() = vr or
117+
ifst.getCondition().getAChild*().(VariableAccess).getTarget() = vro
118+
)
119+
)
120+
}
121+
122+
from CatchAnyBlock cb, string msg
123+
where
124+
exists(Variable vr, Variable vro, Expr exp |
125+
exp.getEnclosingStmt().getParentStmt*() = cb and
126+
exists(VariableAccess va |
127+
(
128+
(
129+
va = exp.(DeleteArrayExpr).getExpr().getAPredecessor+().(Qualifier).(VariableAccess) or
130+
va = exp.(DeleteArrayExpr).getExpr().getAPredecessor+().(VariableAccess)
131+
) and
132+
vr = exp.(DeleteArrayExpr).getExpr().(VariableAccess).getTarget()
133+
or
134+
(
135+
va = exp.(DeleteExpr).getExpr().getAPredecessor+().(Qualifier).(VariableAccess) or
136+
va = exp.(DeleteExpr).getExpr().getAPredecessor+().(VariableAccess)
137+
) and
138+
vr = exp.(DeleteExpr).getExpr().(VariableAccess).getTarget()
139+
) and
140+
va.getEnclosingStmt() = exp.getEnclosingStmt() and
141+
vro = va.getTarget() and
142+
vr != vro
143+
) and
144+
pointerDereference(cb, vr, vro) and
145+
msg =
146+
"it is possible to dereference a pointer when accessing a " + vr.getName() +
147+
", since it is possible to throw an exception before the memory for the " + vro.getName() +
148+
" is allocated"
149+
)
150+
or
151+
exists(Expr exp, Variable vr |
152+
(
153+
exp.(DeleteExpr).getEnclosingStmt().getParentStmt*() = cb and
154+
vr = exp.(DeleteExpr).getExpr().(VariableAccess).getTarget()
155+
or
156+
exp.(DeleteArrayExpr).getEnclosingStmt().getParentStmt*() = cb and
157+
vr = exp.(DeleteArrayExpr).getExpr().(VariableAccess).getTarget()
158+
) and
159+
doubleCallDelete(cb, vr) and
160+
msg =
161+
"perhaps a situation of uncertainty due to the repeated call of the delete function for the variable "
162+
+ vr.getName()
163+
)
164+
select cb, msg

0 commit comments

Comments
 (0)