Merge pull request #16445 from geoffw0/qhelp4

C++: Improve qhelp for DoubleFree.
This commit is contained in:
Geoffrey White
2024-05-08 18:02:12 +01:00
committed by GitHub
5 changed files with 63 additions and 4 deletions

View File

@@ -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>

View File

@@ -0,0 +1,16 @@
void g() {
MyTask *task = nullptr;
try
{
task = new MyTask;
...
delete task;
...
} catch (...) {
delete task; // BAD: potential double-free
}
}

View 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;
}

View 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
}
}