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

Skip to content

Commit 3d980b1

Browse files
committed
Switch to using VariableAssign for instanceof and switch dataflow
1 parent 176adf4 commit 3d980b1

5 files changed

Lines changed: 58 additions & 56 deletions

File tree

java/ql/lib/semmle/code/java/Expr.qll

Lines changed: 51 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1682,15 +1682,51 @@ class LocalVariableDeclExpr extends Expr, @localvariabledeclexpr {
16821682
/** Holds if this is a declaration stemming from a pattern instanceof expression. */
16831683
predicate hasAssociatedInstanceOfExpr() { exists(this.getAssociatedInstanceOfExpr()) }
16841684

1685-
/** Gets the initializer expression of this local variable declaration expression, if any. */
1685+
/**
1686+
* Gets the initializer expression of this local variable declaration expression, if any.
1687+
*
1688+
* Note this applies specifically to a syntactic initialization like `T varname = init`;
1689+
* to include also `e instanceof T varname` and `switch(e) ... case T varname`, which both
1690+
* have the effect of initializing `varname` to a known local expression without using
1691+
* that syntax, use `getInitOrPatternSource`.
1692+
*/
16861693
Expr getInit() { result.isNthChildOf(this, 0) }
16871694

1695+
/**
1696+
* Gets the local expression that initializes this variable declaration, if any.
1697+
*
1698+
* Note this includes explicit `T varname = init;`, as well as `e instanceof T varname`
1699+
* and `switch(e) ... case T varname`. To get only explicit initializers, use `getInit`.
1700+
*
1701+
* Note that record pattern variables like `e instance of T Record(T varname)` do not have
1702+
* either an explicit initializer or a pattern source.
1703+
*/
1704+
Expr getInitOrPatternSource() {
1705+
result = this.getInit()
1706+
or
1707+
exists(SwitchStmt switch |
1708+
result = switch.getExpr() and
1709+
this = switch.getAPatternCase().getPattern().asBindingPattern()
1710+
)
1711+
or
1712+
exists(SwitchExpr switch |
1713+
result = switch.getExpr() and
1714+
this = switch.getAPatternCase().getPattern().asBindingPattern()
1715+
)
1716+
or
1717+
exists(InstanceOfExpr ioe |
1718+
result = ioe.getExpr() and
1719+
this = ioe.getPattern().asBindingPattern()
1720+
)
1721+
}
1722+
16881723
/** Holds if this variable declaration implicitly initializes the variable. */
16891724
predicate hasImplicitInit() {
1690-
exists(CatchClause cc | cc.getVariable() = this) or
1691-
exists(EnhancedForStmt efs | efs.getVariable() = this) or
1692-
this.hasAssociatedSwitch() or
1693-
this.hasAssociatedInstanceOfExpr()
1725+
exists(CatchClause cc | cc.getVariable() = this)
1726+
or
1727+
exists(EnhancedForStmt efs | efs.getVariable() = this)
1728+
or
1729+
this.getParent() instanceof RecordPatternExpr
16941730
}
16951731

16961732
/** Gets a printable representation of this expression. */
@@ -1699,6 +1735,13 @@ class LocalVariableDeclExpr extends Expr, @localvariabledeclexpr {
16991735
override string getAPrimaryQlClass() { result = "LocalVariableDeclExpr" }
17001736
}
17011737

1738+
/** A local variable declaration that occurs within a record pattern. */
1739+
class RecordBindingVariableExpr extends LocalVariableDeclExpr {
1740+
RecordBindingVariableExpr() {
1741+
this.getParent() instanceof RecordPatternExpr
1742+
}
1743+
}
1744+
17021745
/** An update of a variable or an initialization of the variable. */
17031746
class VariableUpdate extends Expr {
17041747
VariableUpdate() {
@@ -1727,12 +1770,12 @@ class VariableAssign extends VariableUpdate {
17271770
/**
17281771
* Gets the source (right-hand side) of this assignment, if any.
17291772
*
1730-
* An initialization in a `CatchClause` or `EnhancedForStmt` is implicit and
1731-
* does not have a source.
1773+
* An initialization in a `CatchClause`, `EnhancedForStmt` or `RecordPatternExpr`
1774+
* is implicit and does not have a source.
17321775
*/
17331776
Expr getSource() {
17341777
result = this.(AssignExpr).getSource() or
1735-
result = this.(LocalVariableDeclExpr).getInit()
1778+
result = this.(LocalVariableDeclExpr).getInitOrPatternSource()
17361779
}
17371780
}
17381781

java/ql/lib/semmle/code/java/dataflow/TypeFlow.qll

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -116,22 +116,6 @@ private predicate step(TypeFlowNode n1, TypeFlowNode n2) {
116116
n2.asSsa().(BaseSsaUpdate).getDefiningExpr().(VariableAssign).getSource() = n1.asExpr()
117117
or
118118
n2.asSsa().(BaseSsaImplicitInit).captures(n1.asSsa())
119-
or
120-
exists(PatternCase pc, LocalVariableDeclExpr patternVar |
121-
patternVar = pc.getPattern().asBindingPattern() and
122-
n2.asSsa().(BaseSsaUpdate).getDefiningExpr() = patternVar and
123-
(
124-
pc.getSwitch().getExpr() = n1.asExpr()
125-
or
126-
pc.getSwitchExpr().getExpr() = n1.asExpr()
127-
)
128-
)
129-
or
130-
exists(InstanceOfExpr ioe, LocalVariableDeclExpr patternVar |
131-
patternVar = ioe.getPattern().asBindingPattern() and
132-
n2.asSsa().(BaseSsaUpdate).getDefiningExpr() = patternVar and
133-
ioe.getExpr() = n1.asExpr()
134-
)
135119
}
136120

137121
/**

java/ql/lib/semmle/code/java/dataflow/internal/DataFlowUtil.qll

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -191,11 +191,14 @@ predicate simpleAstFlowStep(Expr e1, Expr e2) {
191191
or
192192
e2.(WhenExpr).getBranch(_).getAResult() = e1
193193
or
194-
exists(SwitchExpr se | e1 = se.getExpr() and e2 = se.getACase().(PatternCase).getPattern())
194+
// In the following three cases only record patterns need this flow edge, leading from the bound instanceof
195+
// or switch tested expression to a record pattern that will read its fields. Simple binding patterns are
196+
// handled via VariableAssign.getSource instead.
197+
exists(SwitchExpr se | e1 = se.getExpr() and e2 = se.getACase().(PatternCase).getPattern().asRecordPattern())
195198
or
196-
exists(SwitchStmt ss | e1 = ss.getExpr() and e2 = ss.getACase().(PatternCase).getPattern())
199+
exists(SwitchStmt ss | e1 = ss.getExpr() and e2 = ss.getACase().(PatternCase).getPattern().asRecordPattern())
197200
or
198-
exists(InstanceOfExpr ioe | e1 = ioe.getExpr() and e2 = ioe.getPattern())
201+
exists(InstanceOfExpr ioe | e1 = ioe.getExpr() and e2 = ioe.getPattern().asRecordPattern())
199202
}
200203

201204
private predicate simpleLocalFlowStep0(Node node1, Node node2) {
@@ -204,7 +207,7 @@ private predicate simpleLocalFlowStep0(Node node1, Node node2) {
204207
exists(SsaExplicitUpdate upd |
205208
upd.getDefiningExpr().(VariableAssign).getSource() = node1.asExpr() or
206209
upd.getDefiningExpr().(AssignOp) = node1.asExpr() or
207-
upd.getDefiningExpr().(PatternExpr).asBindingPattern() = node1.asExpr()
210+
upd.getDefiningExpr().(RecordBindingVariableExpr) = node1.asExpr()
208211
|
209212
node2.asExpr() = upd.getAFirstUse() and
210213
not capturedVariableRead(node2)

java/ql/lib/semmle/code/java/dispatch/DispatchFlow.qll

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -167,20 +167,6 @@ private module TypeTrackingSteps {
167167
def.(BaseSsaUpdate).getDefiningExpr().(VariableAssign).getSource() = n1.asExpr()
168168
or
169169
def.(BaseSsaImplicitInit).isParameterDefinition(n1.asParameter())
170-
or
171-
exists(PatternCase pc |
172-
pc.getPattern().asBindingPattern() = def.(BaseSsaUpdate).getDefiningExpr() and
173-
(
174-
pc.getSwitch().getExpr() = n1.asExpr()
175-
or
176-
pc.getSwitchExpr().getExpr() = n1.asExpr()
177-
)
178-
)
179-
or
180-
exists(InstanceOfExpr ioe |
181-
ioe.getPattern().asBindingPattern() = def.(BaseSsaUpdate).getDefiningExpr() and
182-
ioe.getExpr() = n1.asExpr()
183-
)
184170
|
185171
v.getAnUltimateDefinition() = def and
186172
v.getAUse() = n2.asExpr()

java/ql/lib/semmle/code/java/dispatch/ObjFlow.qll

Lines changed: 0 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -80,20 +80,6 @@ private predicate step(Node n1, Node n2) {
8080
for.getVariable() = def.(BaseSsaUpdate).getDefiningExpr() and
8181
for.getExpr() = n1.asExpr()
8282
)
83-
or
84-
exists(PatternCase pc |
85-
pc.getPattern().asBindingPattern() = def.(BaseSsaUpdate).getDefiningExpr() and
86-
(
87-
pc.getSwitch().getExpr() = n1.asExpr()
88-
or
89-
pc.getSwitchExpr().getExpr() = n1.asExpr()
90-
)
91-
)
92-
or
93-
exists(InstanceOfExpr ioe |
94-
ioe.getPattern().asBindingPattern() = def.(BaseSsaUpdate).getDefiningExpr() and
95-
ioe.getExpr() = n1.asExpr()
96-
)
9783
|
9884
v.getAnUltimateDefinition() = def and
9985
v.getAUse() = n2.asExpr()

0 commit comments

Comments
 (0)