Skip to content

Commit 15af6c1

Browse files
committed
C++: Provide barrier node API without the unit column when instantiating non-parameterized barrier guards.
1 parent 0151e84 commit 15af6c1

File tree

1 file changed

+62
-2
lines changed

1 file changed

+62
-2
lines changed

cpp/ql/lib/semmle/code/cpp/ir/dataflow/internal/DataFlowUtil.qll

Lines changed: 62 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2641,7 +2641,54 @@ module BarrierGuard<guardChecksSig/3 guardChecks> {
26412641
exists(unit)
26422642
}
26432643

2644-
import ParameterizedBarrierGuard<Unit, guardChecks/4>
2644+
private module P = ParameterizedBarrierGuard<Unit, guardChecks/4>;
2645+
2646+
predicate getABarrierNode = P::getABarrierNode/0;
2647+
2648+
/**
2649+
* Gets an indirect expression node with indirection index `indirectionIndex` that is
2650+
* safely guarded by the given guard check.
2651+
*
2652+
* For example, given the following code:
2653+
* ```cpp
2654+
* int* p;
2655+
* // ...
2656+
* *p = source();
2657+
* if(is_safe_pointer(p)) {
2658+
* sink(*p);
2659+
* }
2660+
* ```
2661+
* and the following barrier guard check:
2662+
* ```ql
2663+
* predicate myGuardChecks(IRGuardCondition g, Expr e, boolean branch) {
2664+
* exists(Call call |
2665+
* g.getUnconvertedResultExpression() = call and
2666+
* call.getTarget().hasName("is_safe_pointer") and
2667+
* e = call.getAnArgument() and
2668+
* branch = true
2669+
* )
2670+
* }
2671+
* ```
2672+
* implementing `isBarrier` as:
2673+
* ```ql
2674+
* predicate isBarrier(DataFlow::Node barrier) {
2675+
* barrier = DataFlow::BarrierGuard<myGuardChecks/3>::getAnIndirectBarrierNode(1)
2676+
* }
2677+
* ```
2678+
* will block flow from `x = source()` to `sink(x)`.
2679+
*
2680+
* NOTE: If a non-indirect expression is tracked, use `getABarrierNode` instead.
2681+
*/
2682+
Node getAnIndirectBarrierNode(int indirectionIndex) {
2683+
result = P::getAnIndirectBarrierNode(indirectionIndex, _)
2684+
}
2685+
2686+
/**
2687+
* Gets an indirect expression node that is safely guarded by the given guard check.
2688+
*
2689+
* See `getAnIndirectBarrierNode/1` for examples.
2690+
*/
2691+
Node getAnIndirectBarrierNode() { result = getAnIndirectBarrierNode(_) }
26452692
}
26462693

26472694
private module InstrWithParam<ParamSig P> {
@@ -2752,7 +2799,20 @@ module InstructionBarrierGuard<instructionGuardChecksSig/3 instructionGuardCheck
27522799
exists(unit)
27532800
}
27542801

2755-
import ParameterizedInstructionBarrierGuard<Unit, instructionGuardChecks/4>
2802+
private module P = ParameterizedInstructionBarrierGuard<Unit, instructionGuardChecks/4>;
2803+
2804+
predicate getABarrierNode = P::getABarrierNode/0;
2805+
2806+
/**
2807+
* Gets an indirect node with indirection index `indirectionIndex` that is
2808+
* safely guarded by the given guard check.
2809+
*/
2810+
Node getAnIndirectBarrierNode(int indirectionIndex) {
2811+
result = P::getAnIndirectBarrierNode(indirectionIndex, _)
2812+
}
2813+
2814+
/** Gets an indirect node that is safely guarded by the given guard check. */
2815+
Node getAnIndirectBarrierNode() { result = getAnIndirectBarrierNode(_) }
27562816
}
27572817

27582818
/**

0 commit comments

Comments
 (0)