mirror of
https://github.com/github/codeql.git
synced 2026-04-30 03:05:15 +02:00
Add files via upload
This commit is contained in:
13
cpp/ql/src/experimental/Security/CWE/CWE-675/DoubleRelease.c
Normal file
13
cpp/ql/src/experimental/Security/CWE/CWE-675/DoubleRelease.c
Normal file
@@ -0,0 +1,13 @@
|
||||
...
|
||||
fs = socket(AF_UNIX, SOCK_STREAM, 0)
|
||||
...
|
||||
close(fs);
|
||||
fs = -1; // GOOD
|
||||
...
|
||||
|
||||
...
|
||||
fs = socket(AF_UNIX, SOCK_STREAM, 0)
|
||||
...
|
||||
close(fs);
|
||||
if(fs) close(fs); // BAD
|
||||
...
|
||||
@@ -0,0 +1,26 @@
|
||||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
<overview>
|
||||
<p>Double release of the descriptor can lead to a crash of the program. Requires the attention of developers.</p>
|
||||
|
||||
</overview>
|
||||
<recommendation>
|
||||
<p>We recommend that you exclude situations of possible double release.</p>
|
||||
|
||||
</recommendation>
|
||||
<example>
|
||||
<p>The following example demonstrates an erroneous and corrected use of descriptor deallocation.</p>
|
||||
<sample src="DoubleFree.c" />
|
||||
|
||||
</example>
|
||||
<references>
|
||||
|
||||
<li>
|
||||
CERT C Coding Standard:
|
||||
<a href="https://wiki.sei.cmu.edu/confluence/display/c/FIO46-C.+Do+not+access+a+closed+file">FIO46-C. Do not access a closed file</a>.
|
||||
</li>
|
||||
|
||||
</references>
|
||||
</qhelp>
|
||||
211
cpp/ql/src/experimental/Security/CWE/CWE-675/DoubleRelease.ql
Normal file
211
cpp/ql/src/experimental/Security/CWE/CWE-675/DoubleRelease.ql
Normal file
@@ -0,0 +1,211 @@
|
||||
/**
|
||||
* @name Errors When Double Release
|
||||
* @description Double release of the descriptor can lead to a crash of the program.
|
||||
* @kind problem
|
||||
* @id cpp/double-release
|
||||
* @problem.severity warning
|
||||
* @precision medium
|
||||
* @tags security
|
||||
* external/cwe/cwe-675
|
||||
* external/cwe/cwe-666
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import semmle.code.cpp.commons.File
|
||||
import semmle.code.cpp.valuenumbering.GlobalValueNumbering
|
||||
import semmle.code.cpp.valuenumbering.HashCons
|
||||
|
||||
/**
|
||||
* A function call that potentially does not return (such as `exit`).
|
||||
*/
|
||||
class CallMayNotReturn extends FunctionCall {
|
||||
CallMayNotReturn() {
|
||||
// call that is known to not return
|
||||
not exists(this.(ControlFlowNode).getASuccessor())
|
||||
or
|
||||
// call to another function that may not return
|
||||
exists(CallMayNotReturn exit | getTarget() = exit.getEnclosingFunction())
|
||||
or
|
||||
exists(ThrowExpr tex | tex = this.(ControlFlowNode).getASuccessor())
|
||||
}
|
||||
}
|
||||
|
||||
/** Holds if there are no assignment expressions to the function argument. */
|
||||
pragma[inline]
|
||||
predicate checkChangeVariable(FunctionCall fc0, FunctionCall fc1, FunctionCall fc2) {
|
||||
not exists(Expr exptmp |
|
||||
(
|
||||
exptmp = fc0.getArgument(0).(VariableAccess).getTarget().getAnAssignedValue() or
|
||||
exptmp.(AddressOfExpr).getOperand() =
|
||||
fc0.getArgument(0).(VariableAccess).getTarget().getAnAccess()
|
||||
) and
|
||||
exptmp = fc1.getASuccessor*() and
|
||||
exptmp = fc2.getAPredecessor*()
|
||||
) and
|
||||
(
|
||||
(
|
||||
not fc0.getArgument(0) instanceof PointerFieldAccess and
|
||||
not fc0.getArgument(0) instanceof ValueFieldAccess
|
||||
or
|
||||
fc0.getArgument(0).(VariableAccess).getQualifier() instanceof ThisExpr
|
||||
)
|
||||
or
|
||||
not exists(Expr exptmp |
|
||||
(
|
||||
exptmp =
|
||||
fc0.getArgument(0)
|
||||
.(VariableAccess)
|
||||
.getQualifier()
|
||||
.(VariableAccess)
|
||||
.getTarget()
|
||||
.getAnAssignedValue() or
|
||||
exptmp.(AddressOfExpr).getOperand() =
|
||||
fc0.getArgument(0)
|
||||
.(VariableAccess)
|
||||
.getQualifier()
|
||||
.(VariableAccess)
|
||||
.getTarget()
|
||||
.getAnAccess()
|
||||
) and
|
||||
exptmp = fc1.getASuccessor*() and
|
||||
exptmp = fc2.getAPredecessor*()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if the underlying expression is a call to the close function. Provided that the function parameter does not change after the call. */
|
||||
predicate closeReturn(FunctionCall fc) {
|
||||
fcloseCall(fc, _) and
|
||||
not exists(Expr exptmp |
|
||||
(
|
||||
exptmp = fc.getArgument(0).(VariableAccess).getTarget().getAnAssignedValue() or
|
||||
exptmp.(AddressOfExpr).getOperand() =
|
||||
fc.getArgument(0).(VariableAccess).getTarget().getAnAccess()
|
||||
) and
|
||||
exptmp = fc.getASuccessor*()
|
||||
) and
|
||||
(
|
||||
(
|
||||
not fc.getArgument(0) instanceof PointerFieldAccess and
|
||||
not fc.getArgument(0) instanceof ValueFieldAccess
|
||||
or
|
||||
fc.getArgument(0).(VariableAccess).getQualifier() instanceof ThisExpr
|
||||
)
|
||||
or
|
||||
not exists(Expr exptmp |
|
||||
(
|
||||
exptmp =
|
||||
fc.getArgument(0)
|
||||
.(VariableAccess)
|
||||
.getQualifier()
|
||||
.(VariableAccess)
|
||||
.getTarget()
|
||||
.getAnAssignedValue() or
|
||||
exptmp.(AddressOfExpr).getOperand() =
|
||||
fc.getArgument(0)
|
||||
.(VariableAccess)
|
||||
.getQualifier()
|
||||
.(VariableAccess)
|
||||
.getTarget()
|
||||
.getAnAccess()
|
||||
) and
|
||||
exptmp = fc.getASuccessor*()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if the underlying expression is a call to the close function. Provided that the function parameter does not change before the call. */
|
||||
predicate closeWithoutChangeBefore(FunctionCall fc) {
|
||||
fcloseCall(fc, _) and
|
||||
not exists(Expr exptmp |
|
||||
(
|
||||
exptmp = fc.getArgument(0).(VariableAccess).getTarget().getAnAssignedValue() or
|
||||
exptmp.(AddressOfExpr).getOperand() =
|
||||
fc.getArgument(0).(VariableAccess).getTarget().getAnAccess()
|
||||
) and
|
||||
exptmp = fc.getAPredecessor*()
|
||||
) and
|
||||
(
|
||||
(
|
||||
not fc.getArgument(0) instanceof PointerFieldAccess and
|
||||
not fc.getArgument(0) instanceof ValueFieldAccess
|
||||
or
|
||||
fc.getArgument(0).(VariableAccess).getQualifier() instanceof ThisExpr
|
||||
)
|
||||
or
|
||||
not exists(Expr exptmp |
|
||||
(
|
||||
exptmp =
|
||||
fc.getArgument(0)
|
||||
.(VariableAccess)
|
||||
.getQualifier()
|
||||
.(VariableAccess)
|
||||
.getTarget()
|
||||
.getAnAssignedValue() or
|
||||
exptmp.(AddressOfExpr).getOperand() =
|
||||
fc.getArgument(0)
|
||||
.(VariableAccess)
|
||||
.getQualifier()
|
||||
.(VariableAccess)
|
||||
.getTarget()
|
||||
.getAnAccess()
|
||||
) and
|
||||
exptmp = fc.getAPredecessor*()
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds, if a sequential call of the specified functions is possible, via a higher-level function call. */
|
||||
predicate callInOtherFunctions(FunctionCall fc, FunctionCall fc1) {
|
||||
exists(FunctionCall fec1, FunctionCall fec2 |
|
||||
// fec1.getTarget() != fec2.getTarget() and
|
||||
fc.getEnclosingFunction() != fc1.getEnclosingFunction() and
|
||||
fec1 = fc.getEnclosingFunction().getACallToThisFunction() and
|
||||
fec2 = fc1.getEnclosingFunction().getACallToThisFunction() and
|
||||
fec1.getASuccessor*() = fec2 and
|
||||
checkChangeVariable(fc, fec1, fec2)
|
||||
)
|
||||
}
|
||||
|
||||
/** Holds if successive calls to close functions are possible. */
|
||||
predicate interDoubleCloseFunctions(FunctionCall fc, FunctionCall fc1) {
|
||||
fcloseCall(fc, _) and
|
||||
fcloseCall(fc1, _) and
|
||||
fc != fc1 and
|
||||
fc.getASuccessor*() = fc1 and
|
||||
checkChangeVariable(fc, fc, fc1)
|
||||
}
|
||||
|
||||
/** Holds if the first arguments of the two functions are similar. */
|
||||
predicate similarArguments(FunctionCall fc, FunctionCall fc1) {
|
||||
globalValueNumber(fc.getArgument(0)) = globalValueNumber(fc1.getArgument(0))
|
||||
or
|
||||
fc.getArgument(0).(VariableAccess).getTarget() = fc1.getArgument(0).(VariableAccess).getTarget() and
|
||||
(
|
||||
not fc.getArgument(0) instanceof PointerFieldAccess and
|
||||
not fc.getArgument(0) instanceof ValueFieldAccess
|
||||
or
|
||||
fc.getArgument(0).(VariableAccess).getQualifier() instanceof ThisExpr
|
||||
)
|
||||
or
|
||||
fc.getArgument(0).(VariableAccess).getTarget() = fc1.getArgument(0).(VariableAccess).getTarget() and
|
||||
(
|
||||
fc.getArgument(0) instanceof PointerFieldAccess or
|
||||
fc.getArgument(0) instanceof ValueFieldAccess
|
||||
) and
|
||||
hashCons(fc.getArgument(0)) = hashCons(fc1.getArgument(0))
|
||||
}
|
||||
|
||||
from FunctionCall fc, FunctionCall fc1
|
||||
where
|
||||
not exists(CallMayNotReturn fctmp | fctmp = fc.getASuccessor*()) and
|
||||
not exists(IfStmt ifs | ifs.getCondition().getAChild*() = fc) and
|
||||
(
|
||||
closeReturn(fc) and
|
||||
closeWithoutChangeBefore(fc1) and
|
||||
callInOtherFunctions(fc, fc1)
|
||||
or
|
||||
interDoubleCloseFunctions(fc, fc1)
|
||||
) and
|
||||
similarArguments(fc, fc1)
|
||||
select fc, "Second call to the $@ function is possible.", fc1, fc1.getTarget().getName()
|
||||
Reference in New Issue
Block a user