Skip to content

Commit

Permalink
Merge pull request #131 from microsoft/powershell-splitting
Browse files Browse the repository at this point in the history
PS: Use the new shared control-flow splitting library
  • Loading branch information
MathiasVP authored Nov 4, 2024
2 parents 7a252e4 + faf3d7c commit e6f8df7
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 62 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ private import Completion
private module CfgInput implements CfgShared::InputSig<Location> {
private import ControlFlowGraphImpl as Impl
private import Completion as Comp
private import Splitting as Splitting
private import semmle.code.powershell.Cfg as Cfg

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

class SplitKindBase = Splitting::TSplitKind;

class Split = Splitting::Split;

class SuccessorType = Cfg::SuccessorType;

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

private import CfgInput
import CfgShared::Make<Location, CfgInput>

private module CfgSplittingInput implements CfgShared::SplittingInputSig<Location, CfgInput> {
private import Splitting as S

class SplitKindBase = S::TSplitKind;

class Split = S::Split;
}

private module ConditionalCompletionSplittingInput implements
CfgShared::ConditionalCompletionSplittingInputSig<Location, CfgInput, CfgSplittingInput>
{
import Splitting::ConditionalCompletionSplitting::ConditionalCompletionSplittingInput
}

import CfgShared::MakeWithSplitting<Location, CfgInput, CfgSplittingInput, ConditionalCompletionSplittingInput>

class CfgScope extends Scope {
predicate entry(Ast first) { first(this, first) }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,20 +3,19 @@
*/

private import powershell
private import Completion
private import Completion as Comp
private import Comp
private import ControlFlowGraphImpl
private import Cfg::SuccessorTypes
private import semmle.code.powershell.controlflow.ControlFlowGraph as Cfg

cached
private module Cached {
cached
newtype TSplitKind =
TConditionalCompletionSplitKind()
newtype TSplitKind = TConditionalCompletionSplitKind()

cached
newtype TSplit =
TConditionalCompletionSplit(ConditionalCompletion c)
newtype TSplit = TConditionalCompletionSplit(ConditionalCompletion c)
}

import Cached
Expand All @@ -27,59 +26,57 @@ class Split extends TSplit {
string toString() { none() }
}

private module ConditionalCompletionSplitting {
/**
* A split for conditional completions.
*/
module ConditionalCompletionSplitting {
class ConditionalCompletionSplit extends Split, TConditionalCompletionSplit {
ConditionalCompletion completion;

ConditionalCompletionSplit() { this = TConditionalCompletionSplit(completion) }

ConditionalCompletion getCompletion() { result = completion }

override string toString() { result = completion.toString() }
}

// private class ConditionalCompletionSplitKind extends SplitKind, TConditionalCompletionSplitKind {
// override int getListOrder() { result = 0 }

// override predicate isEnabled(Ast n) { this.appliesTo(n) }

// override string toString() { result = "ConditionalCompletion" }
// }

int getNextListOrder() { result = 1 }

// private class ConditionalCompletionSplitImpl extends SplitImpl instanceof ConditionalCompletionSplit
// {
// ConditionalCompletion completion;

// ConditionalCompletionSplitImpl() { this = TConditionalCompletionSplit(completion) }
private class ConditionalCompletionSplitKind_ extends SplitKind, TConditionalCompletionSplitKind {
override int getListOrder() { result = 0 }

// override ConditionalCompletionSplitKind getKind() { any() }
override predicate isEnabled(Ast n) { this.appliesTo(n) }

// override predicate hasEntry(Ast pred, Ast succ, Completion c) {
// succ(pred, succ, c) and
// last(succ, _, completion) and
// none() // TODO
// }

// override predicate hasEntryScope(Cfg::CfgScope scope, Ast succ) { none() }

// override predicate hasExit(Ast pred, Ast succ, Completion c) {
// this.appliesTo(pred) and
// succ(pred, succ, c) and
// if c instanceof ConditionalCompletion then completion = c else any()
// }

// override predicate hasExitScope(Cfg::CfgScope scope, Ast last, Completion c) {
// this.appliesTo(last) and
// succExit(scope, last, c) and
// if c instanceof ConditionalCompletion then completion = c else any()
// }
override string toString() { result = "ConditionalCompletion" }
}

// override predicate hasSuccessor(Ast pred, Ast succ, Completion c) { none() }
// }
module ConditionalCompletionSplittingInput {
private import Completion as Comp

class ConditionalCompletion = Comp::ConditionalCompletion;

class ConditionalCompletionSplitKind extends ConditionalCompletionSplitKind_, TSplitKind { }

class ConditionalCompletionSplit = ConditionalCompletionSplitting::ConditionalCompletionSplit;

bindingset[parent, parentCompletion]
predicate condPropagateExpr(
Ast parent, ConditionalCompletion parentCompletion, Ast child,
ConditionalCompletion childCompletion
) {
child = parent.(NotExpr).getOperand() and
childCompletion.(BooleanCompletion).getDual() = parentCompletion
or
childCompletion = parentCompletion and
(
child = parent.(LogicalAndExpr).getAnOperand()
or
child = parent.(LogicalOrExpr).getAnOperand()
or
child = parent.(ConditionalExpr).getBranch(_)
)
}

int getNextListOrder() { result = 1 }

private class ConditionalCompletionSplitImpl extends SplitImplementations::ConditionalCompletionSplitting::ConditionalCompletionSplitImpl
{ }
}
}

class ConditionalCompletionSplit = ConditionalCompletionSplitting::ConditionalCompletionSplit;

40 changes: 31 additions & 9 deletions powershell/ql/test/library-tests/controlflow/graph/Cfg.expected
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,11 @@
| conditionals.ps1:25:5:31:14 | {...} | conditionals.ps1:27:5:30:6 | if (...) {...} | |
| conditionals.ps1:27:5:30:6 | if (...) {...} | conditionals.ps1:27:8:27:16 | myBool1 | |
| conditionals.ps1:27:8:27:16 | myBool1 | conditionals.ps1:27:22:27:30 | myBool2 | false, true |
| conditionals.ps1:27:8:27:30 | ... -and ... | conditionals.ps1:27:8:27:30 | ... -and ... | false, true |
| conditionals.ps1:27:8:27:30 | ... -and ... | conditionals.ps1:28:5:30:6 | {...} | true |
| conditionals.ps1:27:22:27:30 | myBool2 | conditionals.ps1:27:8:27:30 | ... -and ... | false, true |
| conditionals.ps1:27:8:27:30 | [false] ... -and ... | conditionals.ps1:27:8:27:30 | ... -and ... | false |
| conditionals.ps1:27:8:27:30 | [true] ... -and ... | conditionals.ps1:27:8:27:30 | ... -and ... | true |
| conditionals.ps1:27:22:27:30 | myBool2 | conditionals.ps1:27:8:27:30 | [false] ... -and ... | false |
| conditionals.ps1:27:22:27:30 | myBool2 | conditionals.ps1:27:8:27:30 | [true] ... -and ... | true |
| conditionals.ps1:28:5:30:6 | {...} | conditionals.ps1:29:9:29:18 | return ... | |
| conditionals.ps1:29:9:29:18 | return ... | conditionals.ps1:29:16:29:18 | 10 | |
| conditionals.ps1:29:16:29:18 | 10 | conditionals.ps1:29:16:29:18 | 10 | |
Expand All @@ -63,10 +65,12 @@
| conditionals.ps1:35:5:44:6 | {...} | conditionals.ps1:37:5:44:6 | if (...) {...} else {...} | |
| conditionals.ps1:37:5:44:6 | if (...) {...} else {...} | conditionals.ps1:37:8:37:16 | myBool1 | |
| conditionals.ps1:37:8:37:16 | myBool1 | conditionals.ps1:37:22:37:30 | myBool2 | false, true |
| conditionals.ps1:37:8:37:30 | ... -and ... | conditionals.ps1:37:8:37:30 | ... -and ... | false, true |
| conditionals.ps1:37:8:37:30 | ... -and ... | conditionals.ps1:38:5:40:6 | {...} | true |
| conditionals.ps1:37:8:37:30 | ... -and ... | conditionals.ps1:42:5:44:6 | {...} | false |
| conditionals.ps1:37:22:37:30 | myBool2 | conditionals.ps1:37:8:37:30 | ... -and ... | false, true |
| conditionals.ps1:37:8:37:30 | [false] ... -and ... | conditionals.ps1:37:8:37:30 | ... -and ... | false |
| conditionals.ps1:37:8:37:30 | [true] ... -and ... | conditionals.ps1:37:8:37:30 | ... -and ... | true |
| conditionals.ps1:37:22:37:30 | myBool2 | conditionals.ps1:37:8:37:30 | [false] ... -and ... | false |
| conditionals.ps1:37:22:37:30 | myBool2 | conditionals.ps1:37:8:37:30 | [true] ... -and ... | true |
| conditionals.ps1:38:5:40:6 | {...} | conditionals.ps1:39:9:39:18 | return ... | |
| conditionals.ps1:39:9:39:18 | return ... | conditionals.ps1:39:16:39:18 | 10 | |
| conditionals.ps1:39:16:39:18 | 10 | conditionals.ps1:34:28:45:2 | exit {...} (normal) | |
Expand All @@ -83,9 +87,11 @@
| conditionals.ps1:48:5:54:14 | {...} | conditionals.ps1:50:5:53:6 | if (...) {...} | |
| conditionals.ps1:50:5:53:6 | if (...) {...} | conditionals.ps1:50:8:50:16 | myBool1 | |
| conditionals.ps1:50:8:50:16 | myBool1 | conditionals.ps1:50:21:50:29 | myBool2 | false, true |
| conditionals.ps1:50:8:50:29 | ... -or ... | conditionals.ps1:50:8:50:29 | ... -or ... | false, true |
| conditionals.ps1:50:8:50:29 | ... -or ... | conditionals.ps1:51:5:53:6 | {...} | true |
| conditionals.ps1:50:21:50:29 | myBool2 | conditionals.ps1:50:8:50:29 | ... -or ... | false, true |
| conditionals.ps1:50:8:50:29 | [false] ... -or ... | conditionals.ps1:50:8:50:29 | ... -or ... | false |
| conditionals.ps1:50:8:50:29 | [true] ... -or ... | conditionals.ps1:50:8:50:29 | ... -or ... | true |
| conditionals.ps1:50:21:50:29 | myBool2 | conditionals.ps1:50:8:50:29 | [false] ... -or ... | false |
| conditionals.ps1:50:21:50:29 | myBool2 | conditionals.ps1:50:8:50:29 | [true] ... -or ... | true |
| conditionals.ps1:51:5:53:6 | {...} | conditionals.ps1:52:9:52:18 | return ... | |
| conditionals.ps1:52:9:52:18 | return ... | conditionals.ps1:52:16:52:18 | 10 | |
| conditionals.ps1:52:16:52:18 | 10 | conditionals.ps1:52:16:52:18 | 10 | |
Expand All @@ -101,10 +107,12 @@
| conditionals.ps1:58:5:67:6 | {...} | conditionals.ps1:60:5:67:6 | if (...) {...} else {...} | |
| conditionals.ps1:60:5:67:6 | if (...) {...} else {...} | conditionals.ps1:60:8:60:16 | myBool1 | |
| conditionals.ps1:60:8:60:16 | myBool1 | conditionals.ps1:60:21:60:29 | myBool2 | false, true |
| conditionals.ps1:60:8:60:29 | ... -or ... | conditionals.ps1:60:8:60:29 | ... -or ... | false, true |
| conditionals.ps1:60:8:60:29 | ... -or ... | conditionals.ps1:61:5:63:6 | {...} | true |
| conditionals.ps1:60:8:60:29 | ... -or ... | conditionals.ps1:65:5:67:6 | {...} | false |
| conditionals.ps1:60:21:60:29 | myBool2 | conditionals.ps1:60:8:60:29 | ... -or ... | false, true |
| conditionals.ps1:60:8:60:29 | [false] ... -or ... | conditionals.ps1:60:8:60:29 | ... -or ... | false |
| conditionals.ps1:60:8:60:29 | [true] ... -or ... | conditionals.ps1:60:8:60:29 | ... -or ... | true |
| conditionals.ps1:60:21:60:29 | myBool2 | conditionals.ps1:60:8:60:29 | [false] ... -or ... | false |
| conditionals.ps1:60:21:60:29 | myBool2 | conditionals.ps1:60:8:60:29 | [true] ... -or ... | true |
| conditionals.ps1:61:5:63:6 | {...} | conditionals.ps1:62:9:62:18 | return ... | |
| conditionals.ps1:62:9:62:18 | return ... | conditionals.ps1:62:16:62:18 | 10 | |
| conditionals.ps1:62:16:62:18 | 10 | conditionals.ps1:57:28:68:2 | exit {...} (normal) | |
Expand All @@ -122,10 +130,17 @@
| conditionals.ps1:73:5:80:6 | if (...) {...} | conditionals.ps1:73:8:73:16 | myBool1 | |
| conditionals.ps1:73:8:73:16 | myBool1 | conditionals.ps1:73:8:73:16 | myBool1 | false, true |
| conditionals.ps1:73:8:73:16 | myBool1 | conditionals.ps1:74:5:76:6 | {...} | true |
| conditionals.ps1:73:8:73:16 | myBool1 | conditionals.ps1:77:12:77:19 | myBoo2 | false |
| conditionals.ps1:74:5:76:6 | {...} | conditionals.ps1:75:9:75:18 | return ... | |
| conditionals.ps1:75:9:75:18 | return ... | conditionals.ps1:75:16:75:18 | 10 | |
| conditionals.ps1:75:16:75:18 | 10 | conditionals.ps1:75:16:75:18 | 10 | |
| conditionals.ps1:75:16:75:18 | 10 | conditionals.ps1:81:5:81:14 | return ... | |
| conditionals.ps1:77:12:77:19 | myBoo2 | conditionals.ps1:77:12:77:19 | myBoo2 | false, true |
| conditionals.ps1:77:12:77:19 | myBoo2 | conditionals.ps1:78:5:80:6 | {...} | true |
| conditionals.ps1:78:5:80:6 | {...} | conditionals.ps1:79:9:79:18 | return ... | |
| conditionals.ps1:79:9:79:18 | return ... | conditionals.ps1:79:16:79:18 | 11 | |
| conditionals.ps1:79:16:79:18 | 11 | conditionals.ps1:79:16:79:18 | 11 | |
| conditionals.ps1:79:16:79:18 | 11 | conditionals.ps1:81:5:81:14 | return ... | |
| conditionals.ps1:81:5:81:14 | return ... | conditionals.ps1:81:12:81:14 | 12 | |
| conditionals.ps1:81:12:81:14 | 12 | conditionals.ps1:70:23:82:2 | exit {...} (normal) | |
| conditionals.ps1:81:12:81:14 | 12 | conditionals.ps1:81:12:81:14 | 12 | |
Expand All @@ -138,11 +153,18 @@
| conditionals.ps1:87:5:98:6 | if (...) {...} else {...} | conditionals.ps1:87:8:87:16 | myBool1 | |
| conditionals.ps1:87:8:87:16 | myBool1 | conditionals.ps1:87:8:87:16 | myBool1 | false, true |
| conditionals.ps1:87:8:87:16 | myBool1 | conditionals.ps1:88:5:90:6 | {...} | true |
| conditionals.ps1:87:8:87:16 | myBool1 | conditionals.ps1:96:5:98:6 | {...} | false |
| conditionals.ps1:87:8:87:16 | myBool1 | conditionals.ps1:91:12:91:19 | myBoo2 | false |
| conditionals.ps1:88:5:90:6 | {...} | conditionals.ps1:89:9:89:18 | return ... | |
| conditionals.ps1:89:9:89:18 | return ... | conditionals.ps1:89:16:89:18 | 10 | |
| conditionals.ps1:89:16:89:18 | 10 | conditionals.ps1:84:28:99:2 | exit {...} (normal) | |
| conditionals.ps1:89:16:89:18 | 10 | conditionals.ps1:89:16:89:18 | 10 | |
| conditionals.ps1:91:12:91:19 | myBoo2 | conditionals.ps1:91:12:91:19 | myBoo2 | false, true |
| conditionals.ps1:91:12:91:19 | myBoo2 | conditionals.ps1:92:5:94:6 | {...} | true |
| conditionals.ps1:91:12:91:19 | myBoo2 | conditionals.ps1:96:5:98:6 | {...} | false |
| conditionals.ps1:92:5:94:6 | {...} | conditionals.ps1:93:9:93:18 | return ... | |
| conditionals.ps1:93:9:93:18 | return ... | conditionals.ps1:93:16:93:18 | 11 | |
| conditionals.ps1:93:16:93:18 | 11 | conditionals.ps1:84:28:99:2 | exit {...} (normal) | |
| conditionals.ps1:93:16:93:18 | 11 | conditionals.ps1:93:16:93:18 | 11 | |
| conditionals.ps1:96:5:98:6 | {...} | conditionals.ps1:97:9:97:18 | return ... | |
| conditionals.ps1:97:9:97:18 | return ... | conditionals.ps1:97:16:97:18 | 12 | |
| conditionals.ps1:97:16:97:18 | 12 | conditionals.ps1:84:28:99:2 | exit {...} (normal) | |
Expand Down

0 comments on commit e6f8df7

Please sign in to comment.