mirror of
https://github.com/github/codeql.git
synced 2025-12-24 12:46:34 +01:00
Merge pull request #6154 from MathiasVP/more-random-sources-in-uncontrolled-arithmetic
C++: Add more random sources in `cpp/uncontrolled-arithmetic`
This commit is contained in:
2
cpp/change-notes/2021-06-24-uncontrolled-arithmetic.md
Normal file
2
cpp/change-notes/2021-06-24-uncontrolled-arithmetic.md
Normal file
@@ -0,0 +1,2 @@
|
||||
lgtm
|
||||
* The 'Uncontrolled data in arithmetic expression' (cpp/uncontrolled-arithmetic) query now recognizes more sources of randomness.
|
||||
@@ -15,40 +15,63 @@
|
||||
import cpp
|
||||
import semmle.code.cpp.security.Overflow
|
||||
import semmle.code.cpp.security.Security
|
||||
import semmle.code.cpp.security.TaintTracking
|
||||
import TaintedWithPath
|
||||
import semmle.code.cpp.security.FlowSources
|
||||
import semmle.code.cpp.ir.dataflow.TaintTracking
|
||||
import DataFlow::PathGraph
|
||||
import Bounded
|
||||
|
||||
predicate isUnboundedRandCall(FunctionCall fc) {
|
||||
exists(Function func | func = fc.getTarget() |
|
||||
func.hasGlobalOrStdOrBslName("rand") and
|
||||
not bounded(fc) and
|
||||
func.getNumberOfParameters() = 0
|
||||
)
|
||||
/**
|
||||
* A function that outputs random data such as `std::rand`.
|
||||
*/
|
||||
abstract class RandomFunction extends Function {
|
||||
/**
|
||||
* Gets the `FunctionOutput` that describes how this function returns the random data.
|
||||
*/
|
||||
FunctionOutput getFunctionOutput() { result.isReturnValue() }
|
||||
}
|
||||
|
||||
predicate isUnboundedRandCallOrParent(Expr e) {
|
||||
isUnboundedRandCall(e)
|
||||
or
|
||||
isUnboundedRandCallOrParent(e.getAChild())
|
||||
}
|
||||
|
||||
predicate isUnboundedRandValue(Expr e) {
|
||||
isUnboundedRandCall(e)
|
||||
or
|
||||
exists(MacroInvocation mi |
|
||||
e = mi.getExpr() and
|
||||
isUnboundedRandCallOrParent(e)
|
||||
)
|
||||
}
|
||||
|
||||
class SecurityOptionsArith extends SecurityOptions {
|
||||
override predicate isUserInput(Expr expr, string cause) {
|
||||
isUnboundedRandValue(expr) and
|
||||
cause = "rand"
|
||||
/**
|
||||
* The standard function `std::rand`.
|
||||
*/
|
||||
private class StdRand extends RandomFunction {
|
||||
StdRand() {
|
||||
this.hasGlobalOrStdOrBslName("rand") and
|
||||
this.getNumberOfParameters() = 0
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The Unix function `rand_r`.
|
||||
*/
|
||||
private class RandR extends RandomFunction {
|
||||
RandR() {
|
||||
this.hasGlobalName("rand_r") and
|
||||
this.getNumberOfParameters() = 1
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The Unix function `random`.
|
||||
*/
|
||||
private class Random extends RandomFunction {
|
||||
Random() {
|
||||
this.hasGlobalName("random") and
|
||||
this.getNumberOfParameters() = 1
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The Windows `rand_s` function.
|
||||
*/
|
||||
private class RandS extends RandomFunction {
|
||||
RandS() {
|
||||
this.hasGlobalName("rand_s") and
|
||||
this.getNumberOfParameters() = 1
|
||||
}
|
||||
|
||||
override FunctionOutput getFunctionOutput() { result.isParameterDeref(0) }
|
||||
}
|
||||
|
||||
predicate missingGuard(VariableAccess va, string effect) {
|
||||
exists(Operation op | op.getAnOperand() = va |
|
||||
missingGuardAgainstUnderflow(op, va) and effect = "underflow"
|
||||
@@ -57,16 +80,47 @@ predicate missingGuard(VariableAccess va, string effect) {
|
||||
)
|
||||
}
|
||||
|
||||
class Configuration extends TaintTrackingConfiguration {
|
||||
override predicate isSink(Element e) { missingGuard(e, _) }
|
||||
class UncontrolledArithConfiguration extends TaintTracking::Configuration {
|
||||
UncontrolledArithConfiguration() { this = "UncontrolledArithConfiguration" }
|
||||
|
||||
override predicate isBarrier(Expr e) { super.isBarrier(e) or bounded(e) }
|
||||
override predicate isSource(DataFlow::Node source) {
|
||||
exists(RandomFunction rand, Call call | call.getTarget() = rand |
|
||||
rand.getFunctionOutput().isReturnValue() and
|
||||
source.asExpr() = call
|
||||
or
|
||||
exists(int n |
|
||||
source.asDefiningArgument() = call.getArgument(n) and
|
||||
rand.getFunctionOutput().isParameterDeref(n)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) { missingGuard(sink.asExpr(), _) }
|
||||
|
||||
override predicate isSanitizer(DataFlow::Node node) {
|
||||
bounded(node.asExpr())
|
||||
or
|
||||
// If this expression is part of bitwise 'and' or 'or' operation it's likely that the value is
|
||||
// only used as a bit pattern.
|
||||
node.asExpr() =
|
||||
any(Operation op |
|
||||
op instanceof BitwiseOrExpr or
|
||||
op instanceof BitwiseAndExpr or
|
||||
op instanceof ComplementExpr
|
||||
).getAnOperand*()
|
||||
}
|
||||
}
|
||||
|
||||
from Expr origin, VariableAccess va, string effect, PathNode sourceNode, PathNode sinkNode
|
||||
/** Gets the expression that corresponds to `node`, if any. */
|
||||
Expr getExpr(DataFlow::Node node) { result = [node.asExpr(), node.asDefiningArgument()] }
|
||||
|
||||
from
|
||||
UncontrolledArithConfiguration config, DataFlow::PathNode source, DataFlow::PathNode sink,
|
||||
VariableAccess va, string effect
|
||||
where
|
||||
taintedWithPath(origin, va, sourceNode, sinkNode) and
|
||||
config.hasFlowPath(source, sink) and
|
||||
sink.getNode().asExpr() = va and
|
||||
missingGuard(va, effect)
|
||||
select va, sourceNode, sinkNode,
|
||||
"$@ flows to here and is used in arithmetic, potentially causing an " + effect + ".", origin,
|
||||
"Uncontrolled value"
|
||||
select sink.getNode(), source, sink,
|
||||
"$@ flows to here and is used in arithmetic, potentially causing an " + effect + ".",
|
||||
getExpr(source.getNode()), "Uncontrolled value"
|
||||
|
||||
@@ -1,97 +1,60 @@
|
||||
edges
|
||||
| test.c:18:13:18:16 | call to rand | test.c:21:17:21:17 | r |
|
||||
| test.c:18:13:18:16 | call to rand | test.c:21:17:21:17 | r |
|
||||
| test.c:18:13:18:16 | call to rand | test.c:21:17:21:17 | r |
|
||||
| test.c:18:13:18:16 | call to rand | test.c:21:17:21:17 | r |
|
||||
| test.c:34:13:34:18 | call to rand | test.c:35:5:35:5 | r |
|
||||
| test.c:34:13:34:18 | call to rand | test.c:35:5:35:5 | r |
|
||||
| test.c:34:13:34:18 | call to rand | test.c:35:5:35:5 | r |
|
||||
| test.c:34:13:34:18 | call to rand | test.c:35:5:35:5 | r |
|
||||
| test.c:44:13:44:16 | call to rand | test.c:45:5:45:5 | r |
|
||||
| test.c:44:13:44:16 | call to rand | test.c:45:5:45:5 | r |
|
||||
| test.c:44:13:44:16 | call to rand | test.c:45:5:45:5 | r |
|
||||
| test.c:44:13:44:16 | call to rand | test.c:45:5:45:5 | r |
|
||||
| test.c:75:13:75:19 | ... ^ ... | test.c:77:9:77:9 | r |
|
||||
| test.c:75:13:75:19 | ... ^ ... | test.c:77:9:77:9 | r |
|
||||
| test.c:75:13:75:19 | ... ^ ... | test.c:77:9:77:9 | r |
|
||||
| test.c:75:13:75:19 | ... ^ ... | test.c:77:9:77:9 | r |
|
||||
| test.c:99:14:99:19 | call to rand | test.c:100:5:100:5 | r |
|
||||
| test.c:99:14:99:19 | call to rand | test.c:100:5:100:5 | r |
|
||||
| test.c:99:14:99:19 | call to rand | test.c:100:5:100:5 | r |
|
||||
| test.c:75:13:75:19 | call to rand | test.c:77:9:77:9 | r |
|
||||
| test.c:75:13:75:19 | call to rand | test.c:77:9:77:9 | r |
|
||||
| test.c:81:14:81:17 | call to rand | test.c:83:9:83:9 | r |
|
||||
| test.c:81:23:81:26 | call to rand | test.c:83:9:83:9 | r |
|
||||
| test.c:99:14:99:19 | call to rand | test.c:100:5:100:5 | r |
|
||||
| test.cpp:8:9:8:12 | Store | test.cpp:24:11:24:18 | call to get_rand |
|
||||
| test.cpp:8:9:8:12 | call to rand | test.cpp:8:9:8:12 | Store |
|
||||
| test.cpp:8:9:8:12 | call to rand | test.cpp:8:9:8:12 | Store |
|
||||
| test.cpp:13:2:13:15 | Chi [[]] | test.cpp:30:13:30:14 | get_rand2 output argument [[]] |
|
||||
| test.cpp:13:10:13:13 | call to rand | test.cpp:13:2:13:15 | Chi [[]] |
|
||||
| test.cpp:13:10:13:13 | call to rand | test.cpp:13:2:13:15 | Chi [[]] |
|
||||
| test.cpp:18:2:18:14 | Chi [[]] | test.cpp:36:13:36:13 | get_rand3 output argument [[]] |
|
||||
| test.cpp:18:9:18:12 | call to rand | test.cpp:18:2:18:14 | Chi [[]] |
|
||||
| test.cpp:18:9:18:12 | call to rand | test.cpp:18:2:18:14 | Chi [[]] |
|
||||
| test.cpp:24:11:24:18 | call to get_rand | test.cpp:25:7:25:7 | r |
|
||||
| test.cpp:24:11:24:18 | call to get_rand | test.cpp:25:7:25:7 | r |
|
||||
| test.cpp:30:13:30:14 | Chi | test.cpp:31:7:31:7 | r |
|
||||
| test.cpp:30:13:30:14 | Chi | test.cpp:31:7:31:7 | r |
|
||||
| test.cpp:30:13:30:14 | get_rand2 output argument [[]] | test.cpp:30:13:30:14 | Chi |
|
||||
| test.cpp:36:13:36:13 | Chi | test.cpp:37:7:37:7 | r |
|
||||
| test.cpp:36:13:36:13 | Chi | test.cpp:37:7:37:7 | r |
|
||||
| test.cpp:36:13:36:13 | get_rand3 output argument [[]] | test.cpp:36:13:36:13 | Chi |
|
||||
nodes
|
||||
| test.c:18:13:18:16 | call to rand | semmle.label | call to rand |
|
||||
| test.c:18:13:18:16 | call to rand | semmle.label | call to rand |
|
||||
| test.c:21:17:21:17 | r | semmle.label | r |
|
||||
| test.c:21:17:21:17 | r | semmle.label | r |
|
||||
| test.c:21:17:21:17 | r | semmle.label | r |
|
||||
| test.c:34:13:34:18 | call to rand | semmle.label | call to rand |
|
||||
| test.c:34:13:34:18 | call to rand | semmle.label | call to rand |
|
||||
| test.c:35:5:35:5 | r | semmle.label | r |
|
||||
| test.c:35:5:35:5 | r | semmle.label | r |
|
||||
| test.c:35:5:35:5 | r | semmle.label | r |
|
||||
| test.c:44:13:44:16 | call to rand | semmle.label | call to rand |
|
||||
| test.c:44:13:44:16 | call to rand | semmle.label | call to rand |
|
||||
| test.c:45:5:45:5 | r | semmle.label | r |
|
||||
| test.c:45:5:45:5 | r | semmle.label | r |
|
||||
| test.c:45:5:45:5 | r | semmle.label | r |
|
||||
| test.c:75:13:75:19 | ... ^ ... | semmle.label | ... ^ ... |
|
||||
| test.c:75:13:75:19 | ... ^ ... | semmle.label | ... ^ ... |
|
||||
| test.c:77:9:77:9 | r | semmle.label | r |
|
||||
| test.c:77:9:77:9 | r | semmle.label | r |
|
||||
| test.c:75:13:75:19 | call to rand | semmle.label | call to rand |
|
||||
| test.c:75:13:75:19 | call to rand | semmle.label | call to rand |
|
||||
| test.c:77:9:77:9 | r | semmle.label | r |
|
||||
| test.c:81:14:81:17 | call to rand | semmle.label | call to rand |
|
||||
| test.c:81:23:81:26 | call to rand | semmle.label | call to rand |
|
||||
| test.c:83:9:83:9 | r | semmle.label | r |
|
||||
| test.c:99:14:99:19 | call to rand | semmle.label | call to rand |
|
||||
| test.c:99:14:99:19 | call to rand | semmle.label | call to rand |
|
||||
| test.c:100:5:100:5 | r | semmle.label | r |
|
||||
| test.c:100:5:100:5 | r | semmle.label | r |
|
||||
| test.c:100:5:100:5 | r | semmle.label | r |
|
||||
| test.cpp:8:9:8:12 | Store | semmle.label | Store |
|
||||
| test.cpp:8:9:8:12 | call to rand | semmle.label | call to rand |
|
||||
| test.cpp:8:9:8:12 | call to rand | semmle.label | call to rand |
|
||||
| test.cpp:13:2:13:15 | Chi [[]] | semmle.label | Chi [[]] |
|
||||
| test.cpp:13:2:13:15 | ChiPartial | semmle.label | ChiPartial |
|
||||
| test.cpp:13:10:13:13 | call to rand | semmle.label | call to rand |
|
||||
| test.cpp:13:10:13:13 | call to rand | semmle.label | call to rand |
|
||||
| test.cpp:18:2:18:14 | Chi [[]] | semmle.label | Chi [[]] |
|
||||
| test.cpp:18:2:18:14 | ChiPartial | semmle.label | ChiPartial |
|
||||
| test.cpp:18:9:18:12 | call to rand | semmle.label | call to rand |
|
||||
| test.cpp:18:9:18:12 | call to rand | semmle.label | call to rand |
|
||||
| test.cpp:24:11:24:18 | call to get_rand | semmle.label | call to get_rand |
|
||||
| test.cpp:25:7:25:7 | r | semmle.label | r |
|
||||
| test.cpp:25:7:25:7 | r | semmle.label | r |
|
||||
| test.cpp:25:7:25:7 | r | semmle.label | r |
|
||||
| test.cpp:30:13:30:14 | Chi | semmle.label | Chi |
|
||||
| test.cpp:30:13:30:14 | get_rand2 output argument [[]] | semmle.label | get_rand2 output argument [[]] |
|
||||
| test.cpp:31:7:31:7 | r | semmle.label | r |
|
||||
| test.cpp:31:7:31:7 | r | semmle.label | r |
|
||||
| test.cpp:31:7:31:7 | r | semmle.label | r |
|
||||
| test.cpp:36:13:36:13 | Chi | semmle.label | Chi |
|
||||
| test.cpp:36:13:36:13 | get_rand3 output argument [[]] | semmle.label | get_rand3 output argument [[]] |
|
||||
| test.cpp:37:7:37:7 | r | semmle.label | r |
|
||||
| test.cpp:37:7:37:7 | r | semmle.label | r |
|
||||
| test.cpp:37:7:37:7 | r | semmle.label | r |
|
||||
#select
|
||||
| test.c:21:17:21:17 | r | test.c:18:13:18:16 | call to rand | test.c:21:17:21:17 | r | $@ flows to here and is used in arithmetic, potentially causing an overflow. | test.c:18:13:18:16 | call to rand | Uncontrolled value |
|
||||
| test.c:35:5:35:5 | r | test.c:34:13:34:18 | call to rand | test.c:35:5:35:5 | r | $@ flows to here and is used in arithmetic, potentially causing an overflow. | test.c:34:13:34:18 | call to rand | Uncontrolled value |
|
||||
| test.c:45:5:45:5 | r | test.c:44:13:44:16 | call to rand | test.c:45:5:45:5 | r | $@ flows to here and is used in arithmetic, potentially causing an overflow. | test.c:44:13:44:16 | call to rand | Uncontrolled value |
|
||||
| test.c:77:9:77:9 | r | test.c:75:13:75:19 | ... ^ ... | test.c:77:9:77:9 | r | $@ flows to here and is used in arithmetic, potentially causing an underflow. | test.c:75:13:75:19 | ... ^ ... | Uncontrolled value |
|
||||
| test.c:77:9:77:9 | r | test.c:75:13:75:19 | call to rand | test.c:77:9:77:9 | r | $@ flows to here and is used in arithmetic, potentially causing an underflow. | test.c:75:13:75:19 | call to rand | Uncontrolled value |
|
||||
| test.c:77:9:77:9 | r | test.c:75:13:75:19 | call to rand | test.c:77:9:77:9 | r | $@ flows to here and is used in arithmetic, potentially causing an underflow. | test.c:75:13:75:19 | call to rand | Uncontrolled value |
|
||||
| test.c:83:9:83:9 | r | test.c:81:14:81:17 | call to rand | test.c:83:9:83:9 | r | $@ flows to here and is used in arithmetic, potentially causing an underflow. | test.c:81:14:81:17 | call to rand | Uncontrolled value |
|
||||
| test.c:83:9:83:9 | r | test.c:81:23:81:26 | call to rand | test.c:83:9:83:9 | r | $@ flows to here and is used in arithmetic, potentially causing an underflow. | test.c:81:23:81:26 | call to rand | Uncontrolled value |
|
||||
| test.c:100:5:100:5 | r | test.c:99:14:99:19 | call to rand | test.c:100:5:100:5 | r | $@ flows to here and is used in arithmetic, potentially causing an underflow. | test.c:99:14:99:19 | call to rand | Uncontrolled value |
|
||||
| test.cpp:25:7:25:7 | r | test.cpp:8:9:8:12 | call to rand | test.cpp:25:7:25:7 | r | $@ flows to here and is used in arithmetic, potentially causing an overflow. | test.cpp:8:9:8:12 | call to rand | Uncontrolled value |
|
||||
| test.cpp:31:7:31:7 | r | test.cpp:13:10:13:13 | call to rand | test.cpp:31:7:31:7 | r | $@ flows to here and is used in arithmetic, potentially causing an overflow. | test.cpp:13:10:13:13 | call to rand | Uncontrolled value |
|
||||
|
||||
@@ -80,7 +80,7 @@ void randomTester() {
|
||||
{
|
||||
int r = (rand() ^ rand());
|
||||
|
||||
r = r - 100; // BAD [NOT DETECTED]
|
||||
r = r - 100; // BAD
|
||||
}
|
||||
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user