Skip to content

Commit 07ac8a5

Browse files
committed
C++: Parameterize the BarrierGuard modules. This is useful for barrier guards with flow states and will be necessary in the next commit for adding MaD specified barriers.
1 parent 2b31928 commit 07ac8a5

2 files changed

Lines changed: 149 additions & 46 deletions

File tree

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

Lines changed: 115 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -2417,6 +2417,19 @@ class ContentSet instanceof Content {
24172417
}
24182418
}
24192419

2420+
private signature class ParamSig;
2421+
2422+
private module WithParam<ParamSig P> {
2423+
/**
2424+
* Holds if the guard `g` validates the expression `e` upon evaluating to `branch`.
2425+
*
2426+
* The expression `e` is expected to be a syntactic part of the guard `g`.
2427+
* For example, the guard `g` might be a call `isSafe(x)` and the expression `e`
2428+
* the argument `x`.
2429+
*/
2430+
signature predicate guardChecksSig(IRGuardCondition g, Expr e, boolean branch, P param);
2431+
}
2432+
24202433
/**
24212434
* Holds if the guard `g` validates the expression `e` upon evaluating to `branch`.
24222435
*
@@ -2438,7 +2451,7 @@ private predicate controls(IRGuardCondition g, Node n, boolean edge) {
24382451
* This is expected to be used in `isBarrier`/`isSanitizer` definitions
24392452
* in data flow and taint tracking.
24402453
*/
2441-
module BarrierGuard<guardChecksSig/3 guardChecks> {
2454+
module ParameterizedBarrierGuard<ParamSig P, WithParam<P>::guardChecksSig/4 guardChecks> {
24422455
bindingset[value, n]
24432456
pragma[inline_late]
24442457
private predicate convertedExprHasValueNumber(ValueNumber value, Node n) {
@@ -2448,12 +2461,13 @@ module BarrierGuard<guardChecksSig/3 guardChecks> {
24482461
)
24492462
}
24502463

2451-
private predicate guardChecksNode(IRGuardCondition g, Node n, boolean branch) {
2452-
guardChecks(g, n.asOperand().getDef().getConvertedResultExpression(), branch)
2464+
private predicate guardChecksNode(IRGuardCondition g, Node n, boolean branch, P p) {
2465+
guardChecks(g, n.asOperand().getDef().getConvertedResultExpression(), branch, p)
24532466
}
24542467

24552468
/**
2456-
* Gets an expression node that is safely guarded by the given guard check.
2469+
* Gets an expression node that is safely guarded by the given guard check
2470+
* when the parameter is `p`.
24572471
*
24582472
* For example, given the following code:
24592473
* ```cpp
@@ -2484,19 +2498,27 @@ module BarrierGuard<guardChecksSig/3 guardChecks> {
24842498
*
24852499
* NOTE: If an indirect expression is tracked, use `getAnIndirectBarrierNode` instead.
24862500
*/
2487-
Node getABarrierNode() {
2501+
Node getABarrierNode(P p) {
24882502
exists(IRGuardCondition g, ValueNumber value, boolean edge |
24892503
convertedExprHasValueNumber(value, result) and
24902504
guardChecks(g,
2491-
pragma[only_bind_into](value.getAnInstruction().getConvertedResultExpression()), edge) and
2505+
pragma[only_bind_into](value.getAnInstruction().getConvertedResultExpression()), edge, p) and
24922506
controls(g, result, edge)
24932507
)
24942508
or
2495-
result = SsaImpl::BarrierGuard<guardChecksNode/3>::getABarrierNode()
2509+
result = SsaImpl::BarrierGuard<P, guardChecksNode/4>::getABarrierNode(p)
24962510
}
24972511

24982512
/**
2499-
* Gets an indirect expression node that is safely guarded by the given guard check.
2513+
* Gets an expression node that is safely guarded by the given guard check.
2514+
*
2515+
* See `getABarrierNode/1` for examples.
2516+
*/
2517+
Node getABarrierNode() { result = getABarrierNode(_) }
2518+
2519+
/**
2520+
* Gets an indirect expression node that is safely guarded by the given
2521+
* guard check with parameter `p`.
25002522
*
25012523
* For example, given the following code:
25022524
* ```cpp
@@ -2528,6 +2550,13 @@ module BarrierGuard<guardChecksSig/3 guardChecks> {
25282550
*
25292551
* NOTE: If a non-indirect expression is tracked, use `getABarrierNode` instead.
25302552
*/
2553+
Node getAnIndirectBarrierNode(P p) { result = getAnIndirectBarrierNode(_, p) }
2554+
2555+
/**
2556+
* Gets an indirect expression node that is safely guarded by the given guard check.
2557+
*
2558+
* See `getAnIndirectBarrierNode/1` for examples.
2559+
*/
25312560
Node getAnIndirectBarrierNode() { result = getAnIndirectBarrierNode(_) }
25322561

25332562
bindingset[value, n]
@@ -2542,10 +2571,10 @@ module BarrierGuard<guardChecksSig/3 guardChecks> {
25422571
}
25432572

25442573
private predicate guardChecksIndirectNode(
2545-
IRGuardCondition g, Node n, boolean branch, int indirectionIndex
2574+
IRGuardCondition g, Node n, boolean branch, int indirectionIndex, P p
25462575
) {
25472576
guardChecks(g, n.asIndirectOperand(indirectionIndex).getDef().getConvertedResultExpression(),
2548-
branch)
2577+
branch, p)
25492578
}
25502579

25512580
/**
@@ -2582,19 +2611,44 @@ module BarrierGuard<guardChecksSig/3 guardChecks> {
25822611
*
25832612
* NOTE: If a non-indirect expression is tracked, use `getABarrierNode` instead.
25842613
*/
2585-
Node getAnIndirectBarrierNode(int indirectionIndex) {
2614+
Node getAnIndirectBarrierNode(int indirectionIndex, P p) {
25862615
exists(IRGuardCondition g, ValueNumber value, boolean edge |
25872616
indirectConvertedExprHasValueNumber(indirectionIndex, value, result) and
25882617
guardChecks(g,
2589-
pragma[only_bind_into](value.getAnInstruction().getConvertedResultExpression()), edge) and
2618+
pragma[only_bind_into](value.getAnInstruction().getConvertedResultExpression()), edge, p) and
25902619
controls(g, result, edge)
25912620
)
25922621
or
25932622
result =
2594-
SsaImpl::BarrierGuardWithIntParam<guardChecksIndirectNode/4>::getABarrierNode(indirectionIndex)
2623+
SsaImpl::BarrierGuardWithIntParam<P, guardChecksIndirectNode/5>::getABarrierNode(indirectionIndex,
2624+
p)
25952625
}
25962626
}
25972627

2628+
/**
2629+
* Provides a set of barrier nodes for a guard that validates an expression.
2630+
*
2631+
* This is expected to be used in `isBarrier`/`isSanitizer` definitions
2632+
* in data flow and taint tracking.
2633+
*/
2634+
module BarrierGuard<guardChecksSig/3 guardChecks> {
2635+
private predicate guardChecks(IRGuardCondition g, Expr e, boolean branch, Unit unit) {
2636+
guardChecks(g, e, branch) and
2637+
exists(unit)
2638+
}
2639+
2640+
import ParameterizedBarrierGuard<Unit, guardChecks/4>
2641+
}
2642+
2643+
private module InstrWithParam<ParamSig P> {
2644+
/**
2645+
* Holds if the guard `g` validates the instruction `instr` upon evaluating to `branch`.
2646+
*/
2647+
signature predicate instructionGuardChecksSig(
2648+
IRGuardCondition g, Instruction instr, boolean branch, P p
2649+
);
2650+
}
2651+
25982652
/**
25992653
* Holds if the guard `g` validates the instruction `instr` upon evaluating to `branch`.
26002654
*/
@@ -2606,7 +2660,9 @@ signature predicate instructionGuardChecksSig(IRGuardCondition g, Instruction in
26062660
* This is expected to be used in `isBarrier`/`isSanitizer` definitions
26072661
* in data flow and taint tracking.
26082662
*/
2609-
module InstructionBarrierGuard<instructionGuardChecksSig/3 instructionGuardChecks> {
2663+
module ParameterizedInstructionBarrierGuard<
2664+
ParamSig P, InstrWithParam<P>::instructionGuardChecksSig/4 instructionGuardChecks>
2665+
{
26102666
bindingset[value, n]
26112667
pragma[inline_late]
26122668
private predicate operandHasValueNumber(ValueNumber value, Node n) {
@@ -2616,21 +2672,27 @@ module InstructionBarrierGuard<instructionGuardChecksSig/3 instructionGuardCheck
26162672
)
26172673
}
26182674

2619-
private predicate guardChecksNode(IRGuardCondition g, Node n, boolean branch) {
2620-
instructionGuardChecks(g, n.asOperand().getDef(), branch)
2675+
private predicate guardChecksNode(IRGuardCondition g, Node n, boolean branch, P p) {
2676+
instructionGuardChecks(g, n.asOperand().getDef(), branch, p)
26212677
}
26222678

2623-
/** Gets a node that is safely guarded by the given guard check. */
2624-
Node getABarrierNode() {
2679+
/**
2680+
* Gets a node that is safely guarded by the given guard check with
2681+
* parameter `p`.
2682+
*/
2683+
Node getABarrierNode(P p) {
26252684
exists(IRGuardCondition g, ValueNumber value, boolean edge |
2626-
instructionGuardChecks(g, pragma[only_bind_into](value.getAnInstruction()), edge) and
2685+
instructionGuardChecks(g, pragma[only_bind_into](value.getAnInstruction()), edge, p) and
26272686
operandHasValueNumber(value, result) and
26282687
controls(g, result, edge)
26292688
)
26302689
or
2631-
result = SsaImpl::BarrierGuard<guardChecksNode/3>::getABarrierNode()
2690+
result = SsaImpl::BarrierGuard<P, guardChecksNode/4>::getABarrierNode(p)
26322691
}
26332692

2693+
/** Gets a node that is safely guarded by the given guard check. */
2694+
Node getABarrierNode() { result = getABarrierNode(_) }
2695+
26342696
bindingset[value, n]
26352697
pragma[inline_late]
26362698
private predicate indirectOperandHasValueNumber(ValueNumber value, int indirectionIndex, Node n) {
@@ -2641,25 +2703,52 @@ module InstructionBarrierGuard<instructionGuardChecksSig/3 instructionGuardCheck
26412703
}
26422704

26432705
private predicate guardChecksIndirectNode(
2644-
IRGuardCondition g, Node n, boolean branch, int indirectionIndex
2706+
IRGuardCondition g, Node n, boolean branch, int indirectionIndex, P p
26452707
) {
2646-
instructionGuardChecks(g, n.asIndirectOperand(indirectionIndex).getDef(), branch)
2708+
instructionGuardChecks(g, n.asIndirectOperand(indirectionIndex).getDef(), branch, p)
26472709
}
26482710

26492711
/**
26502712
* Gets an indirect node with indirection index `indirectionIndex` that is
2651-
* safely guarded by the given guard check.
2713+
* safely guarded by the given guard check with parameter `p`.
26522714
*/
2653-
Node getAnIndirectBarrierNode(int indirectionIndex) {
2715+
Node getAnIndirectBarrierNode(int indirectionIndex, P p) {
26542716
exists(IRGuardCondition g, ValueNumber value, boolean edge |
2655-
instructionGuardChecks(g, pragma[only_bind_into](value.getAnInstruction()), edge) and
2717+
instructionGuardChecks(g, pragma[only_bind_into](value.getAnInstruction()), edge, p) and
26562718
indirectOperandHasValueNumber(value, indirectionIndex, result) and
26572719
controls(g, result, edge)
26582720
)
26592721
or
26602722
result =
2661-
SsaImpl::BarrierGuardWithIntParam<guardChecksIndirectNode/4>::getABarrierNode(indirectionIndex)
2723+
SsaImpl::BarrierGuardWithIntParam<P, guardChecksIndirectNode/5>::getABarrierNode(indirectionIndex,
2724+
p)
26622725
}
2726+
2727+
/**
2728+
* Gets an indirect node that is safely guarded by the given guard check
2729+
* with parameter `p`.
2730+
*/
2731+
Node getAnIndirectBarrierNode(P p) { result = getAnIndirectBarrierNode(_, p) }
2732+
2733+
/** Gets an indirect node that is safely guarded by the given guard check. */
2734+
Node getAnIndirectBarrierNode() { result = getAnIndirectBarrierNode(_) }
2735+
}
2736+
2737+
/**
2738+
* Provides a set of barrier nodes for a guard that validates an instruction.
2739+
*
2740+
* This is expected to be used in `isBarrier`/`isSanitizer` definitions
2741+
* in data flow and taint tracking.
2742+
*/
2743+
module InstructionBarrierGuard<instructionGuardChecksSig/3 instructionGuardChecks> {
2744+
private predicate instructionGuardChecks(
2745+
IRGuardCondition g, Instruction i, boolean branch, Unit unit
2746+
) {
2747+
instructionGuardChecks(g, i, branch) and
2748+
exists(unit)
2749+
}
2750+
2751+
import ParameterizedInstructionBarrierGuard<Unit, instructionGuardChecks/4>
26632752
}
26642753

26652754
/**

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

Lines changed: 34 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1035,13 +1035,23 @@ class SynthNode extends DataFlowIntegrationImpl::SsaNode {
10351035
SynthNode() { not this.asDefinition() instanceof SsaImpl::WriteDefinition }
10361036
}
10371037

1038-
signature predicate guardChecksNodeSig(IRGuards::IRGuardCondition g, Node e, boolean branch);
1038+
private signature class ParamSig;
10391039

1040-
signature predicate guardChecksNodeSig(
1041-
IRGuards::IRGuardCondition g, Node e, boolean branch, int indirectionIndex
1042-
);
1040+
private module ParamIntPair<ParamSig P> {
1041+
newtype TPair = MkPair(P p, int indirectionIndex) { nodeHasInstruction(_, _, indirectionIndex) }
1042+
}
1043+
1044+
private module WithParam<ParamSig P> {
1045+
signature predicate guardChecksNodeSig(IRGuards::IRGuardCondition g, Node e, boolean gv, P param);
1046+
}
1047+
1048+
private module IntWithParam<ParamSig P> {
1049+
signature predicate guardChecksNodeSig(
1050+
IRGuards::IRGuardCondition g, Node e, boolean gv, int indirectionIndex, P param
1051+
);
1052+
}
10431053

1044-
module BarrierGuardWithIntParam<guardChecksNodeSig/4 guardChecksNode> {
1054+
module BarrierGuardWithIntParam<ParamSig P, IntWithParam<P>::guardChecksNodeSig/5 guardChecksNode> {
10451055
private predicate ssaDefReachesCertainUse(Definition def, UseImpl use) {
10461056
exists(SourceVariable v, IRBlock bb, int i |
10471057
use.hasIndexInBlock(bb, i, v) and
@@ -1052,21 +1062,23 @@ module BarrierGuardWithIntParam<guardChecksNodeSig/4 guardChecksNode> {
10521062

10531063
private predicate guardChecksInstr(
10541064
IRGuards::Guards_v1::Guard g, IRGuards::GuardsInput::Expr instr, IRGuards::GuardValue gv,
1055-
int indirectionIndex
1065+
ParamIntPair<P>::TPair pair
10561066
) {
1057-
exists(Node node |
1067+
exists(Node node, int indirectionIndex, P p |
1068+
pair = ParamIntPair<P>::MkPair(p, indirectionIndex) and
10581069
nodeHasInstruction(node, instr, indirectionIndex) and
1059-
guardChecksNode(g, node, gv.asBooleanValue(), indirectionIndex)
1070+
guardChecksNode(g, node, gv.asBooleanValue(), indirectionIndex, p)
10601071
)
10611072
}
10621073

10631074
private predicate guardChecksWithWrappers(
10641075
DataFlowIntegrationInput::Guard g, SsaImpl::Definition def, IRGuards::GuardValue val,
1065-
int indirectionIndex
1076+
ParamIntPair<P>::MkPair pair
10661077
) {
1067-
exists(Instruction e |
1068-
IRGuards::Guards_v1::ParameterizedValidationWrapper<int, guardChecksInstr/4>::guardChecks(g,
1069-
e, val, indirectionIndex)
1078+
exists(Instruction e, int indirectionIndex |
1079+
IRGuards::Guards_v1::ParameterizedValidationWrapper<ParamIntPair<P>::TPair, guardChecksInstr/4>::guardChecks(g,
1080+
e, val, pair) and
1081+
pair = ParamIntPair<P>::MkPair(_, indirectionIndex)
10701082
|
10711083
indirectionIndex = 0 and
10721084
def.(Definition).getAUse().getDef() = e
@@ -1075,18 +1087,19 @@ module BarrierGuardWithIntParam<guardChecksNodeSig/4 guardChecksNode> {
10751087
)
10761088
}
10771089

1078-
Node getABarrierNode(int indirectionIndex) {
1090+
Node getABarrierNode(int indirectionIndex, P p) {
10791091
// Only get the SynthNodes from the shared implementation, as the ExprNodes cannot
10801092
// be matched on SourceVariable.
10811093
result.(SsaSynthNode).getSynthNode() =
1082-
DataFlowIntegrationImpl::BarrierGuardDefWithState<int, guardChecksWithWrappers/4>::getABarrierNode(indirectionIndex)
1094+
DataFlowIntegrationImpl::BarrierGuardDefWithState<ParamIntPair<P>::MkPair, guardChecksWithWrappers/4>::getABarrierNode(ParamIntPair<P>::MkPair(p,
1095+
indirectionIndex))
10831096
or
10841097
// Calculate the guarded UseImpls corresponding to ExprNodes directly.
10851098
exists(
10861099
DataFlowIntegrationInput::Guard g, IRGuards::GuardValue branch, Definition def, IRBlock bb
10871100
|
1088-
guardChecksWithWrappers(g, def, branch, indirectionIndex) and
10891101
exists(UseImpl use |
1102+
guardChecksWithWrappers(g, def, branch, ParamIntPair<P>::MkPair(p, indirectionIndex)) and
10901103
ssaDefReachesCertainUse(def, use) and
10911104
use.getBlock() = bb and
10921105
DataFlowIntegrationInput::guardControlsBlock(g, bb, branch) and
@@ -1096,15 +1109,16 @@ module BarrierGuardWithIntParam<guardChecksNodeSig/4 guardChecksNode> {
10961109
}
10971110
}
10981111

1099-
module BarrierGuard<guardChecksNodeSig/3 guardChecksNode> {
1112+
module BarrierGuard<ParamSig P, WithParam<P>::guardChecksNodeSig/4 guardChecksNode> {
11001113
private predicate guardChecksNode(
1101-
IRGuards::IRGuardCondition g, Node e, boolean branch, int indirectionIndex
1114+
IRGuards::IRGuardCondition g, Node e, boolean gv, int indirectionIndex, P p
11021115
) {
1103-
guardChecksNode(g, e, branch) and indirectionIndex = 0
1116+
indirectionIndex = 0 and
1117+
guardChecksNode(g, e, gv, p)
11041118
}
11051119

1106-
Node getABarrierNode() {
1107-
result = BarrierGuardWithIntParam<guardChecksNode/4>::getABarrierNode(0)
1120+
Node getABarrierNode(P p) {
1121+
result = BarrierGuardWithIntParam<P, guardChecksNode/5>::getABarrierNode(0, p)
11081122
}
11091123
}
11101124

0 commit comments

Comments
 (0)