@@ -6,6 +6,65 @@ import java
66private import SSA
77private import semmle.code.java.controlflow.internal.GuardsLogic
88
9+ /**
10+ * Holds if `v` is an input to `phi` that is not along a back edge, and the
11+ * only other input to `phi` is a `null` value.
12+ *
13+ * Note that the declared type of `phi` is `SsaVariable` instead of
14+ * `SsaPhiNode` in order for the reflexive case of `nonNullSsaFwdStep*(..)` to
15+ * have non-`SsaPhiNode` results.
16+ */
17+ private predicate nonNullSsaFwdStep ( SsaVariable v , SsaVariable phi ) {
18+ exists ( SsaExplicitUpdate vnull , SsaPhiNode phi0 | phi0 = phi |
19+ 2 = strictcount ( phi0 .getAPhiInput ( ) ) and
20+ vnull = phi0 .getAPhiInput ( ) and
21+ v = phi0 .getAPhiInput ( ) and
22+ not backEdge ( phi0 , v , _) and
23+ vnull != v and
24+ vnull .getDefiningExpr ( ) .( VariableAssign ) .getSource ( ) instanceof NullLiteral
25+ )
26+ }
27+
28+ private predicate nonNullDefStep ( Expr e1 , Expr e2 ) {
29+ e2 .( ParExpr ) .getExpr ( ) = e1
30+ or
31+ exists ( ConditionalExpr cond | cond = e2 |
32+ cond .getTrueExpr ( ) = e1 and cond .getFalseExpr ( ) instanceof NullLiteral
33+ or
34+ cond .getFalseExpr ( ) = e1 and cond .getTrueExpr ( ) instanceof NullLiteral
35+ )
36+ }
37+
38+ /**
39+ * Gets the definition of `v` provided that `v` is a non-null array with an
40+ * explicit `ArrayCreationExpr` definition and that the definition does not go
41+ * through a back edge.
42+ */
43+ ArrayCreationExpr getArrayDef ( SsaVariable v ) {
44+ exists ( Expr src |
45+ v .( SsaExplicitUpdate ) .getDefiningExpr ( ) .( VariableAssign ) .getSource ( ) = src and
46+ nonNullDefStep * ( result , src )
47+ )
48+ or
49+ exists ( SsaVariable mid |
50+ result = getArrayDef ( mid ) and
51+ nonNullSsaFwdStep ( mid , v )
52+ )
53+ }
54+
55+ /**
56+ * Holds if `arrlen` is a read of an array `length` field on an array that, if
57+ * it is non-null, is defined by `def` and that the definition can reach
58+ * `arrlen` without going through a back edge.
59+ */
60+ private predicate arrayLengthDef ( FieldRead arrlen , ArrayCreationExpr def ) {
61+ exists ( SsaVariable arr |
62+ arrlen .getField ( ) instanceof ArrayLengthField and
63+ arrlen .getQualifier ( ) = arr .getAUse ( ) and
64+ def = getArrayDef ( arr )
65+ )
66+ }
67+
968/** An expression that always has the same integer value. */
1069pragma [ nomagic]
1170private predicate constantIntegerExpr ( Expr e , int val ) {
@@ -17,11 +76,17 @@ private predicate constantIntegerExpr(Expr e, int val) {
1776 constantIntegerExpr ( src , val )
1877 )
1978 or
20- exists ( SsaExplicitUpdate v , FieldRead arrlen |
21- e = arrlen and
79+ exists ( ArrayCreationExpr a |
80+ arrayLengthDef ( e , a ) and
81+ a .getFirstDimensionSize ( ) = val
82+ )
83+ or
84+ exists ( Field a , FieldRead arrlen |
85+ a .isFinal ( ) and
86+ a .getInitializer ( ) .( ArrayCreationExpr ) .getFirstDimensionSize ( ) = val and
2287 arrlen .getField ( ) instanceof ArrayLengthField and
23- arrlen .getQualifier ( ) = v . getAUse ( ) and
24- v . getDefiningExpr ( ) . ( VariableAssign ) . getSource ( ) . ( ArrayCreationExpr ) . getFirstDimensionSize ( ) = val
88+ arrlen .getQualifier ( ) = a . getAnAccess ( ) and
89+ e = arrlen
2590 )
2691}
2792
@@ -122,6 +187,18 @@ class SsaReadPositionPhiInputEdge extends SsaReadPosition, TSsaReadPositionPhiIn
122187 override string toString ( ) { result = "edge" }
123188}
124189
190+ /**
191+ * Holds if `inp` is an input to `phi` along a back edge.
192+ */
193+ predicate backEdge ( SsaPhiNode phi , SsaVariable inp , SsaReadPositionPhiInputEdge edge ) {
194+ edge .phiInput ( phi , inp ) and
195+ // Conservatively assume that every edge is a back edge if we don't have dominance information.
196+ (
197+ phi .getBasicBlock ( ) .bbDominates ( edge .getOrigBlock ( ) ) or
198+ not hasDominanceInformation ( edge .getOrigBlock ( ) )
199+ )
200+ }
201+
125202/**
126203 * Holds if `guard` directly controls the position `controlled` with the
127204 * value `testIsTrue`.
@@ -201,11 +278,9 @@ predicate valueFlowStep(Expr e2, Expr e1, int delta) {
201278 or
202279 e2 .( PreDecExpr ) .getExpr ( ) = e1 and delta = - 1
203280 or
204- exists ( SsaExplicitUpdate v , FieldRead arrlen |
205- e2 = arrlen and
206- arrlen .getField ( ) instanceof ArrayLengthField and
207- arrlen .getQualifier ( ) = v .getAUse ( ) and
208- v .getDefiningExpr ( ) .( VariableAssign ) .getSource ( ) .( ArrayCreationExpr ) .getDimension ( 0 ) = e1 and
281+ exists ( ArrayCreationExpr a |
282+ arrayLengthDef ( e2 , a ) and
283+ a .getDimension ( 0 ) = e1 and
209284 delta = 0
210285 )
211286 or
0 commit comments