mirror of
https://github.com/github/codeql.git
synced 2026-04-24 00:05:14 +02:00
C++: Slightly refactor test QL files so that we can add a test which tests the nodes being selected.
This commit is contained in:
103
cpp/ql/test/library-tests/dataflow/dataflow-tests/TestBase.qll
Normal file
103
cpp/ql/test/library-tests/dataflow/dataflow-tests/TestBase.qll
Normal file
@@ -0,0 +1,103 @@
|
||||
module AstTest {
|
||||
import semmle.code.cpp.dataflow.DataFlow
|
||||
private import semmle.code.cpp.controlflow.Guards
|
||||
|
||||
/**
|
||||
* A `BarrierGuard` that stops flow to all occurrences of `x` within statement
|
||||
* S in `if (guarded(x)) S`.
|
||||
*/
|
||||
// This is tested in `BarrierGuard.cpp`.
|
||||
predicate testBarrierGuard(GuardCondition g, Expr checked, boolean isTrue) {
|
||||
g.(FunctionCall).getTarget().getName() = "guarded" and
|
||||
checked = g.(FunctionCall).getArgument(0) and
|
||||
isTrue = true
|
||||
}
|
||||
|
||||
/** Common data flow configuration to be used by tests. */
|
||||
module AstTestAllocationConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) {
|
||||
source.asExpr().(FunctionCall).getTarget().getName() = "source"
|
||||
or
|
||||
source.asParameter().getName().matches("source%")
|
||||
or
|
||||
source.asExpr().(FunctionCall).getTarget().getName() = "indirect_source"
|
||||
or
|
||||
source.(DataFlow::DefinitionByReferenceNode).getParameter().getName().matches("ref_source%")
|
||||
or
|
||||
// Track uninitialized variables
|
||||
exists(source.asUninitialized())
|
||||
}
|
||||
|
||||
predicate isSink(DataFlow::Node sink) {
|
||||
exists(FunctionCall call |
|
||||
call.getTarget().getName() = ["sink", "indirect_sink"] and
|
||||
sink.asExpr() = call.getAnArgument()
|
||||
)
|
||||
}
|
||||
|
||||
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 {
|
||||
private import cpp
|
||||
import semmle.code.cpp.ir.dataflow.DataFlow
|
||||
private import semmle.code.cpp.ir.IR
|
||||
private import semmle.code.cpp.controlflow.IRGuards
|
||||
|
||||
/**
|
||||
* A `BarrierGuard` that stops flow to all occurrences of `x` within statement
|
||||
* S in `if (guarded(x)) S`.
|
||||
*/
|
||||
// This is tested in `BarrierGuard.cpp`.
|
||||
predicate testBarrierGuard(IRGuardCondition g, Expr checked, boolean isTrue) {
|
||||
exists(Call call |
|
||||
call = g.getUnconvertedResultExpression() and
|
||||
call.getTarget().hasName("guarded") and
|
||||
checked = call.getArgument(0) and
|
||||
isTrue = true
|
||||
)
|
||||
}
|
||||
|
||||
/** Common data flow configuration to be used by tests. */
|
||||
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"
|
||||
or
|
||||
source.asParameter().getName().matches("source%")
|
||||
or
|
||||
source.(DataFlow::DefinitionByReferenceNode).getParameter().getName().matches("ref_source%")
|
||||
or
|
||||
exists(source.asUninitialized())
|
||||
}
|
||||
|
||||
predicate isSink(DataFlow::Node sink) {
|
||||
exists(FunctionCall call, Expr e | e = call.getAnArgument() |
|
||||
call.getTarget().getName() = "sink" and
|
||||
sink.asExpr() = e
|
||||
or
|
||||
call.getTarget().getName() = "indirect_sink" and
|
||||
sink.asIndirectExpr() = e
|
||||
)
|
||||
}
|
||||
|
||||
predicate isBarrier(DataFlow::Node barrier) {
|
||||
exists(Expr barrierExpr | barrierExpr in [barrier.asExpr(), barrier.asIndirectExpr()] |
|
||||
barrierExpr.(VariableAccess).getTarget().hasName("barrier")
|
||||
)
|
||||
or
|
||||
barrier = DataFlow::BarrierGuard<testBarrierGuard/3>::getABarrierNode()
|
||||
or
|
||||
barrier = DataFlow::BarrierGuard<testBarrierGuard/3>::getAnIndirectBarrierNode()
|
||||
}
|
||||
}
|
||||
|
||||
module IRFlow = DataFlow::Global<IRTestAllocationConfig>;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
import TestBase
|
||||
|
||||
query predicate astFlow(AstTest::DataFlow::Node source, AstTest::DataFlow::Node sink) {
|
||||
AstTest::AstFlow::flow(source, sink)
|
||||
}
|
||||
|
||||
query predicate irFlow(IRTest::DataFlow::Node source, IRTest::DataFlow::Node sink) {
|
||||
IRTest::IRFlow::flow(source, sink)
|
||||
}
|
||||
@@ -1,107 +1,3 @@
|
||||
import TestBase
|
||||
import TestUtilities.dataflow.FlowTestCommon
|
||||
|
||||
module AstTest {
|
||||
private import semmle.code.cpp.dataflow.DataFlow
|
||||
private import semmle.code.cpp.controlflow.Guards
|
||||
|
||||
/**
|
||||
* A `BarrierGuard` that stops flow to all occurrences of `x` within statement
|
||||
* S in `if (guarded(x)) S`.
|
||||
*/
|
||||
// This is tested in `BarrierGuard.cpp`.
|
||||
predicate testBarrierGuard(GuardCondition g, Expr checked, boolean isTrue) {
|
||||
g.(FunctionCall).getTarget().getName() = "guarded" and
|
||||
checked = g.(FunctionCall).getArgument(0) and
|
||||
isTrue = true
|
||||
}
|
||||
|
||||
/** Common data flow configuration to be used by tests. */
|
||||
module AstTestAllocationConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) {
|
||||
source.asExpr().(FunctionCall).getTarget().getName() = "source"
|
||||
or
|
||||
source.asParameter().getName().matches("source%")
|
||||
or
|
||||
source.asExpr().(FunctionCall).getTarget().getName() = "indirect_source"
|
||||
or
|
||||
source.(DataFlow::DefinitionByReferenceNode).getParameter().getName().matches("ref_source%")
|
||||
or
|
||||
// Track uninitialized variables
|
||||
exists(source.asUninitialized())
|
||||
}
|
||||
|
||||
predicate isSink(DataFlow::Node sink) {
|
||||
exists(FunctionCall call |
|
||||
call.getTarget().getName() = ["sink", "indirect_sink"] and
|
||||
sink.asExpr() = call.getAnArgument()
|
||||
)
|
||||
}
|
||||
|
||||
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 {
|
||||
private import cpp
|
||||
private import semmle.code.cpp.ir.dataflow.DataFlow
|
||||
private import semmle.code.cpp.ir.IR
|
||||
private import semmle.code.cpp.controlflow.IRGuards
|
||||
|
||||
/**
|
||||
* A `BarrierGuard` that stops flow to all occurrences of `x` within statement
|
||||
* S in `if (guarded(x)) S`.
|
||||
*/
|
||||
// This is tested in `BarrierGuard.cpp`.
|
||||
predicate testBarrierGuard(IRGuardCondition g, Expr checked, boolean isTrue) {
|
||||
exists(Call call |
|
||||
call = g.getUnconvertedResultExpression() and
|
||||
call.getTarget().hasName("guarded") and
|
||||
checked = call.getArgument(0) and
|
||||
isTrue = true
|
||||
)
|
||||
}
|
||||
|
||||
/** Common data flow configuration to be used by tests. */
|
||||
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"
|
||||
or
|
||||
source.asParameter().getName().matches("source%")
|
||||
or
|
||||
source.(DataFlow::DefinitionByReferenceNode).getParameter().getName().matches("ref_source%")
|
||||
or
|
||||
exists(source.asUninitialized())
|
||||
}
|
||||
|
||||
predicate isSink(DataFlow::Node sink) {
|
||||
exists(FunctionCall call, Expr e | e = call.getAnArgument() |
|
||||
call.getTarget().getName() = "sink" and
|
||||
sink.asExpr() = e
|
||||
or
|
||||
call.getTarget().getName() = "indirect_sink" and
|
||||
sink.asIndirectExpr() = e
|
||||
)
|
||||
}
|
||||
|
||||
predicate isBarrier(DataFlow::Node barrier) {
|
||||
exists(Expr barrierExpr | barrierExpr in [barrier.asExpr(), barrier.asIndirectExpr()] |
|
||||
barrierExpr.(VariableAccess).getTarget().hasName("barrier")
|
||||
)
|
||||
or
|
||||
barrier = DataFlow::BarrierGuard<testBarrierGuard/3>::getABarrierNode()
|
||||
or
|
||||
barrier = DataFlow::BarrierGuard<testBarrierGuard/3>::getAnIndirectBarrierNode()
|
||||
}
|
||||
}
|
||||
|
||||
module IRFlow = DataFlow::Global<IRTestAllocationConfig>;
|
||||
}
|
||||
|
||||
import MakeTest<MergeTests<AstFlowTest<AstTest::AstFlow>, IRFlowTest<IRTest::IRFlow>>>
|
||||
|
||||
Reference in New Issue
Block a user