Skip to content

C++: Rewrite flow test common to use inline expectation test module #13260

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
May 23, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 12 additions & 21 deletions cpp/ql/test/TestUtilities/dataflow/FlowTestCommon.qll
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -47,20 +45,16 @@ class IRFlowTest extends InlineExpectationsTest {
}
}

class AstFlowTest extends InlineExpectationsTest {
AstFlowTest() { this = "ASTFlowTest" }

override string getARelevantTag() { result = "ast" }
module AstFlowTest<AstDataFlow::GlobalFlowSig Flow> implements TestSig {
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
Expand All @@ -79,6 +73,3 @@ class AstFlowTest extends InlineExpectationsTest {
)
}
}

/** DEPRECATED: Alias for AstFlowTest */
deprecated class ASTFlowTest = AstFlowTest;
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
failures
testFailures
26 changes: 14 additions & 12 deletions cpp/ql/test/library-tests/dataflow/dataflow-tests/test.ql
Original file line number Diff line number Diff line change
Expand Up @@ -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%")
Expand All @@ -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 {
Expand All @@ -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"
Expand All @@ -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
Expand All @@ -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")
)
Expand All @@ -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>>>
13 changes: 5 additions & 8 deletions cpp/ql/test/library-tests/dataflow/fields/ASTConfiguration.qll
Original file line number Diff line number Diff line change
@@ -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")
Expand All @@ -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()
Expand All @@ -31,5 +29,4 @@ class AstConf extends Configuration {
}
}

/** DEPRECATED: Alias for AstConf */
deprecated class ASTConf = AstConf;
module AstFlow = Global<AstConfig>;
12 changes: 6 additions & 6 deletions cpp/ql/test/library-tests/dataflow/fields/IRConfiguration.qll
Original file line number Diff line number Diff line change
@@ -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")
Expand All @@ -15,18 +13,20 @@ 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()
or
b.asExpr().(AddressOfExpr).getOperand() = a.asExpr()
}
}

module IRFlow = Global<IRConfig>;
2 changes: 2 additions & 0 deletions cpp/ql/test/library-tests/dataflow/fields/flow.expected
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
failures
testFailures
6 changes: 4 additions & 2 deletions cpp/ql/test/library-tests/dataflow/fields/flow.ql
Original file line number Diff line number Diff line change
@@ -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>>>
6 changes: 3 additions & 3 deletions cpp/ql/test/library-tests/dataflow/fields/ir-path-flow.ql
Original file line number Diff line number Diff line change
Expand Up @@ -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()
6 changes: 3 additions & 3 deletions cpp/ql/test/library-tests/dataflow/fields/path-flow.ql
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
failures
testFailures
22 changes: 12 additions & 10 deletions cpp/ql/test/library-tests/dataflow/smart-pointers-taint/taint.ql
Original file line number Diff line number Diff line change
Expand Up @@ -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>>>
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
failures
testFailures
30 changes: 16 additions & 14 deletions cpp/ql/test/library-tests/dataflow/taint-tests/taint.ql
Original file line number Diff line number Diff line change
Expand Up @@ -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%")
Expand All @@ -60,28 +58,28 @@ 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 {
private import semmle.code.cpp.ir.IR
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"
Expand All @@ -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>>>