mirror of
https://github.com/github/codeql.git
synced 2026-01-06 11:10:23 +01:00
212 lines
5.8 KiB
Plaintext
212 lines
5.8 KiB
Plaintext
import cpp
|
|
|
|
/**
|
|
* Holds if `val` is an access to the variable `v`, or if `val`
|
|
* is an assignment with an access to `v` on the left-hand side.
|
|
*/
|
|
predicate valueOfVar(Variable v, Expr val) {
|
|
val = v.getAnAccess() or
|
|
val.(AssignExpr).getLValue() = v.getAnAccess()
|
|
}
|
|
|
|
/**
|
|
* Holds if either:
|
|
* - `cond` is an (in)equality expression that compares the variable `v` to the value `-1`, or
|
|
* - `cond` is a relational expression that compares the variable `v` to a constant.
|
|
*/
|
|
predicate boundsCheckExpr(Variable v, Expr cond) {
|
|
exists(EQExpr eq |
|
|
cond = eq and
|
|
eq.getAnOperand().getValue() = "-1" and
|
|
valueOfVar(v, eq.getAnOperand())
|
|
)
|
|
or
|
|
exists(NEExpr ne |
|
|
cond = ne and
|
|
ne.getAnOperand().getValue() = "-1" and
|
|
valueOfVar(v, ne.getAnOperand())
|
|
)
|
|
or
|
|
exists(LTExpr lt |
|
|
cond = lt and
|
|
valueOfVar(v, lt.getAnOperand()) and
|
|
exists(lt.getAnOperand().getValue())
|
|
)
|
|
or
|
|
exists(LEExpr le |
|
|
cond = le and
|
|
valueOfVar(v, le.getAnOperand()) and
|
|
exists(le.getAnOperand().getValue())
|
|
)
|
|
or
|
|
exists(GTExpr gt |
|
|
cond = gt and
|
|
valueOfVar(v, gt.getAnOperand()) and
|
|
exists(gt.getAnOperand().getValue())
|
|
)
|
|
or
|
|
exists(GEExpr ge |
|
|
cond = ge and
|
|
valueOfVar(v, ge.getAnOperand()) and
|
|
exists(ge.getAnOperand().getValue())
|
|
)
|
|
}
|
|
|
|
/**
|
|
* Holds if `node` is an expression in a conditional statement and `succ` is an
|
|
* immediate successor of `node` that may be reached after evaluating `node`.
|
|
* For example, given
|
|
* ```
|
|
* if (a < 10 && b) func1();
|
|
* else func2();
|
|
* ```
|
|
* this predicate holds when either:
|
|
* - `node` is `a < 10` and `succ` is `func2()` or `b`, or
|
|
* - `node` is `b` and `succ` is `func1()` or `func2()`
|
|
*/
|
|
predicate conditionalSuccessor(ControlFlowNode node, ControlFlowNode succ) {
|
|
if node.isCondition()
|
|
then succ = node.getATrueSuccessor() or succ = node.getAFalseSuccessor()
|
|
else
|
|
exists(BinaryLogicalOperation binop |
|
|
binop.getAnOperand() = node and conditionalSuccessor(binop, succ)
|
|
)
|
|
}
|
|
|
|
/**
|
|
* Holds if the current value of the variable `v` at control-flow
|
|
* node `n` has been used either in:
|
|
* - an (in)equality comparison with the value `-1`, or
|
|
* - a relational comparison that compares `v` to a constant.
|
|
*/
|
|
predicate boundsChecked(Variable v, ControlFlowNode node) {
|
|
exists(Expr test |
|
|
boundsCheckExpr(v, test) and
|
|
conditionalSuccessor(test, node)
|
|
)
|
|
or
|
|
exists(ControlFlowNode mid |
|
|
boundsChecked(v, mid) and mid = node.getAPredecessor() and not definitionBarrier(v, mid)
|
|
)
|
|
}
|
|
|
|
/**
|
|
* Holds if `cond` compares `v` to some common error values. Specifically, this
|
|
* predicate holds when:
|
|
* - `cond` checks that `v` is equal to `-1`, or
|
|
* - `cond` checks that `v` is less than `0`, or
|
|
* - `cond` checks that `v` is less than or equal to `-1`, or
|
|
* - `cond` checks that `v` is not some common success value (see `successCondition`).
|
|
*/
|
|
predicate errorCondition(Variable v, Expr cond) {
|
|
exists(EQExpr eq |
|
|
cond = eq and
|
|
eq.getAnOperand().getValue() = "-1" and
|
|
eq.getAnOperand() = v.getAnAccess()
|
|
)
|
|
or
|
|
exists(LTExpr lt |
|
|
cond = lt and
|
|
lt.getLeftOperand() = v.getAnAccess() and
|
|
lt.getRightOperand().getValue() = "0"
|
|
)
|
|
or
|
|
exists(LEExpr le |
|
|
cond = le and
|
|
le.getRightOperand() = v.getAnAccess() and
|
|
le.getRightOperand().getValue() = "-1"
|
|
)
|
|
or
|
|
exists(NotExpr ne |
|
|
cond = ne and
|
|
successCondition(v, ne.getOperand())
|
|
)
|
|
}
|
|
|
|
/**
|
|
* Holds if `cond` compares `v` to some common success values. Specifically, this
|
|
* predicate holds when:
|
|
* - `cond` checks that `v` is not equal to `-1`, or
|
|
* - `cond` checks that `v` is greater than or equal than `0`, or
|
|
* - `cond` checks that `v` is greater than `-1`, or
|
|
* - `cond` checks that `v` is not some common error value (see `errorCondition`).
|
|
*/
|
|
predicate successCondition(Variable v, Expr cond) {
|
|
exists(NEExpr ne |
|
|
cond = ne and
|
|
ne.getAnOperand().getValue() = "-1" and
|
|
ne.getAnOperand() = v.getAnAccess()
|
|
)
|
|
or
|
|
exists(GEExpr ge |
|
|
cond = ge and
|
|
ge.getLeftOperand() = v.getAnAccess() and
|
|
ge.getRightOperand().getValue() = "0"
|
|
)
|
|
or
|
|
exists(GTExpr gt |
|
|
cond = gt and
|
|
gt.getRightOperand() = v.getAnAccess() and
|
|
gt.getRightOperand().getValue() = "-1"
|
|
)
|
|
or
|
|
exists(NotExpr ne |
|
|
cond = ne and
|
|
errorCondition(v, ne.getOperand())
|
|
)
|
|
}
|
|
|
|
/**
|
|
* Holds if there exists a comparison operation that checks whether `v`
|
|
* represents some common *error* values, and `n` may be reached
|
|
* immediately following the comparison operation.
|
|
*/
|
|
predicate errorSuccessor(Variable v, ControlFlowNode n) {
|
|
exists(Expr cond |
|
|
errorCondition(v, cond) and n = cond.getATrueSuccessor()
|
|
or
|
|
successCondition(v, cond) and n = cond.getAFalseSuccessor()
|
|
)
|
|
}
|
|
|
|
/**
|
|
* Holds if there exists a comparison operation that checks whether `v`
|
|
* represents some common *success* values, and `n` may be reached
|
|
* immediately following the comparison operation.
|
|
*/
|
|
predicate successSuccessor(Variable v, ControlFlowNode n) {
|
|
exists(Expr cond |
|
|
successCondition(v, cond) and n = cond.getATrueSuccessor()
|
|
or
|
|
errorCondition(v, cond) and n = cond.getAFalseSuccessor()
|
|
)
|
|
}
|
|
|
|
/**
|
|
* Holds if the current value of the variable `v` at control-flow node
|
|
* `n` may have been checked against a common set of *error* values.
|
|
*/
|
|
predicate checkedError(Variable v, ControlFlowNode n) {
|
|
errorSuccessor(v, n)
|
|
or
|
|
exists(ControlFlowNode mid |
|
|
checkedError(v, mid) and
|
|
n = mid.getASuccessor() and
|
|
not definitionBarrier(v, mid)
|
|
)
|
|
}
|
|
|
|
/**
|
|
* Holds if the current value of the variable `v` at control-flow node
|
|
* `n` may have been checked against a common set of *success* values.
|
|
*/
|
|
predicate checkedSuccess(Variable v, ControlFlowNode n) {
|
|
successSuccessor(v, n)
|
|
or
|
|
exists(ControlFlowNode mid |
|
|
checkedSuccess(v, mid) and
|
|
n = mid.getASuccessor() and
|
|
not definitionBarrier(v, mid)
|
|
)
|
|
}
|