Files
codeql/cpp/ql/src/Likely Bugs/InconsistentCallOnResult.ql
Jonas Jensen 4ef5c9af62 C++: Autoformat everything
Some files that will change in #1736 have been spared.

    ./build -j4 target/jars/qlformat
    find ql/cpp/ql -name "*.ql"  -print0 | xargs -0 target/jars/qlformat --input
    find ql/cpp/ql -name "*.qll" -print0 | xargs -0 target/jars/qlformat --input
    (cd ql && git checkout 'cpp/ql/src/semmle/code/cpp/ir/implementation/**/*SSA*.qll')
    buildutils-internal/scripts/pr-checks/sync-identical-files.py --latest
2019-09-09 11:25:53 +02:00

75 lines
2.5 KiB
Plaintext

/**
* @name Inconsistent operation on return value
* @description A function is called, and the same operation is usually performed on the return value - for example, free, delete, close etc. However, in some cases it is not performed. These unusual cases may indicate misuse of the API and could cause resource leaks.
* @kind problem
* @problem.severity warning
* @precision medium
* @id cpp/inconsistent-call-on-result
* @tags reliability
* correctness
* statistical
* non-attributable
* external/cwe/cwe-252
*/
import cpp
predicate exclude(Function f) {
exists(string name | name = f.getName() |
name.toLowerCase().matches("get%") or
name.matches("strto%")
)
}
predicate checkExpr(Expr e, string operation, Variable v) {
exists(FunctionCall fc | fc = e and not exclude(fc.getTarget()) |
fc.getTarget().getName() = operation and
(fc.getAnArgument() = v.getAnAccess() or fc.getQualifier() = v.getAnAccess())
)
or
exists(DeleteExpr del | del = e |
del.getExpr() = v.getAnAccess() and
operation = "delete"
)
or
exists(DeleteArrayExpr del | del = e |
del.getExpr() = v.getAnAccess() and
operation = "delete[]"
)
}
predicate checkedFunctionCall(FunctionCall fc, string operation) {
relevantFunctionCall(fc, _) and
exists(Variable v, Expr check | v.getAnAssignedValue() = fc |
checkExpr(check, operation, v) and
check != fc
)
}
predicate relevantFunctionCall(FunctionCall fc, Function f) {
fc.getTarget() = f and
exists(Variable v | v.getAnAssignedValue() = fc) and
not okToIgnore(fc)
}
predicate okToIgnore(FunctionCall fc) { fc.isInMacroExpansion() }
predicate functionStats(Function f, string operation, int used, int total, int percentage) {
exists(PointerType pt | pt.getATypeNameUse() = f.getADeclarationEntry()) and
used = strictcount(FunctionCall fc | checkedFunctionCall(fc, operation) and f = fc.getTarget()) and
total = strictcount(FunctionCall fc | relevantFunctionCall(fc, f)) and
percentage = used * 100 / total
}
from FunctionCall unchecked, Function f, string operation, int percent
where
relevantFunctionCall(unchecked, f) and
not checkedFunctionCall(unchecked, operation) and
functionStats(f, operation, _, _, percent) and
percent >= 70 and
unchecked.getFile().getAbsolutePath().matches("%fbcode%") and
not unchecked.getFile().getAbsolutePath().matches("%\\_build%")
select unchecked,
"After " + percent.toString() + "% of calls to " + f.getName() + " there is a call to " +
operation + " on the return value. The call may be missing in this case."