mirror of
https://github.com/github/codeql.git
synced 2026-04-30 11:15:13 +02:00
Add files via upload
This commit is contained in:
@@ -0,0 +1,20 @@
|
||||
// BAD: on unsuccessful call to realloc, we will lose a pointer to a valid memory block
|
||||
if (currentSize < newSize)
|
||||
{
|
||||
buffer = (unsigned char *)realloc(buffer, newSize);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// GOOD: this way we will exclude possible memory leak
|
||||
unsigned char * tmp;
|
||||
if (currentSize < newSize)
|
||||
{
|
||||
tmp = (unsigned char *)realloc(buffer, newSize);
|
||||
}
|
||||
if (tmp == NULL)
|
||||
{
|
||||
free(buffer);
|
||||
}
|
||||
else
|
||||
buffer = tmp;
|
||||
@@ -0,0 +1,38 @@
|
||||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
<overview>
|
||||
<p>Memory leak on failed call to realloc.
|
||||
The expression mem = realloc (mem, size) is potentially dangerous, if the call fails, we will lose the pointer to the memory block.
|
||||
An unsuccessful call is possible not only when trying to allocate a large amount of memory, but also when the process memory is strongly segmented.</p>
|
||||
|
||||
<p>False positives include code in which immediately after calling the realloc function, the pointer is manipulated without first checking for validity.
|
||||
In this case, an exception will occur in the program and it will terminate.
|
||||
But from the point of view of safe coding, these places require the attention of developers.
|
||||
At this stage, false positives are also possible in situations where the exception handling is quite complicated and occurs outside the base block in which memory is redistributed.</p>
|
||||
|
||||
</overview>
|
||||
<recommendation>
|
||||
|
||||
<p>We recommend storing the result in a temporary variable and eliminating memory leak.</p>
|
||||
|
||||
</recommendation>
|
||||
<example>
|
||||
<p>The following example demonstrates an erroneous and corrected use of the realloc function.</p>
|
||||
<sample src="MemoryLeakOnFailedCallToRealloc.c" />
|
||||
|
||||
</example>
|
||||
<references>
|
||||
|
||||
<li>
|
||||
CERT C++ Coding Standard:
|
||||
<a href="https://wiki.sei.cmu.edu/confluence/display/cplusplus/MEM51-CPP.+Properly+deallocate+dynamically+allocated+resources">MEM51-CPP. Properly deallocate dynamically allocated resources</a>.
|
||||
</li>
|
||||
<li>
|
||||
CERT C Coding Standard:
|
||||
<a href="https://wiki.sei.cmu.edu/confluence/display/c/WIN30-C.+Properly+pair+allocation+and+deallocation+functions">WIN30-C. Properly pair allocation and deallocation functions</a>.
|
||||
</li>
|
||||
|
||||
</references>
|
||||
</qhelp>
|
||||
@@ -0,0 +1,64 @@
|
||||
/**
|
||||
* @name Memory leak on failed call to realloc
|
||||
* @description The expression mem = realloc (mem, size) is potentially dangerous, if the call fails, we will lose the pointer to the memory block.
|
||||
* An unsuccessful call is possible not only when trying to allocate a large amount of memory, but also when the process memory is strongly segmented.
|
||||
* We recommend storing the result in a temporary variable and eliminating memory leak.
|
||||
* @kind problem
|
||||
* @id cpp/memory-leak-on-failed-call-to-realloc
|
||||
* @problem.severity warning
|
||||
* @precision medium
|
||||
* @tags security
|
||||
* external/cwe/cwe-401
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import semmle.code.cpp.dataflow.DataFlow
|
||||
|
||||
class ReallocCallLeak extends FunctionCall {
|
||||
ReallocCallLeak() {
|
||||
exists(AssignExpr ex, Variable v, VariableAccess va1, VariableAccess va2 |
|
||||
this.getTarget().hasName("realloc") and
|
||||
this = ex.getRValue() and
|
||||
va1 = ex.getLValue() and
|
||||
va2 = this.getArgument(0) and
|
||||
va1 = v.getAnAccess() and
|
||||
va2 = v.getAnAccess()
|
||||
)
|
||||
}
|
||||
|
||||
predicate isExistsIfWithExitCall() {
|
||||
exists(IfStmt ifc |
|
||||
exists(Variable v, DataFlow::Node source, DataFlow::Node sink |
|
||||
DataFlow::localFlow(source, sink) and
|
||||
source.asExpr() = this.getArgument(0) and
|
||||
this.getArgument(0) = v.getAnAccess() and
|
||||
ifc.getEnclosingFunction() = this.getEnclosingFunction() and
|
||||
ifc.getLocation().getStartLine() >= this.getArgument(0).getLocation().getStartLine() and
|
||||
v.getAnAccess() = ifc.getCondition().getAChild*() and
|
||||
sink.asExpr() = v.getAnAccess()
|
||||
) and
|
||||
exists(FunctionCall fc |
|
||||
fc.getEnclosingFunction() = this.getEnclosingFunction() and
|
||||
fc.getTarget().hasName("exit") and
|
||||
(ifc.getThen().getAChild*() = fc or ifc.getElse().getAChild*() = fc)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
predicate isExistsAssertWithArgumentCall() {
|
||||
exists(FunctionCall fc, Variable v, VariableAccess va1, VariableAccess va2 |
|
||||
fc.getTarget().hasName("assert") and
|
||||
this.getEnclosingFunction() = fc.getEnclosingFunction() and
|
||||
fc.getLocation().getStartLine() > this.getArgument(0).getLocation().getEndLine() and
|
||||
va2 = this.getArgument(0) and
|
||||
va1 = v.getAnAccess() and
|
||||
va2 = v.getAnAccess()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
from ReallocCallLeak rcl
|
||||
where
|
||||
not rcl.isExistsIfWithExitCall() and
|
||||
not rcl.isExistsAssertWithArgumentCall()
|
||||
select rcl, "possible loss of original pointer on unsuccessful call realloc"
|
||||
Reference in New Issue
Block a user