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::getABarrierNode() } } module AstFlow = DataFlow::Global; } 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.asExpr().(StringLiteral).getValue() = "source" or // indirect_source(n) gives the dataflow node representing the indirect node after n dereferences. exists(int n, string s | n = s.regexpCapture("indirect_source\\((\\d)\\)", 1).toInt() and source.asIndirectExpr(n).(StringLiteral).getValue() = s ) 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::getABarrierNode() or barrier = DataFlow::BarrierGuard::getAnIndirectBarrierNode() } } module IRFlow = DataFlow::Global; }