Skip to content

Commit 38451a8

Browse files
committed
PS: Implement conditional splitting in the Powershell CFG.
1 parent 7a252e4 commit 38451a8

File tree

2 files changed

+60
-53
lines changed

2 files changed

+60
-53
lines changed

powershell/ql/lib/semmle/code/powershell/controlflow/internal/ControlFlowGraphImpl.qll

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ private import Completion
1212
private module CfgInput implements CfgShared::InputSig<Location> {
1313
private import ControlFlowGraphImpl as Impl
1414
private import Completion as Comp
15-
private import Splitting as Splitting
1615
private import semmle.code.powershell.Cfg as Cfg
1716

1817
class Completion = Comp::Completion;
@@ -35,10 +34,6 @@ private module CfgInput implements CfgShared::InputSig<Location> {
3534
scope.(Impl::CfgScope).exit(last, c)
3635
}
3736

38-
class SplitKindBase = Splitting::TSplitKind;
39-
40-
class Split = Splitting::Split;
41-
4237
class SuccessorType = Cfg::SuccessorType;
4338

4439
SuccessorType getAMatchingSuccessorType(Completion c) { result = c.getAMatchingSuccessorType() }
@@ -58,7 +53,22 @@ private module CfgInput implements CfgShared::InputSig<Location> {
5853
}
5954

6055
private import CfgInput
61-
import CfgShared::Make<Location, CfgInput>
56+
57+
private module CfgSplittingInput implements CfgShared::SplittingInputSig<Location, CfgInput> {
58+
private import Splitting as S
59+
60+
class SplitKindBase = S::TSplitKind;
61+
62+
class Split = S::Split;
63+
}
64+
65+
private module ConditionalCompletionSplittingInput implements
66+
CfgShared::ConditionalCompletionSplittingInputSig<Location, CfgInput, CfgSplittingInput>
67+
{
68+
import Splitting::ConditionalCompletionSplitting::ConditionalCompletionSplittingInput
69+
}
70+
71+
import CfgShared::MakeWithSplitting<Location, CfgInput, CfgSplittingInput, ConditionalCompletionSplittingInput>
6272

6373
class CfgScope extends Scope {
6474
predicate entry(Ast first) { first(this, first) }

powershell/ql/lib/semmle/code/powershell/controlflow/internal/Splitting.qll

Lines changed: 44 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,19 @@
33
*/
44

55
private import powershell
6-
private import Completion
6+
private import Completion as Comp
7+
private import Comp
78
private import ControlFlowGraphImpl
89
private import Cfg::SuccessorTypes
910
private import semmle.code.powershell.controlflow.ControlFlowGraph as Cfg
1011

1112
cached
1213
private module Cached {
1314
cached
14-
newtype TSplitKind =
15-
TConditionalCompletionSplitKind()
15+
newtype TSplitKind = TConditionalCompletionSplitKind()
1616

1717
cached
18-
newtype TSplit =
19-
TConditionalCompletionSplit(ConditionalCompletion c)
18+
newtype TSplit = TConditionalCompletionSplit(ConditionalCompletion c)
2019
}
2120

2221
import Cached
@@ -27,59 +26,57 @@ class Split extends TSplit {
2726
string toString() { none() }
2827
}
2928

30-
private module ConditionalCompletionSplitting {
31-
/**
32-
* A split for conditional completions.
33-
*/
29+
module ConditionalCompletionSplitting {
3430
class ConditionalCompletionSplit extends Split, TConditionalCompletionSplit {
3531
ConditionalCompletion completion;
3632

3733
ConditionalCompletionSplit() { this = TConditionalCompletionSplit(completion) }
3834

35+
ConditionalCompletion getCompletion() { result = completion }
36+
3937
override string toString() { result = completion.toString() }
4038
}
4139

42-
// private class ConditionalCompletionSplitKind extends SplitKind, TConditionalCompletionSplitKind {
43-
// override int getListOrder() { result = 0 }
44-
45-
// override predicate isEnabled(Ast n) { this.appliesTo(n) }
46-
47-
// override string toString() { result = "ConditionalCompletion" }
48-
// }
49-
50-
int getNextListOrder() { result = 1 }
51-
52-
// private class ConditionalCompletionSplitImpl extends SplitImpl instanceof ConditionalCompletionSplit
53-
// {
54-
// ConditionalCompletion completion;
55-
56-
// ConditionalCompletionSplitImpl() { this = TConditionalCompletionSplit(completion) }
40+
private class ConditionalCompletionSplitKind_ extends SplitKind, TConditionalCompletionSplitKind {
41+
override int getListOrder() { result = 0 }
5742

58-
// override ConditionalCompletionSplitKind getKind() { any() }
43+
override predicate isEnabled(Ast n) { this.appliesTo(n) }
5944

60-
// override predicate hasEntry(Ast pred, Ast succ, Completion c) {
61-
// succ(pred, succ, c) and
62-
// last(succ, _, completion) and
63-
// none() // TODO
64-
// }
65-
66-
// override predicate hasEntryScope(Cfg::CfgScope scope, Ast succ) { none() }
67-
68-
// override predicate hasExit(Ast pred, Ast succ, Completion c) {
69-
// this.appliesTo(pred) and
70-
// succ(pred, succ, c) and
71-
// if c instanceof ConditionalCompletion then completion = c else any()
72-
// }
73-
74-
// override predicate hasExitScope(Cfg::CfgScope scope, Ast last, Completion c) {
75-
// this.appliesTo(last) and
76-
// succExit(scope, last, c) and
77-
// if c instanceof ConditionalCompletion then completion = c else any()
78-
// }
45+
override string toString() { result = "ConditionalCompletion" }
46+
}
7947

80-
// override predicate hasSuccessor(Ast pred, Ast succ, Completion c) { none() }
81-
// }
48+
module ConditionalCompletionSplittingInput {
49+
private import Completion as Comp
50+
51+
class ConditionalCompletion = Comp::ConditionalCompletion;
52+
53+
class ConditionalCompletionSplitKind extends ConditionalCompletionSplitKind_, TSplitKind { }
54+
55+
class ConditionalCompletionSplit = ConditionalCompletionSplitting::ConditionalCompletionSplit;
56+
57+
bindingset[parent, parentCompletion]
58+
predicate condPropagateExpr(
59+
Ast parent, ConditionalCompletion parentCompletion, Ast child,
60+
ConditionalCompletion childCompletion
61+
) {
62+
child = parent.(NotExpr).getOperand() and
63+
childCompletion.(BooleanCompletion).getDual() = parentCompletion
64+
or
65+
childCompletion = parentCompletion and
66+
(
67+
child = parent.(LogicalAndExpr).getAnOperand()
68+
or
69+
child = parent.(LogicalOrExpr).getAnOperand()
70+
or
71+
child = parent.(ConditionalExpr).getBranch(_)
72+
)
73+
}
74+
75+
int getNextListOrder() { result = 1 }
76+
77+
private class ConditionalCompletionSplitImpl extends SplitImplementations::ConditionalCompletionSplitting::ConditionalCompletionSplitImpl
78+
{ }
79+
}
8280
}
8381

8482
class ConditionalCompletionSplit = ConditionalCompletionSplitting::ConditionalCompletionSplit;
85-

0 commit comments

Comments
 (0)