Skip to content

Commit 9071ba2

Browse files
authored
Add files via upload
1 parent 6966453 commit 9071ba2

3 files changed

Lines changed: 154 additions & 0 deletions

File tree

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// BAD: no memory allocation errors are detected
2+
void f(const int *array, std::size_t size) noexcept {
3+
int *copy = new int[size];
4+
std::memcpy(copy, array, size * sizeof(*copy));
5+
// ...
6+
delete [] copy;
7+
}
8+
// GOOD: memory allocation errors are detected
9+
void f(const int *array, std::size_t size) noexcept {
10+
int *copy;
11+
try {
12+
copy = new int[size];
13+
} catch(std::bad_alloc) {
14+
// Handle error
15+
return;
16+
}
17+
// At this point, copy has been initialized to allocated memory
18+
std::memcpy(copy, array, size * sizeof(*copy));
19+
// ...
20+
delete [] copy;
21+
}
22+
// GOOD: memory allocation errors are detected
23+
void f(const int *array, std::size_t size) noexcept {
24+
int *copy = new (std::nothrow) int[size];
25+
if (!copy) {
26+
// Handle error
27+
return;
28+
}
29+
std::memcpy(copy, array, size * sizeof(*copy));
30+
// ...
31+
delete [] copy;
32+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<!DOCTYPE qhelp PUBLIC
2+
"-//Semmle//qhelp//EN"
3+
"qhelp.dtd">
4+
<qhelp>
5+
<overview>
6+
<p>when using the new operator to allocate memory, you need to pay attention to the different way of detecting errors. so <code> ::operator new(std::size_t) </code> throws an exception on error, and <code> ::operator new(std::size_t, const std::nothrow_t &) </code> returns zero on error. the programmer can get confused and check the error that occurs when allocating memory incorrectly. That can lead to an unhandled program termination or to a violation of the program logic.</p>
7+
8+
<p>Loss of detection probably refers to use cases where memory allocation using your own solutions with strong nesting. It is also possible when using a buffer in the form of fields of different structures with the same names.</p>
9+
10+
</overview>
11+
<recommendation>
12+
13+
<p>We recommend using the error detection method, depending on the selected memory allocation method.</code>.</p>
14+
15+
</recommendation>
16+
<example>
17+
<p>The following file demonstrates various approaches to detecting memory allocation errors using the new operator.</p>
18+
<sample src="WrongInDetectingAndHandlingMemoryAllocationErrors.cpp" />
19+
20+
</example>
21+
<references>
22+
23+
<li>
24+
CERT C++ Coding Standard:
25+
<a href="https://wiki.sei.cmu.edu/confluence/display/cplusplus/MEM52-CPP.+Detect+and+handle+memory+allocation+errors">MEM52-CPP. Detect and handle memory allocation errors</a>.
26+
</li>
27+
28+
</references>
29+
</qhelp>
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
/**
2+
* @name Сonfusion In Detecting And Handling Memory Allocation Errors
3+
* @description --::operator new(std::size_t) throws an exception on error, and ::operator new(std::size_t, const std::nothrow_t &) returns zero on error.
4+
* --the programmer can get confused when check the error that occurs when allocating memory incorrectly.
5+
* --Making a call of this type may result in a zero byte being written just outside the buffer.
6+
* @kind problem
7+
* @id cpp/detect-and-handle-memory-allocation-errors
8+
* @problem.severity warning
9+
* @precision medium
10+
* @tags correctness
11+
* security
12+
* external/cwe/cwe-570
13+
*/
14+
15+
import cpp
16+
17+
/**
18+
* Lookup if condition compare with 0
19+
*/
20+
class IfCompareWithZero extends IfStmt {
21+
IfCompareWithZero() {
22+
this.getCondition().(EQExpr).getAChild().getValue() = "0"
23+
or
24+
this.getCondition().(NEExpr).getAChild().getValue() = "0" and
25+
this.hasElse()
26+
}
27+
}
28+
29+
/**
30+
* lookup for calls to `operator new`, with incorrect error handling.
31+
*/
32+
class WrongCheckErrorOperatorNew extends FunctionCall {
33+
Expr exp;
34+
35+
WrongCheckErrorOperatorNew() {
36+
this = exp.(NewOrNewArrayExpr).getAChild().(FunctionCall) and
37+
(
38+
this.getTarget().hasGlobalOrStdName("operator new")
39+
or
40+
this.getTarget().hasGlobalOrStdName("operator new[]")
41+
)
42+
}
43+
44+
/**
45+
* Holds if handler `try ... catch` exists.
46+
*/
47+
predicate isExistsTryCatchBlock() {
48+
exists(TryStmt tb, AssignExpr aex, Initializer it |
49+
tb.getAChild*() = exp
50+
or
51+
exp = it.getExpr() and
52+
tb.getAChild*().(DeclStmt).getADeclaration() = it.getDeclaration()
53+
or
54+
aex.getAChild*() = exp and
55+
tb.getAChild*().(AssignExpr) = aex
56+
)
57+
}
58+
59+
/**
60+
* Holds if results call `operator new` check in `operator if`.
61+
*/
62+
predicate isExistsIfCondition() {
63+
exists(IfCompareWithZero ifc, AssignExpr aex, Initializer it |
64+
// call `operator new` directly from the condition of `operator if`.
65+
this = ifc.getCondition().getAChild()
66+
or
67+
// check results call `operator new` with variable appropriation
68+
postDominates(ifc, this) and
69+
aex.getAChild() = exp and
70+
ifc.getCondition().getAChild().(VariableAccess).getTarget() =
71+
aex.getLValue().(VariableAccess).getTarget()
72+
or
73+
// check results call `operator new` with declaration variable
74+
postDominates(ifc, this) and
75+
exp = it.getExpr() and
76+
it.getDeclaration() = ifc.getCondition().getAChild().(VariableAccess).getTarget()
77+
)
78+
}
79+
80+
/**
81+
* Holds if `(std::nothrow)` exists in call `operator new`.
82+
*/
83+
predicate isExistsNothrow() { this.getAChild().toString() = "nothrow" }
84+
}
85+
86+
from WrongCheckErrorOperatorNew op
87+
where
88+
// use call `operator new` with `(std::nothrow)` and checking error using `try ... catch` block and not `operator if`
89+
op.isExistsNothrow() and not op.isExistsIfCondition() and op.isExistsTryCatchBlock()
90+
or
91+
// use call `operator new` without `(std::nothrow)` and checking error using `operator if` and not `try ... catch` block
92+
not op.isExistsNothrow() and not op.isExistsTryCatchBlock() and op.isExistsIfCondition()
93+
select op, "memory allocation error check is incorrect or missing"

0 commit comments

Comments
 (0)