Skip to content

Commit e6f8df7

Browse files
authored
Merge pull request #131 from microsoft/powershell-splitting
PS: Use the new shared control-flow splitting library
2 parents 7a252e4 + faf3d7c commit e6f8df7

File tree

3 files changed

+91
-62
lines changed

3 files changed

+91
-62
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-

powershell/ql/test/library-tests/controlflow/graph/Cfg.expected

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -45,9 +45,11 @@
4545
| conditionals.ps1:25:5:31:14 | {...} | conditionals.ps1:27:5:30:6 | if (...) {...} | |
4646
| conditionals.ps1:27:5:30:6 | if (...) {...} | conditionals.ps1:27:8:27:16 | myBool1 | |
4747
| conditionals.ps1:27:8:27:16 | myBool1 | conditionals.ps1:27:22:27:30 | myBool2 | false, true |
48-
| conditionals.ps1:27:8:27:30 | ... -and ... | conditionals.ps1:27:8:27:30 | ... -and ... | false, true |
4948
| conditionals.ps1:27:8:27:30 | ... -and ... | conditionals.ps1:28:5:30:6 | {...} | true |
50-
| conditionals.ps1:27:22:27:30 | myBool2 | conditionals.ps1:27:8:27:30 | ... -and ... | false, true |
49+
| conditionals.ps1:27:8:27:30 | [false] ... -and ... | conditionals.ps1:27:8:27:30 | ... -and ... | false |
50+
| conditionals.ps1:27:8:27:30 | [true] ... -and ... | conditionals.ps1:27:8:27:30 | ... -and ... | true |
51+
| conditionals.ps1:27:22:27:30 | myBool2 | conditionals.ps1:27:8:27:30 | [false] ... -and ... | false |
52+
| conditionals.ps1:27:22:27:30 | myBool2 | conditionals.ps1:27:8:27:30 | [true] ... -and ... | true |
5153
| conditionals.ps1:28:5:30:6 | {...} | conditionals.ps1:29:9:29:18 | return ... | |
5254
| conditionals.ps1:29:9:29:18 | return ... | conditionals.ps1:29:16:29:18 | 10 | |
5355
| conditionals.ps1:29:16:29:18 | 10 | conditionals.ps1:29:16:29:18 | 10 | |
@@ -63,10 +65,12 @@
6365
| conditionals.ps1:35:5:44:6 | {...} | conditionals.ps1:37:5:44:6 | if (...) {...} else {...} | |
6466
| conditionals.ps1:37:5:44:6 | if (...) {...} else {...} | conditionals.ps1:37:8:37:16 | myBool1 | |
6567
| conditionals.ps1:37:8:37:16 | myBool1 | conditionals.ps1:37:22:37:30 | myBool2 | false, true |
66-
| conditionals.ps1:37:8:37:30 | ... -and ... | conditionals.ps1:37:8:37:30 | ... -and ... | false, true |
6768
| conditionals.ps1:37:8:37:30 | ... -and ... | conditionals.ps1:38:5:40:6 | {...} | true |
6869
| conditionals.ps1:37:8:37:30 | ... -and ... | conditionals.ps1:42:5:44:6 | {...} | false |
69-
| conditionals.ps1:37:22:37:30 | myBool2 | conditionals.ps1:37:8:37:30 | ... -and ... | false, true |
70+
| conditionals.ps1:37:8:37:30 | [false] ... -and ... | conditionals.ps1:37:8:37:30 | ... -and ... | false |
71+
| conditionals.ps1:37:8:37:30 | [true] ... -and ... | conditionals.ps1:37:8:37:30 | ... -and ... | true |
72+
| conditionals.ps1:37:22:37:30 | myBool2 | conditionals.ps1:37:8:37:30 | [false] ... -and ... | false |
73+
| conditionals.ps1:37:22:37:30 | myBool2 | conditionals.ps1:37:8:37:30 | [true] ... -and ... | true |
7074
| conditionals.ps1:38:5:40:6 | {...} | conditionals.ps1:39:9:39:18 | return ... | |
7175
| conditionals.ps1:39:9:39:18 | return ... | conditionals.ps1:39:16:39:18 | 10 | |
7276
| conditionals.ps1:39:16:39:18 | 10 | conditionals.ps1:34:28:45:2 | exit {...} (normal) | |
@@ -83,9 +87,11 @@
8387
| conditionals.ps1:48:5:54:14 | {...} | conditionals.ps1:50:5:53:6 | if (...) {...} | |
8488
| conditionals.ps1:50:5:53:6 | if (...) {...} | conditionals.ps1:50:8:50:16 | myBool1 | |
8589
| conditionals.ps1:50:8:50:16 | myBool1 | conditionals.ps1:50:21:50:29 | myBool2 | false, true |
86-
| conditionals.ps1:50:8:50:29 | ... -or ... | conditionals.ps1:50:8:50:29 | ... -or ... | false, true |
8790
| conditionals.ps1:50:8:50:29 | ... -or ... | conditionals.ps1:51:5:53:6 | {...} | true |
88-
| conditionals.ps1:50:21:50:29 | myBool2 | conditionals.ps1:50:8:50:29 | ... -or ... | false, true |
91+
| conditionals.ps1:50:8:50:29 | [false] ... -or ... | conditionals.ps1:50:8:50:29 | ... -or ... | false |
92+
| conditionals.ps1:50:8:50:29 | [true] ... -or ... | conditionals.ps1:50:8:50:29 | ... -or ... | true |
93+
| conditionals.ps1:50:21:50:29 | myBool2 | conditionals.ps1:50:8:50:29 | [false] ... -or ... | false |
94+
| conditionals.ps1:50:21:50:29 | myBool2 | conditionals.ps1:50:8:50:29 | [true] ... -or ... | true |
8995
| conditionals.ps1:51:5:53:6 | {...} | conditionals.ps1:52:9:52:18 | return ... | |
9096
| conditionals.ps1:52:9:52:18 | return ... | conditionals.ps1:52:16:52:18 | 10 | |
9197
| conditionals.ps1:52:16:52:18 | 10 | conditionals.ps1:52:16:52:18 | 10 | |
@@ -101,10 +107,12 @@
101107
| conditionals.ps1:58:5:67:6 | {...} | conditionals.ps1:60:5:67:6 | if (...) {...} else {...} | |
102108
| conditionals.ps1:60:5:67:6 | if (...) {...} else {...} | conditionals.ps1:60:8:60:16 | myBool1 | |
103109
| conditionals.ps1:60:8:60:16 | myBool1 | conditionals.ps1:60:21:60:29 | myBool2 | false, true |
104-
| conditionals.ps1:60:8:60:29 | ... -or ... | conditionals.ps1:60:8:60:29 | ... -or ... | false, true |
105110
| conditionals.ps1:60:8:60:29 | ... -or ... | conditionals.ps1:61:5:63:6 | {...} | true |
106111
| conditionals.ps1:60:8:60:29 | ... -or ... | conditionals.ps1:65:5:67:6 | {...} | false |
107-
| conditionals.ps1:60:21:60:29 | myBool2 | conditionals.ps1:60:8:60:29 | ... -or ... | false, true |
112+
| conditionals.ps1:60:8:60:29 | [false] ... -or ... | conditionals.ps1:60:8:60:29 | ... -or ... | false |
113+
| conditionals.ps1:60:8:60:29 | [true] ... -or ... | conditionals.ps1:60:8:60:29 | ... -or ... | true |
114+
| conditionals.ps1:60:21:60:29 | myBool2 | conditionals.ps1:60:8:60:29 | [false] ... -or ... | false |
115+
| conditionals.ps1:60:21:60:29 | myBool2 | conditionals.ps1:60:8:60:29 | [true] ... -or ... | true |
108116
| conditionals.ps1:61:5:63:6 | {...} | conditionals.ps1:62:9:62:18 | return ... | |
109117
| conditionals.ps1:62:9:62:18 | return ... | conditionals.ps1:62:16:62:18 | 10 | |
110118
| conditionals.ps1:62:16:62:18 | 10 | conditionals.ps1:57:28:68:2 | exit {...} (normal) | |
@@ -122,10 +130,17 @@
122130
| conditionals.ps1:73:5:80:6 | if (...) {...} | conditionals.ps1:73:8:73:16 | myBool1 | |
123131
| conditionals.ps1:73:8:73:16 | myBool1 | conditionals.ps1:73:8:73:16 | myBool1 | false, true |
124132
| conditionals.ps1:73:8:73:16 | myBool1 | conditionals.ps1:74:5:76:6 | {...} | true |
133+
| conditionals.ps1:73:8:73:16 | myBool1 | conditionals.ps1:77:12:77:19 | myBoo2 | false |
125134
| conditionals.ps1:74:5:76:6 | {...} | conditionals.ps1:75:9:75:18 | return ... | |
126135
| conditionals.ps1:75:9:75:18 | return ... | conditionals.ps1:75:16:75:18 | 10 | |
127136
| conditionals.ps1:75:16:75:18 | 10 | conditionals.ps1:75:16:75:18 | 10 | |
128137
| conditionals.ps1:75:16:75:18 | 10 | conditionals.ps1:81:5:81:14 | return ... | |
138+
| conditionals.ps1:77:12:77:19 | myBoo2 | conditionals.ps1:77:12:77:19 | myBoo2 | false, true |
139+
| conditionals.ps1:77:12:77:19 | myBoo2 | conditionals.ps1:78:5:80:6 | {...} | true |
140+
| conditionals.ps1:78:5:80:6 | {...} | conditionals.ps1:79:9:79:18 | return ... | |
141+
| conditionals.ps1:79:9:79:18 | return ... | conditionals.ps1:79:16:79:18 | 11 | |
142+
| conditionals.ps1:79:16:79:18 | 11 | conditionals.ps1:79:16:79:18 | 11 | |
143+
| conditionals.ps1:79:16:79:18 | 11 | conditionals.ps1:81:5:81:14 | return ... | |
129144
| conditionals.ps1:81:5:81:14 | return ... | conditionals.ps1:81:12:81:14 | 12 | |
130145
| conditionals.ps1:81:12:81:14 | 12 | conditionals.ps1:70:23:82:2 | exit {...} (normal) | |
131146
| conditionals.ps1:81:12:81:14 | 12 | conditionals.ps1:81:12:81:14 | 12 | |
@@ -138,11 +153,18 @@
138153
| conditionals.ps1:87:5:98:6 | if (...) {...} else {...} | conditionals.ps1:87:8:87:16 | myBool1 | |
139154
| conditionals.ps1:87:8:87:16 | myBool1 | conditionals.ps1:87:8:87:16 | myBool1 | false, true |
140155
| conditionals.ps1:87:8:87:16 | myBool1 | conditionals.ps1:88:5:90:6 | {...} | true |
141-
| conditionals.ps1:87:8:87:16 | myBool1 | conditionals.ps1:96:5:98:6 | {...} | false |
156+
| conditionals.ps1:87:8:87:16 | myBool1 | conditionals.ps1:91:12:91:19 | myBoo2 | false |
142157
| conditionals.ps1:88:5:90:6 | {...} | conditionals.ps1:89:9:89:18 | return ... | |
143158
| conditionals.ps1:89:9:89:18 | return ... | conditionals.ps1:89:16:89:18 | 10 | |
144159
| conditionals.ps1:89:16:89:18 | 10 | conditionals.ps1:84:28:99:2 | exit {...} (normal) | |
145160
| conditionals.ps1:89:16:89:18 | 10 | conditionals.ps1:89:16:89:18 | 10 | |
161+
| conditionals.ps1:91:12:91:19 | myBoo2 | conditionals.ps1:91:12:91:19 | myBoo2 | false, true |
162+
| conditionals.ps1:91:12:91:19 | myBoo2 | conditionals.ps1:92:5:94:6 | {...} | true |
163+
| conditionals.ps1:91:12:91:19 | myBoo2 | conditionals.ps1:96:5:98:6 | {...} | false |
164+
| conditionals.ps1:92:5:94:6 | {...} | conditionals.ps1:93:9:93:18 | return ... | |
165+
| conditionals.ps1:93:9:93:18 | return ... | conditionals.ps1:93:16:93:18 | 11 | |
166+
| conditionals.ps1:93:16:93:18 | 11 | conditionals.ps1:84:28:99:2 | exit {...} (normal) | |
167+
| conditionals.ps1:93:16:93:18 | 11 | conditionals.ps1:93:16:93:18 | 11 | |
146168
| conditionals.ps1:96:5:98:6 | {...} | conditionals.ps1:97:9:97:18 | return ... | |
147169
| conditionals.ps1:97:9:97:18 | return ... | conditionals.ps1:97:16:97:18 | 12 | |
148170
| conditionals.ps1:97:16:97:18 | 12 | conditionals.ps1:84:28:99:2 | exit {...} (normal) | |

0 commit comments

Comments
 (0)