mirror of
https://github.com/github/codeql.git
synced 2026-04-20 22:44:52 +02:00
C++: Rewrite flow test common to use inline expectation test module
This also rewrites all uses of flow test common to use `DataFlow::ConfigSig`. Note that the removed deprecated aliases are 14 months old by now and, hence, can be safely removed.
This commit is contained in:
@@ -16,18 +16,16 @@ private import semmle.code.cpp.ir.dataflow.DataFlow::DataFlow as IRDataFlow
|
||||
private import semmle.code.cpp.dataflow.DataFlow::DataFlow as AstDataFlow
|
||||
import TestUtilities.InlineExpectationsTest
|
||||
|
||||
class IRFlowTest extends InlineExpectationsTest {
|
||||
IRFlowTest() { this = "IRFlowTest" }
|
||||
module IRFlowTest<IRDataFlow::GlobalFlowSig Flow> implements TestSig {
|
||||
string getARelevantTag() { result = "ir" }
|
||||
|
||||
override string getARelevantTag() { result = "ir" }
|
||||
|
||||
override predicate hasActualResult(Location location, string element, string tag, string value) {
|
||||
exists(IRDataFlow::Node source, IRDataFlow::Node sink, IRDataFlow::Configuration conf, int n |
|
||||
predicate hasActualResult(Location location, string element, string tag, string value) {
|
||||
exists(IRDataFlow::Node source, IRDataFlow::Node sink, int n |
|
||||
tag = "ir" and
|
||||
conf.hasFlow(source, sink) and
|
||||
Flow::flow(source, sink) and
|
||||
n =
|
||||
strictcount(int line, int column |
|
||||
conf.hasFlow(any(IRDataFlow::Node otherSource |
|
||||
Flow::flow(any(IRDataFlow::Node otherSource |
|
||||
otherSource.hasLocationInfo(_, line, column, _, _)
|
||||
), sink)
|
||||
) and
|
||||
@@ -47,20 +45,16 @@ class IRFlowTest extends InlineExpectationsTest {
|
||||
}
|
||||
}
|
||||
|
||||
class AstFlowTest extends InlineExpectationsTest {
|
||||
AstFlowTest() { this = "ASTFlowTest" }
|
||||
module AstFlowTest<AstDataFlow::GlobalFlowSig Flow> implements TestSig {
|
||||
string getARelevantTag() { result = "ast" }
|
||||
|
||||
override string getARelevantTag() { result = "ast" }
|
||||
|
||||
override predicate hasActualResult(Location location, string element, string tag, string value) {
|
||||
exists(
|
||||
AstDataFlow::Node source, AstDataFlow::Node sink, AstDataFlow::Configuration conf, int n
|
||||
|
|
||||
predicate hasActualResult(Location location, string element, string tag, string value) {
|
||||
exists(AstDataFlow::Node source, AstDataFlow::Node sink, int n |
|
||||
tag = "ast" and
|
||||
conf.hasFlow(source, sink) and
|
||||
Flow::flow(source, sink) and
|
||||
n =
|
||||
strictcount(int line, int column |
|
||||
conf.hasFlow(any(AstDataFlow::Node otherSource |
|
||||
Flow::flow(any(AstDataFlow::Node otherSource |
|
||||
otherSource.hasLocationInfo(_, line, column, _, _)
|
||||
), sink)
|
||||
) and
|
||||
@@ -79,6 +73,3 @@ class AstFlowTest extends InlineExpectationsTest {
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for AstFlowTest */
|
||||
deprecated class ASTFlowTest = AstFlowTest;
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
failures
|
||||
testFailures
|
||||
|
||||
@@ -16,10 +16,8 @@ module AstTest {
|
||||
}
|
||||
|
||||
/** Common data flow configuration to be used by tests. */
|
||||
class AstTestAllocationConfig extends DataFlow::Configuration {
|
||||
AstTestAllocationConfig() { this = "ASTTestAllocationConfig" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) {
|
||||
module AstTestAllocationConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) {
|
||||
source.asExpr().(FunctionCall).getTarget().getName() = "source"
|
||||
or
|
||||
source.asParameter().getName().matches("source%")
|
||||
@@ -32,18 +30,20 @@ module AstTest {
|
||||
exists(source.asUninitialized())
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) {
|
||||
predicate isSink(DataFlow::Node sink) {
|
||||
exists(FunctionCall call |
|
||||
call.getTarget().getName() = ["sink", "indirect_sink"] and
|
||||
sink.asExpr() = call.getAnArgument()
|
||||
)
|
||||
}
|
||||
|
||||
override predicate isBarrier(DataFlow::Node barrier) {
|
||||
predicate isBarrier(DataFlow::Node barrier) {
|
||||
barrier.asExpr().(VariableAccess).getTarget().hasName("barrier") or
|
||||
barrier = DataFlow::BarrierGuard<testBarrierGuard/3>::getABarrierNode()
|
||||
}
|
||||
}
|
||||
|
||||
module AstFlow = DataFlow::Global<AstTestAllocationConfig>;
|
||||
}
|
||||
|
||||
module IRTest {
|
||||
@@ -67,10 +67,8 @@ module IRTest {
|
||||
}
|
||||
|
||||
/** Common data flow configuration to be used by tests. */
|
||||
class IRTestAllocationConfig extends DataFlow::Configuration {
|
||||
IRTestAllocationConfig() { this = "IRTestAllocationConfig" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) {
|
||||
module IRTestAllocationConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) {
|
||||
source.asExpr().(FunctionCall).getTarget().getName() = "source"
|
||||
or
|
||||
source.asIndirectExpr(1).(FunctionCall).getTarget().getName() = "indirect_source"
|
||||
@@ -82,7 +80,7 @@ module IRTest {
|
||||
exists(source.asUninitialized())
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) {
|
||||
predicate isSink(DataFlow::Node sink) {
|
||||
exists(FunctionCall call, Expr e | e = call.getAnArgument() |
|
||||
call.getTarget().getName() = "sink" and
|
||||
sink.asExpr() = e
|
||||
@@ -92,7 +90,7 @@ module IRTest {
|
||||
)
|
||||
}
|
||||
|
||||
override predicate isBarrier(DataFlow::Node barrier) {
|
||||
predicate isBarrier(DataFlow::Node barrier) {
|
||||
exists(Expr barrierExpr | barrierExpr in [barrier.asExpr(), barrier.asIndirectExpr()] |
|
||||
barrierExpr.(VariableAccess).getTarget().hasName("barrier")
|
||||
)
|
||||
@@ -102,4 +100,8 @@ module IRTest {
|
||||
barrier = DataFlow::BarrierGuard<testBarrierGuard/3>::getAnIndirectBarrierNode()
|
||||
}
|
||||
}
|
||||
|
||||
module IRFlow = DataFlow::Global<IRTestAllocationConfig>;
|
||||
}
|
||||
|
||||
import MakeTest<MergeTests<AstFlowTest<AstTest::AstFlow>, IRFlowTest<IRTest::IRFlow>>>
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
private import semmle.code.cpp.dataflow.DataFlow
|
||||
private import DataFlow
|
||||
|
||||
class AstConf extends Configuration {
|
||||
AstConf() { this = "ASTFieldFlowConf" }
|
||||
|
||||
override predicate isSource(Node src) {
|
||||
module AstConfig implements ConfigSig {
|
||||
predicate isSource(Node src) {
|
||||
src.asExpr() instanceof NewExpr
|
||||
or
|
||||
src.asExpr().(Call).getTarget().hasName("user_input")
|
||||
@@ -15,14 +13,14 @@ class AstConf extends Configuration {
|
||||
)
|
||||
}
|
||||
|
||||
override predicate isSink(Node sink) {
|
||||
predicate isSink(Node sink) {
|
||||
exists(Call c |
|
||||
c.getTarget().hasName("sink") and
|
||||
c.getAnArgument() = sink.asExpr()
|
||||
)
|
||||
}
|
||||
|
||||
override predicate isAdditionalFlowStep(Node a, Node b) {
|
||||
predicate isAdditionalFlowStep(Node a, Node b) {
|
||||
b.asPartialDefinition() =
|
||||
any(Call c | c.getTarget().hasName("insert") and c.getAnArgument() = a.asExpr())
|
||||
.getQualifier()
|
||||
@@ -31,5 +29,4 @@ class AstConf extends Configuration {
|
||||
}
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for AstConf */
|
||||
deprecated class ASTConf = AstConf;
|
||||
module AstFlow = Global<AstConfig>;
|
||||
|
||||
@@ -1,10 +1,8 @@
|
||||
private import semmle.code.cpp.ir.dataflow.DataFlow
|
||||
private import DataFlow
|
||||
|
||||
class IRConf extends Configuration {
|
||||
IRConf() { this = "IRFieldFlowConf" }
|
||||
|
||||
override predicate isSource(Node src) {
|
||||
module IRConfig implements ConfigSig {
|
||||
predicate isSource(Node src) {
|
||||
src.asExpr() instanceof NewExpr
|
||||
or
|
||||
src.asExpr().(Call).getTarget().hasName("user_input")
|
||||
@@ -15,14 +13,14 @@ class IRConf extends Configuration {
|
||||
)
|
||||
}
|
||||
|
||||
override predicate isSink(Node sink) {
|
||||
predicate isSink(Node sink) {
|
||||
exists(Call c |
|
||||
c.getTarget().hasName("sink") and
|
||||
c.getAnArgument() = [sink.asExpr(), sink.asIndirectExpr(), sink.asConvertedExpr()]
|
||||
)
|
||||
}
|
||||
|
||||
override predicate isAdditionalFlowStep(Node a, Node b) {
|
||||
predicate isAdditionalFlowStep(Node a, Node b) {
|
||||
b.asPartialDefinition() =
|
||||
any(Call c | c.getTarget().hasName("insert") and c.getAnArgument() = a.asExpr())
|
||||
.getQualifier()
|
||||
@@ -30,3 +28,5 @@ class IRConf extends Configuration {
|
||||
b.asExpr().(AddressOfExpr).getOperand() = a.asExpr()
|
||||
}
|
||||
}
|
||||
|
||||
module IRFlow = Global<IRConfig>;
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
failures
|
||||
testFailures
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import TestUtilities.dataflow.FlowTestCommon
|
||||
|
||||
module AstTest {
|
||||
private import ASTConfiguration
|
||||
import ASTConfiguration
|
||||
}
|
||||
|
||||
module IRTest {
|
||||
private import IRConfiguration
|
||||
import IRConfiguration
|
||||
}
|
||||
|
||||
import MakeTest<MergeTests<AstFlowTest<AstTest::AstFlow>, IRFlowTest<IRTest::IRFlow>>>
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
|
||||
import semmle.code.cpp.ir.dataflow.DataFlow
|
||||
import IRConfiguration
|
||||
import DataFlow::PathGraph
|
||||
import IRFlow::PathGraph
|
||||
|
||||
from DataFlow::PathNode src, DataFlow::PathNode sink, IRConf conf
|
||||
where conf.hasFlowPath(src, sink)
|
||||
from IRFlow::PathNode src, IRFlow::PathNode sink
|
||||
where IRFlow::flowPath(src, sink)
|
||||
select sink, src, sink, sink + " flows from $@", src, src.toString()
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
|
||||
import semmle.code.cpp.dataflow.DataFlow
|
||||
import ASTConfiguration
|
||||
import DataFlow::PathGraph
|
||||
import AstFlow::PathGraph
|
||||
|
||||
from DataFlow::PathNode src, DataFlow::PathNode sink, AstConf conf
|
||||
where conf.hasFlowPath(src, sink)
|
||||
from AstFlow::PathNode src, AstFlow::PathNode sink
|
||||
where AstFlow::flowPath(src, sink)
|
||||
select sink, src, sink, sink + " flows from $@", src, src.toString()
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
failures
|
||||
testFailures
|
||||
|
||||
@@ -3,37 +3,39 @@ import TestUtilities.dataflow.FlowTestCommon
|
||||
module AstTest {
|
||||
private import semmle.code.cpp.dataflow.TaintTracking
|
||||
|
||||
class AstSmartPointerTaintConfig extends TaintTracking::Configuration {
|
||||
AstSmartPointerTaintConfig() { this = "ASTSmartPointerTaintConfig" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) {
|
||||
module AstSmartPointerTaintConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) {
|
||||
source.asExpr().(FunctionCall).getTarget().getName() = "source"
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) {
|
||||
predicate isSink(DataFlow::Node sink) {
|
||||
exists(FunctionCall call |
|
||||
call.getTarget().getName() = "sink" and
|
||||
sink.asExpr() = call.getAnArgument()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
module AstFlow = TaintTracking::Global<AstSmartPointerTaintConfig>;
|
||||
}
|
||||
|
||||
module IRTest {
|
||||
private import semmle.code.cpp.ir.dataflow.TaintTracking
|
||||
|
||||
class IRSmartPointerTaintConfig extends TaintTracking::Configuration {
|
||||
IRSmartPointerTaintConfig() { this = "IRSmartPointerTaintConfig" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) {
|
||||
module IRSmartPointerTaintConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) {
|
||||
source.asExpr().(FunctionCall).getTarget().getName() = "source"
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) {
|
||||
predicate isSink(DataFlow::Node sink) {
|
||||
exists(FunctionCall call |
|
||||
call.getTarget().getName() = "sink" and
|
||||
sink.asExpr() = call.getAnArgument()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
module IRFlow = TaintTracking::Global<IRSmartPointerTaintConfig>;
|
||||
}
|
||||
|
||||
import MakeTest<MergeTests<AstFlowTest<AstTest::AstFlow>, IRFlowTest<IRTest::IRFlow>>>
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
failures
|
||||
testFailures
|
||||
|
||||
@@ -43,10 +43,8 @@ module AstTest {
|
||||
private import semmle.code.cpp.models.interfaces.Taint
|
||||
|
||||
/** Common data flow configuration to be used by tests. */
|
||||
class AstTestAllocationConfig extends TaintTracking::Configuration {
|
||||
AstTestAllocationConfig() { this = "ASTTestAllocationConfig" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) {
|
||||
module AstTestAllocationConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) {
|
||||
source.asExpr().(FunctionCall).getTarget().getName() = "source"
|
||||
or
|
||||
source.asParameter().getName().matches("source%")
|
||||
@@ -60,17 +58,19 @@ module AstTest {
|
||||
)
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) {
|
||||
predicate isSink(DataFlow::Node sink) {
|
||||
exists(FunctionCall call |
|
||||
call.getTarget().getName() = "sink" and
|
||||
sink.asExpr() = call.getAnArgument()
|
||||
)
|
||||
}
|
||||
|
||||
override predicate isSanitizer(DataFlow::Node barrier) {
|
||||
predicate isBarrier(DataFlow::Node barrier) {
|
||||
barrier.asExpr().(VariableAccess).getTarget().hasName("sanitizer")
|
||||
}
|
||||
}
|
||||
|
||||
module AstFlow = TaintTracking::Global<AstTestAllocationConfig>;
|
||||
}
|
||||
|
||||
module IRTest {
|
||||
@@ -78,10 +78,8 @@ module IRTest {
|
||||
private import semmle.code.cpp.ir.dataflow.TaintTracking
|
||||
|
||||
/** Common data flow configuration to be used by tests. */
|
||||
class TestAllocationConfig extends TaintTracking::Configuration {
|
||||
TestAllocationConfig() { this = "TestAllocationConfig" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) {
|
||||
module TestAllocationConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) {
|
||||
source.asExpr().(FunctionCall).getTarget().getName() = "source"
|
||||
or
|
||||
source.asIndirectExpr().(FunctionCall).getTarget().getName() = "source"
|
||||
@@ -94,21 +92,25 @@ module IRTest {
|
||||
)
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) {
|
||||
predicate isSink(DataFlow::Node sink) {
|
||||
exists(FunctionCall call |
|
||||
call.getTarget().getName() = "sink" and
|
||||
[sink.asExpr(), sink.asIndirectExpr()] = call.getAnArgument()
|
||||
)
|
||||
}
|
||||
|
||||
override predicate isSanitizer(DataFlow::Node barrier) {
|
||||
predicate isBarrier(DataFlow::Node barrier) {
|
||||
barrier.asExpr().(VariableAccess).getTarget().hasName("sanitizer")
|
||||
}
|
||||
|
||||
override predicate allowImplicitRead(DataFlow::Node node, DataFlow::ContentSet c) {
|
||||
predicate allowImplicitRead(DataFlow::Node node, DataFlow::ContentSet c) {
|
||||
// allow arbitrary reads at sinks
|
||||
this.isSink(node) and
|
||||
isSink(node) and
|
||||
c.(DataFlow::FieldContent).getField().getDeclaringType() = node.getType().getUnspecifiedType()
|
||||
}
|
||||
}
|
||||
|
||||
module IRFlow = TaintTracking::Global<TestAllocationConfig>;
|
||||
}
|
||||
|
||||
import MakeTest<MergeTests<AstFlowTest<AstTest::AstFlow>, IRFlowTest<IRTest::IRFlow>>>
|
||||
|
||||
Reference in New Issue
Block a user