Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit e24e5b1

Browse files
committed
C#: Improve CFG to handle 'and' and 'or' patterns
1 parent 4685fc0 commit e24e5b1

13 files changed

Lines changed: 452 additions & 1 deletion

File tree

csharp/ql/src/semmle/code/csharp/controlflow/internal/Completion.qll

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -552,6 +552,8 @@ private predicate mustHaveMatchingCompletion(Expr e, PatternExpr pe) {
552552
pe = any(IsExpr ie | inBooleanContext(ie) and e = ie.getExpr()).getPattern()
553553
or
554554
pe = any(UnaryPatternExpr upe | mustHaveMatchingCompletion(e, upe)).getPattern()
555+
or
556+
pe = any(BinaryPatternExpr bpe | mustHaveMatchingCompletion(e, bpe)).getAnOperand()
555557
}
556558

557559
/**

csharp/ql/src/semmle/code/csharp/controlflow/internal/ControlFlowGraphImpl.qll

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -360,7 +360,9 @@ module Expressions {
360360
not this instanceof SwitchExpr and
361361
not this instanceof SwitchCaseExpr and
362362
not this instanceof ConstructorInitializer and
363-
not this instanceof NotPatternExpr
363+
not this instanceof NotPatternExpr and
364+
not this instanceof OrPatternExpr and
365+
not this instanceof AndPatternExpr
364366
}
365367

366368
final override ControlFlowElement getChildElement(int i) { result = getExprChild(this, i) }
@@ -902,6 +904,56 @@ module Expressions {
902904
c instanceof NormalCompletion
903905
}
904906
}
907+
908+
private class AndPatternExprTree extends PostOrderTree, AndPatternExpr {
909+
final override predicate propagatesAbnormal(ControlFlowElement child) {
910+
child = this.getAnOperand()
911+
}
912+
913+
final override predicate first(ControlFlowElement first) { first(this.getLeftOperand(), first) }
914+
915+
final override predicate succ(ControlFlowElement pred, ControlFlowElement succ, Completion c) {
916+
// Flow from last element of left operand to first element of right operand
917+
last(this.getLeftOperand(), pred, c) and
918+
c.(MatchingCompletion).getValue() = true and
919+
first(this.getRightOperand(), succ)
920+
or
921+
// Post-order: flow from last element of left operand to element itself
922+
last(this.getLeftOperand(), pred, c) and
923+
c.(MatchingCompletion).getValue() = false and
924+
succ = this
925+
or
926+
// Post-order: flow from last element of right operand to element itself
927+
last(this.getRightOperand(), pred, c) and
928+
c instanceof MatchingCompletion and
929+
succ = this
930+
}
931+
}
932+
933+
private class OrPatternExprTree extends PostOrderTree, OrPatternExpr {
934+
final override predicate propagatesAbnormal(ControlFlowElement child) {
935+
child = this.getAnOperand()
936+
}
937+
938+
final override predicate first(ControlFlowElement first) { first(this.getLeftOperand(), first) }
939+
940+
final override predicate succ(ControlFlowElement pred, ControlFlowElement succ, Completion c) {
941+
// Flow from last element of left operand to first element of right operand
942+
last(this.getLeftOperand(), pred, c) and
943+
c.(MatchingCompletion).getValue() = false and
944+
first(this.getRightOperand(), succ)
945+
or
946+
// Post-order: flow from last element of left operand to element itself
947+
last(this.getLeftOperand(), pred, c) and
948+
c.(MatchingCompletion).getValue() = true and
949+
succ = this
950+
or
951+
// Post-order: flow from last element of right operand to element itself
952+
last(this.getRightOperand(), pred, c) and
953+
c instanceof MatchingCompletion and
954+
succ = this
955+
}
956+
}
905957
}
906958

907959
module Statements {

csharp/ql/src/semmle/code/csharp/controlflow/internal/Splitting.qll

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -471,6 +471,12 @@ module ConditionalCompletionSplitting {
471471
or
472472
last(succ.(IsExpr).getPattern(), pred, c) and
473473
completion.(BooleanCompletion).getValue() = c.(MatchingCompletion).getValue()
474+
or
475+
last(succ.(AndPatternExpr).getAnOperand(), pred, c) and
476+
completion = c
477+
or
478+
last(succ.(OrPatternExpr).getAnOperand(), pred, c) and
479+
completion = c
474480
)
475481
}
476482

csharp/ql/src/semmle/code/csharp/exprs/Expr.qll

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -509,6 +509,9 @@ class NotPatternExpr extends UnaryPatternExpr, @not_pattern_expr {
509509

510510
/** A binary pattern. For example, `1 or 2`. */
511511
class BinaryPatternExpr extends PatternExpr, @binary_pattern_expr {
512+
/** Gets a pattern. */
513+
PatternExpr getAnOperand() { result = getLeftOperand() or result = getRightOperand() }
514+
512515
/** Gets the left pattern. */
513516
PatternExpr getLeftOperand() { result = this.getChild(0) }
514517

csharp/ql/test/library-tests/controlflow/graph/BasicBlock.expected

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -983,6 +983,28 @@
983983
| Patterns.cs:80:18:80:20 | "1" | Patterns.cs:80:13:80:20 | ... => ... | 2 |
984984
| Patterns.cs:81:13:81:13 | _ | Patterns.cs:81:13:81:13 | _ | 1 |
985985
| Patterns.cs:81:18:81:20 | "0" | Patterns.cs:81:13:81:20 | ... => ... | 2 |
986+
| Patterns.cs:85:26:85:27 | enter M8 | Patterns.cs:85:44:85:44 | 1 | 3 |
987+
| Patterns.cs:85:39:85:53 | [false] ... is ... | Patterns.cs:85:39:85:53 | [false] ... is ... | 1 |
988+
| Patterns.cs:85:39:85:53 | [true] ... is ... | Patterns.cs:85:39:85:53 | [true] ... is ... | 1 |
989+
| Patterns.cs:85:39:85:69 | ... ? ... : ... | Patterns.cs:85:26:85:27 | exit M8 | 3 |
990+
| Patterns.cs:85:44:85:53 | [match] ... or ... | Patterns.cs:85:44:85:53 | [match] ... or ... | 1 |
991+
| Patterns.cs:85:44:85:53 | [no-match] ... or ... | Patterns.cs:85:44:85:53 | [no-match] ... or ... | 1 |
992+
| Patterns.cs:85:49:85:53 | [match] not ... | Patterns.cs:85:49:85:53 | [match] not ... | 1 |
993+
| Patterns.cs:85:49:85:53 | [no-match] not ... | Patterns.cs:85:49:85:53 | [no-match] not ... | 1 |
994+
| Patterns.cs:85:53:85:53 | 2 | Patterns.cs:85:53:85:53 | 2 | 1 |
995+
| Patterns.cs:85:57:85:63 | "not 2" | Patterns.cs:85:57:85:63 | "not 2" | 1 |
996+
| Patterns.cs:85:67:85:69 | "2" | Patterns.cs:85:67:85:69 | "2" | 1 |
997+
| Patterns.cs:87:26:87:27 | enter M9 | Patterns.cs:87:44:87:44 | 1 | 3 |
998+
| Patterns.cs:87:39:87:54 | [false] ... is ... | Patterns.cs:87:39:87:54 | [false] ... is ... | 1 |
999+
| Patterns.cs:87:39:87:54 | [true] ... is ... | Patterns.cs:87:39:87:54 | [true] ... is ... | 1 |
1000+
| Patterns.cs:87:39:87:70 | ... ? ... : ... | Patterns.cs:87:26:87:27 | exit M9 | 3 |
1001+
| Patterns.cs:87:44:87:54 | [match] ... and ... | Patterns.cs:87:44:87:54 | [match] ... and ... | 1 |
1002+
| Patterns.cs:87:44:87:54 | [no-match] ... and ... | Patterns.cs:87:44:87:54 | [no-match] ... and ... | 1 |
1003+
| Patterns.cs:87:50:87:54 | [match] not ... | Patterns.cs:87:50:87:54 | [match] not ... | 1 |
1004+
| Patterns.cs:87:50:87:54 | [no-match] not ... | Patterns.cs:87:50:87:54 | [no-match] not ... | 1 |
1005+
| Patterns.cs:87:54:87:54 | 2 | Patterns.cs:87:54:87:54 | 2 | 1 |
1006+
| Patterns.cs:87:58:87:60 | "1" | Patterns.cs:87:58:87:60 | "1" | 1 |
1007+
| Patterns.cs:87:64:87:70 | "not 1" | Patterns.cs:87:64:87:70 | "not 1" | 1 |
9861008
| PostDominance.cs:5:10:5:11 | enter M1 | PostDominance.cs:5:10:5:11 | exit M1 | 7 |
9871009
| PostDominance.cs:10:10:10:11 | enter M2 | PostDominance.cs:12:18:12:21 | null | 5 |
9881010
| PostDominance.cs:10:10:10:11 | exit M2 (normal) | PostDominance.cs:10:10:10:11 | exit M2 | 2 |

csharp/ql/test/library-tests/controlflow/graph/Condition.expected

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1890,6 +1890,46 @@ conditionBlock
18901890
| Patterns.cs:80:13:80:13 | 1 | Patterns.cs:81:13:81:13 | _ | false |
18911891
| Patterns.cs:80:13:80:13 | 1 | Patterns.cs:81:18:81:20 | "0" | false |
18921892
| Patterns.cs:81:13:81:13 | _ | Patterns.cs:81:18:81:20 | "0" | true |
1893+
| Patterns.cs:85:26:85:27 | enter M8 | Patterns.cs:85:39:85:53 | [false] ... is ... | false |
1894+
| Patterns.cs:85:26:85:27 | enter M8 | Patterns.cs:85:44:85:53 | [no-match] ... or ... | false |
1895+
| Patterns.cs:85:26:85:27 | enter M8 | Patterns.cs:85:49:85:53 | [match] not ... | false |
1896+
| Patterns.cs:85:26:85:27 | enter M8 | Patterns.cs:85:49:85:53 | [no-match] not ... | false |
1897+
| Patterns.cs:85:26:85:27 | enter M8 | Patterns.cs:85:53:85:53 | 2 | false |
1898+
| Patterns.cs:85:26:85:27 | enter M8 | Patterns.cs:85:67:85:69 | "2" | false |
1899+
| Patterns.cs:85:39:85:53 | [false] ... is ... | Patterns.cs:85:67:85:69 | "2" | false |
1900+
| Patterns.cs:85:39:85:53 | [true] ... is ... | Patterns.cs:85:57:85:63 | "not 2" | true |
1901+
| Patterns.cs:85:44:85:53 | [match] ... or ... | Patterns.cs:85:39:85:53 | [true] ... is ... | true |
1902+
| Patterns.cs:85:44:85:53 | [match] ... or ... | Patterns.cs:85:57:85:63 | "not 2" | true |
1903+
| Patterns.cs:85:44:85:53 | [no-match] ... or ... | Patterns.cs:85:39:85:53 | [false] ... is ... | false |
1904+
| Patterns.cs:85:44:85:53 | [no-match] ... or ... | Patterns.cs:85:67:85:69 | "2" | false |
1905+
| Patterns.cs:85:49:85:53 | [no-match] not ... | Patterns.cs:85:39:85:53 | [false] ... is ... | false |
1906+
| Patterns.cs:85:49:85:53 | [no-match] not ... | Patterns.cs:85:44:85:53 | [no-match] ... or ... | false |
1907+
| Patterns.cs:85:49:85:53 | [no-match] not ... | Patterns.cs:85:67:85:69 | "2" | false |
1908+
| Patterns.cs:85:53:85:53 | 2 | Patterns.cs:85:39:85:53 | [false] ... is ... | true |
1909+
| Patterns.cs:85:53:85:53 | 2 | Patterns.cs:85:44:85:53 | [no-match] ... or ... | true |
1910+
| Patterns.cs:85:53:85:53 | 2 | Patterns.cs:85:49:85:53 | [match] not ... | false |
1911+
| Patterns.cs:85:53:85:53 | 2 | Patterns.cs:85:49:85:53 | [no-match] not ... | true |
1912+
| Patterns.cs:85:53:85:53 | 2 | Patterns.cs:85:67:85:69 | "2" | true |
1913+
| Patterns.cs:87:26:87:27 | enter M9 | Patterns.cs:87:39:87:54 | [true] ... is ... | true |
1914+
| Patterns.cs:87:26:87:27 | enter M9 | Patterns.cs:87:44:87:54 | [match] ... and ... | true |
1915+
| Patterns.cs:87:26:87:27 | enter M9 | Patterns.cs:87:50:87:54 | [match] not ... | true |
1916+
| Patterns.cs:87:26:87:27 | enter M9 | Patterns.cs:87:50:87:54 | [no-match] not ... | true |
1917+
| Patterns.cs:87:26:87:27 | enter M9 | Patterns.cs:87:54:87:54 | 2 | true |
1918+
| Patterns.cs:87:26:87:27 | enter M9 | Patterns.cs:87:58:87:60 | "1" | true |
1919+
| Patterns.cs:87:39:87:54 | [false] ... is ... | Patterns.cs:87:64:87:70 | "not 1" | false |
1920+
| Patterns.cs:87:39:87:54 | [true] ... is ... | Patterns.cs:87:58:87:60 | "1" | true |
1921+
| Patterns.cs:87:44:87:54 | [match] ... and ... | Patterns.cs:87:39:87:54 | [true] ... is ... | true |
1922+
| Patterns.cs:87:44:87:54 | [match] ... and ... | Patterns.cs:87:58:87:60 | "1" | true |
1923+
| Patterns.cs:87:44:87:54 | [no-match] ... and ... | Patterns.cs:87:39:87:54 | [false] ... is ... | false |
1924+
| Patterns.cs:87:44:87:54 | [no-match] ... and ... | Patterns.cs:87:64:87:70 | "not 1" | false |
1925+
| Patterns.cs:87:50:87:54 | [match] not ... | Patterns.cs:87:39:87:54 | [true] ... is ... | true |
1926+
| Patterns.cs:87:50:87:54 | [match] not ... | Patterns.cs:87:44:87:54 | [match] ... and ... | true |
1927+
| Patterns.cs:87:50:87:54 | [match] not ... | Patterns.cs:87:58:87:60 | "1" | true |
1928+
| Patterns.cs:87:54:87:54 | 2 | Patterns.cs:87:39:87:54 | [true] ... is ... | false |
1929+
| Patterns.cs:87:54:87:54 | 2 | Patterns.cs:87:44:87:54 | [match] ... and ... | false |
1930+
| Patterns.cs:87:54:87:54 | 2 | Patterns.cs:87:50:87:54 | [match] not ... | false |
1931+
| Patterns.cs:87:54:87:54 | 2 | Patterns.cs:87:50:87:54 | [no-match] not ... | true |
1932+
| Patterns.cs:87:54:87:54 | 2 | Patterns.cs:87:58:87:60 | "1" | false |
18931933
| PostDominance.cs:10:10:10:11 | enter M2 | PostDominance.cs:12:13:12:21 | [false] ... is ... | false |
18941934
| PostDominance.cs:10:10:10:11 | enter M2 | PostDominance.cs:12:13:12:21 | [true] ... is ... | true |
18951935
| PostDominance.cs:10:10:10:11 | enter M2 | PostDominance.cs:13:13:13:19 | return ...; | true |
@@ -2798,6 +2838,10 @@ conditionFlow
27982838
| Patterns.cs:24:30:24:35 | ... > ... | Patterns.cs:27:13:27:24 | case ...: | false |
27992839
| Patterns.cs:51:9:51:21 | [false] ... is ... | Patterns.cs:51:34:51:34 | access to parameter c | false |
28002840
| Patterns.cs:51:9:51:21 | [true] ... is ... | Patterns.cs:51:25:51:25 | access to parameter c | true |
2841+
| Patterns.cs:85:39:85:53 | [false] ... is ... | Patterns.cs:85:67:85:69 | "2" | false |
2842+
| Patterns.cs:85:39:85:53 | [true] ... is ... | Patterns.cs:85:57:85:63 | "not 2" | true |
2843+
| Patterns.cs:87:39:87:54 | [false] ... is ... | Patterns.cs:87:64:87:70 | "not 1" | false |
2844+
| Patterns.cs:87:39:87:54 | [true] ... is ... | Patterns.cs:87:58:87:60 | "1" | true |
28012845
| PostDominance.cs:12:13:12:21 | [false] ... is ... | PostDominance.cs:14:9:14:29 | ...; | false |
28022846
| PostDominance.cs:12:13:12:21 | [true] ... is ... | PostDominance.cs:13:13:13:19 | return ...; | true |
28032847
| PostDominance.cs:19:13:19:21 | [false] ... is ... | PostDominance.cs:21:9:21:29 | ...; | false |

0 commit comments

Comments
 (0)