Add files via upload

This commit is contained in:
ihsinme
2021-01-25 00:06:19 +03:00
committed by GitHub
parent 69664535b0
commit 9071ba2f99
3 changed files with 154 additions and 0 deletions

View File

@@ -0,0 +1,32 @@
// BAD: no memory allocation errors are detected
void f(const int *array, std::size_t size) noexcept {
int *copy = new int[size];
std::memcpy(copy, array, size * sizeof(*copy));
// ...
delete [] copy;
}
// GOOD: memory allocation errors are detected
void f(const int *array, std::size_t size) noexcept {
int *copy;
try {
copy = new int[size];
} catch(std::bad_alloc) {
// Handle error
return;
}
// At this point, copy has been initialized to allocated memory
std::memcpy(copy, array, size * sizeof(*copy));
// ...
delete [] copy;
}
// GOOD: memory allocation errors are detected
void f(const int *array, std::size_t size) noexcept {
int *copy = new (std::nothrow) int[size];
if (!copy) {
// Handle error
return;
}
std::memcpy(copy, array, size * sizeof(*copy));
// ...
delete [] copy;
}

View File

@@ -0,0 +1,29 @@
<!DOCTYPE qhelp PUBLIC
"-//Semmle//qhelp//EN"
"qhelp.dtd">
<qhelp>
<overview>
<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>
<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>
</overview>
<recommendation>
<p>We recommend using the error detection method, depending on the selected memory allocation method.</code>.</p>
</recommendation>
<example>
<p>The following file demonstrates various approaches to detecting memory allocation errors using the new operator.</p>
<sample src="WrongInDetectingAndHandlingMemoryAllocationErrors.cpp" />
</example>
<references>
<li>
CERT C++ Coding Standard:
<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>.
</li>
</references>
</qhelp>

View File

@@ -0,0 +1,93 @@
/**
* @name Сonfusion In Detecting And Handling Memory Allocation Errors
* @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.
* --the programmer can get confused when check the error that occurs when allocating memory incorrectly.
* --Making a call of this type may result in a zero byte being written just outside the buffer.
* @kind problem
* @id cpp/detect-and-handle-memory-allocation-errors
* @problem.severity warning
* @precision medium
* @tags correctness
* security
* external/cwe/cwe-570
*/
import cpp
/**
* Lookup if condition compare with 0
*/
class IfCompareWithZero extends IfStmt {
IfCompareWithZero() {
this.getCondition().(EQExpr).getAChild().getValue() = "0"
or
this.getCondition().(NEExpr).getAChild().getValue() = "0" and
this.hasElse()
}
}
/**
* lookup for calls to `operator new`, with incorrect error handling.
*/
class WrongCheckErrorOperatorNew extends FunctionCall {
Expr exp;
WrongCheckErrorOperatorNew() {
this = exp.(NewOrNewArrayExpr).getAChild().(FunctionCall) and
(
this.getTarget().hasGlobalOrStdName("operator new")
or
this.getTarget().hasGlobalOrStdName("operator new[]")
)
}
/**
* Holds if handler `try ... catch` exists.
*/
predicate isExistsTryCatchBlock() {
exists(TryStmt tb, AssignExpr aex, Initializer it |
tb.getAChild*() = exp
or
exp = it.getExpr() and
tb.getAChild*().(DeclStmt).getADeclaration() = it.getDeclaration()
or
aex.getAChild*() = exp and
tb.getAChild*().(AssignExpr) = aex
)
}
/**
* Holds if results call `operator new` check in `operator if`.
*/
predicate isExistsIfCondition() {
exists(IfCompareWithZero ifc, AssignExpr aex, Initializer it |
// call `operator new` directly from the condition of `operator if`.
this = ifc.getCondition().getAChild()
or
// check results call `operator new` with variable appropriation
postDominates(ifc, this) and
aex.getAChild() = exp and
ifc.getCondition().getAChild().(VariableAccess).getTarget() =
aex.getLValue().(VariableAccess).getTarget()
or
// check results call `operator new` with declaration variable
postDominates(ifc, this) and
exp = it.getExpr() and
it.getDeclaration() = ifc.getCondition().getAChild().(VariableAccess).getTarget()
)
}
/**
* Holds if `(std::nothrow)` exists in call `operator new`.
*/
predicate isExistsNothrow() { this.getAChild().toString() = "nothrow" }
}
from WrongCheckErrorOperatorNew op
where
// use call `operator new` with `(std::nothrow)` and checking error using `try ... catch` block and not `operator if`
op.isExistsNothrow() and not op.isExistsIfCondition() and op.isExistsTryCatchBlock()
or
// use call `operator new` without `(std::nothrow)` and checking error using `operator if` and not `try ... catch` block
not op.isExistsNothrow() and not op.isExistsTryCatchBlock() and op.isExistsIfCondition()
select op, "memory allocation error check is incorrect or missing"