mirror of
https://github.com/github/codeql.git
synced 2025-12-17 09:13:20 +01:00
Merge pull request #16445 from geoffw0/qhelp4
C++: Improve qhelp for DoubleFree.
This commit is contained in:
@@ -14,13 +14,32 @@ the program, or security vulnerabilities, by allowing an attacker to overwrite a
|
|||||||
</overview>
|
</overview>
|
||||||
<recommendation>
|
<recommendation>
|
||||||
<p>
|
<p>
|
||||||
Ensure that all execution paths deallocate the allocated memory at most once. If possible, reassign
|
Ensure that all execution paths deallocate the allocated memory at most once. In complex cases it may
|
||||||
the pointer to a null value after deallocating it. This will prevent double-free vulnerabilities since
|
help to reassign a pointer to a null value after deallocating it. This will prevent double-free vulnerabilities
|
||||||
most deallocation functions will perform a null-pointer check before attempting to deallocate the memory.
|
since most deallocation functions will perform a null-pointer check before attempting to deallocate memory.
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
</recommendation>
|
</recommendation>
|
||||||
<example><sample src="DoubleFree.cpp" />
|
<example>
|
||||||
|
<p>
|
||||||
|
In the following example, <code>buff</code> is allocated and then freed twice:
|
||||||
|
</p>
|
||||||
|
<sample src="DoubleFreeBad.cpp" />
|
||||||
|
<p>
|
||||||
|
Reviewing the code above, the issue can be fixed by simply deleting the additional call to
|
||||||
|
<code>free(buff)</code>.
|
||||||
|
</p>
|
||||||
|
<sample src="DoubleFreeGood.cpp" />
|
||||||
|
<p>
|
||||||
|
In the next example, <code>task</code> may be deleted twice, if an exception occurs inside the <code>try</code>
|
||||||
|
block after the first <code>delete</code>:
|
||||||
|
</p>
|
||||||
|
<sample src="DoubleFreeBad2.cpp" />
|
||||||
|
<p>
|
||||||
|
The problem can be solved by assigning a null value to the pointer after the first <code>delete</code>, as
|
||||||
|
calling <code>delete</code> a second time on the null pointer is harmless.
|
||||||
|
</p>
|
||||||
|
<sample src="DoubleFreeGood2.cpp" />
|
||||||
</example>
|
</example>
|
||||||
<references>
|
<references>
|
||||||
|
|
||||||
|
|||||||
16
cpp/ql/src/Critical/DoubleFreeBad2.cpp
Normal file
16
cpp/ql/src/Critical/DoubleFreeBad2.cpp
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
void g() {
|
||||||
|
MyTask *task = nullptr;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
task = new MyTask;
|
||||||
|
|
||||||
|
...
|
||||||
|
|
||||||
|
delete task;
|
||||||
|
|
||||||
|
...
|
||||||
|
} catch (...) {
|
||||||
|
delete task; // BAD: potential double-free
|
||||||
|
}
|
||||||
|
}
|
||||||
7
cpp/ql/src/Critical/DoubleFreeGood.cpp
Normal file
7
cpp/ql/src/Critical/DoubleFreeGood.cpp
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
int* f() {
|
||||||
|
int *buff = malloc(SIZE*sizeof(int));
|
||||||
|
do_stuff(buff);
|
||||||
|
free(buff); // GOOD: buff is only freed once.
|
||||||
|
int *new_buffer = malloc(SIZE*sizeof(int));
|
||||||
|
return new_buffer;
|
||||||
|
}
|
||||||
17
cpp/ql/src/Critical/DoubleFreeGood2.cpp
Normal file
17
cpp/ql/src/Critical/DoubleFreeGood2.cpp
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
void g() {
|
||||||
|
MyTask *task = nullptr;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
task = new MyTask;
|
||||||
|
|
||||||
|
...
|
||||||
|
|
||||||
|
delete task;
|
||||||
|
task = nullptr;
|
||||||
|
|
||||||
|
...
|
||||||
|
} catch (...) {
|
||||||
|
delete task; // GOOD: harmless if task is NULL
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user