跳到主要内容

evconnlistener_free

API 概述

evconnlistener_freelibevent 中的一个API。该规属于api pair 类型。该规则是使用 ChatDetector 生成的。

规则描述

提示

Once a resource is passed as the 1-th argument to evconnlistener_free, it must not be freed again.

信息

标签:api pair

参数下标:0

CWE类别:CWE-415

规则代码

/**
* @name doublefree
* @description description
* @kind problem
* @problem.severity error
* @precision high
* @id cpp/doublefree
* @tags security
*/

import cpp
import semmle.code.cpp.dataflow.TaintTracking
import semmle.code.cpp.dataflow.DataFlow
import semmle.code.cpp.security.Security
import semmle.code.cpp.controlflow.Guards
import semmle.code.cpp.valuenumbering.GlobalValueNumbering

Expr getMallocExpr(FunctionCall fc)
{
exists(Expr e |
result = e
and
(
(fc.getTarget().hasName("evconnlistener_new") and e = fc.getArgument(0))
// TODO-addMallocHere
)
)
}

Expr getFreeExpr(FunctionCall fc)
{

result = fc.getArgument(0)
and
(
fc.getTarget().hasName("evconnlistener_free")
// or
// fc.getTarget().hasName("target")
// TODO-addFreeHere
)
}
predicate isSourceFC(FunctionCall fc)
{

fc.getTarget().hasName("evconnlistener_new")
}

predicate isSinkFC(FunctionCall fc)
{
fc.getTarget().hasName("evconnlistener_free")
// or
// fc.getTarget().hasName("target")
}
DataFlow::Node getSinkNode(FunctionCall fc)
{
result.asExpr() = getFreeExpr(fc)
or
result.asDefiningArgument() = getFreeExpr(fc)
}

DataFlow::Node getSourceNode(FunctionCall fc)
{
result.asExpr() = getMallocExpr(fc)
or
result.asDefiningArgument() = getMallocExpr(fc)
}
class MallocConfiguration extends DataFlow::Configuration {
MallocConfiguration() { this = "MallocConfiguration" }

override predicate isSource(DataFlow::Node source) {
exists(FunctionCall fc |
isSourceFC(fc)
and
source = getSourceNode(fc)
)
or
exists(AssignExpr ae|
ae.getAChild() = source.asExpr()
or ae.getAChild() = source.asDefiningArgument()
)
}
override predicate isSink(DataFlow::Node sink) {
// sink.asExpr()
exists(FunctionCall fc |
isSinkFC(fc)
and sink = getSinkNode(fc)
)
}
}

from FunctionCall target, FunctionCall free
where
isSinkFC(target)
and exists(FunctionCall malloc | isSourceFC(malloc) and free.getAPredecessor*() = malloc)
and
isSinkFC(free)
and free.getASuccessor*() = target
and not free = target
and exists(Variable v |

v.getAnAccess() = getFreeExpr(target)
and v.getAnAccess() = getFreeExpr(free)
// and
// isLocalVariable(getMallocExpr(target))
and not
exists(MallocConfiguration cfg, Expr malloc|
// isSourceFC(malloc)
free.getASuccessor*() = malloc
and malloc.getASuccessor*() = target
and
cfg.hasFlow(DataFlow::exprNode(malloc), getSinkNode(target))
)
)
select target, "First Freed in " + free.getLocation().toString() + ". Double free in " + target.getLocation().toString()