mirror of
https://github.com/github/codeql.git
synced 2025-12-27 14:16:34 +01:00
73 lines
2.2 KiB
Plaintext
73 lines
2.2 KiB
Plaintext
/**
|
|
* @name Unchecked return value used as offset
|
|
* @description Using a return value as a pointer offset without checking that the value is positive
|
|
* may lead to buffer overruns.
|
|
* @kind problem
|
|
* @id cpp/missing-negativity-test
|
|
* @problem.severity warning
|
|
* @security-severity 9.3
|
|
* @tags reliability
|
|
* security
|
|
* external/cwe/cwe-823
|
|
*/
|
|
|
|
import cpp
|
|
import Negativity
|
|
|
|
class IntegralReturnValue extends FunctionCall {
|
|
IntegralReturnValue() { this.getType().getUnderlyingType() instanceof IntegralType }
|
|
|
|
predicate isChecked() {
|
|
exists(ControlFlowNode def, ControlFlowNode test, Variable v |
|
|
exprDefinition(v, def, this) and
|
|
definitionReaches(def, test) and
|
|
errorSuccessor(v, test.getASuccessor())
|
|
)
|
|
}
|
|
}
|
|
|
|
class FunctionWithNegativeReturn extends Function {
|
|
FunctionWithNegativeReturn() {
|
|
this.getType().getUnderlyingType() instanceof IntegralType and
|
|
(
|
|
exists(ReturnStmt ret |
|
|
ret.getExpr().getValue().toInt() < 0 and
|
|
ret.getEnclosingFunction() = this
|
|
)
|
|
or
|
|
count(IntegralReturnValue val | val.getTarget() = this and val.isChecked()) * 100 /
|
|
count(IntegralReturnValue val | val.getTarget() = this) >= 80
|
|
)
|
|
}
|
|
}
|
|
|
|
predicate dangerousUse(IntegralReturnValue val, Expr use) {
|
|
exists(ArrayExpr ae | ae.getArrayOffset() = val and use = val)
|
|
or
|
|
exists(StackVariable v, ControlFlowNode def, ArrayExpr ae |
|
|
exprDefinition(v, def, val) and
|
|
use = ae.getArrayOffset() and
|
|
not boundsChecked(v, use) and
|
|
definitionUsePair(v, def, use)
|
|
)
|
|
or
|
|
use.getParent().(AddExpr).getAnOperand() = val and
|
|
val = use and
|
|
use.getType().getUnderlyingType() instanceof PointerType
|
|
or
|
|
exists(StackVariable v, ControlFlowNode def, AddExpr add |
|
|
exprDefinition(v, def, val) and
|
|
definitionUsePair(v, def, use) and
|
|
add.getAnOperand() = use and
|
|
not boundsChecked(v, use) and
|
|
add.getType().getUnderlyingType() instanceof PointerType
|
|
)
|
|
}
|
|
|
|
from FunctionWithNegativeReturn f, IntegralReturnValue val, Expr dangerous
|
|
where
|
|
val.getTarget() = f and
|
|
dangerousUse(val, dangerous)
|
|
select dangerous,
|
|
"Dangerous use of possibly negative value (return value of '" + f.getName() + "')."
|