mirror of
https://github.com/github/codeql.git
synced 2026-05-13 18:59:27 +02:00
58 lines
1.7 KiB
Plaintext
58 lines
1.7 KiB
Plaintext
private import cpp
|
|
private import semmle.code.cpp.commons.Scanf
|
|
private import semmle.code.cpp.controlflow.IRGuards
|
|
private import semmle.code.cpp.ir.ValueNumbering
|
|
|
|
private predicate exprInBooleanContext(Expr e) {
|
|
exists(IRGuardCondition gc |
|
|
exists(Instruction i |
|
|
i.getUnconvertedResultExpression() = e and
|
|
gc.comparesEq(valueNumber(i).getAUse(), 0, _, _)
|
|
)
|
|
or
|
|
gc.getUnconvertedResultExpression() = e
|
|
)
|
|
}
|
|
|
|
private predicate isLinuxKernel() {
|
|
// For the purpose of sscanf, we check the header guards for the files that it is defined in (which have changed)
|
|
exists(Macro macro | macro.getName() in ["_LINUX_KERNEL_SPRINTF_H_", "_LINUX_KERNEL_H"])
|
|
}
|
|
|
|
/**
|
|
* Gets the value of the EOF macro.
|
|
*
|
|
* This is typically `"-1"`, but this is not guaranteed to be the case on all
|
|
* systems.
|
|
*/
|
|
private string getEofValue() {
|
|
exists(MacroInvocation mi |
|
|
mi.getMacroName() = "EOF" and
|
|
result = unique( | | mi.getExpr().getValue())
|
|
)
|
|
}
|
|
|
|
/**
|
|
* Holds if the value of `call` has been checked to not equal `EOF`.
|
|
*/
|
|
private predicate checkedForEof(ScanfFunctionCall call) {
|
|
exists(IRGuardCondition gc |
|
|
exists(Instruction i | i.getUnconvertedResultExpression() = call |
|
|
// call == EOF
|
|
gc.comparesEq(valueNumber(i).getAUse(), getEofValue().toInt(), _, _)
|
|
or
|
|
// call < 0 (EOF is guaranteed to be negative)
|
|
gc.comparesLt(valueNumber(i).getAUse(), 0, true, _)
|
|
)
|
|
)
|
|
}
|
|
|
|
/**
|
|
* Holds if `call` is a `scanf`-like call were the result is only checked against 0, but it can also return EOF.
|
|
*/
|
|
predicate incorrectlyCheckedScanf(ScanfFunctionCall call) {
|
|
exprInBooleanContext(call) and
|
|
not checkedForEof(call) and
|
|
not isLinuxKernel() // scanf in the linux kernel can't return EOF
|
|
}
|