@@ -15,31 +15,30 @@ import DeadStore
1515/**
1616 * Holds if `assign` definitely assigns property `name` of `base`.
1717 */
18- predicate unambiguousPropWrite ( DataFlow:: SourceNode base , string name , Assignment assign ) {
19- exists ( DataFlow:: PropWrite lhs |
20- assign .getLhs ( ) .flow ( ) = lhs and
21- base .getAPropertyWrite ( name ) = lhs and
22- not exists ( DataFlow:: SourceNode otherBase |
23- otherBase != base and
24- lhs = otherBase .getAPropertyWrite ( name )
25- )
18+ predicate unambiguousPropWrite ( DataFlow:: SourceNode base , string name , DataFlow:: PropWrite write ) {
19+ write = base .getAPropertyWrite ( name ) and
20+ not exists ( DataFlow:: SourceNode otherBase |
21+ otherBase != base and
22+ write = otherBase .getAPropertyWrite ( name )
2623 )
2724}
2825
2926/**
3027 * Holds if `assign1` and `assign2` both assign property `name` of the same object, and `assign2` post-dominates `assign1`.
3128 */
32- predicate postDominatedPropWrite ( string name , Assignment assign1 , Assignment assign2 ) {
33- exists ( DataFlow:: SourceNode base , ReachableBasicBlock block1 , ReachableBasicBlock block2 |
34- block1 = assign1 .getBasicBlock ( ) and
35- block2 = assign2 .getBasicBlock ( ) and
29+ predicate postDominatedPropWrite ( string name , DataFlow:: PropWrite assign1 , DataFlow:: PropWrite assign2 ) {
30+ exists ( ControlFlowNode write1 , ControlFlowNode write2 , DataFlow:: SourceNode base , ReachableBasicBlock block1 , ReachableBasicBlock block2 |
31+ write1 = assign1 .getWriteNode ( ) and
32+ write2 = assign2 .getWriteNode ( ) and
33+ block1 = write1 .getBasicBlock ( ) and
34+ block2 = write2 .getBasicBlock ( ) and
3635 unambiguousPropWrite ( base , name , assign1 ) and
3736 unambiguousPropWrite ( base , name , assign2 ) and
3837 block2 .postDominates ( block1 ) and
3938 ( block1 = block2 implies
4039 exists ( int i1 , int i2 |
41- assign1 = block1 .getNode ( i1 ) and
42- assign2 = block2 .getNode ( i2 ) and
40+ write1 = block1 .getNode ( i1 ) and
41+ write2 = block2 .getNode ( i2 ) and
4342 i1 < i2
4443 )
4544 )
@@ -59,7 +58,7 @@ predicate maybeAccessesProperty(Expr e, string name) {
5958/**
6059 * Holds if `assign1` and `assign2` both assign property `name`, but `assign1` is dead because of `assign2`.
6160 */
62- predicate isDeadAssignment ( string name , Assignment assign1 , Assignment assign2 ) {
61+ predicate isDeadAssignment ( string name , DataFlow :: PropWrite assign1 , DataFlow :: PropWrite assign2 ) {
6362 postDominatedPropWrite ( name , assign1 , assign2 ) and
6463 noPropAccessBetween ( name , assign1 , assign2 ) and
6564 not isDOMProperty ( name )
@@ -70,10 +69,11 @@ predicate isDeadAssignment(string name, Assignment assign1, Assignment assign2)
7069 * `after` indicates if the access happens before or after the node for `assign`.
7170 */
7271bindingset [ name]
73- predicate maybeAccessesAssignedPropInBlock ( string name , Assignment assign , boolean after ) {
74- exists ( ReachableBasicBlock block , int i , int j , Expr e |
72+ predicate maybeAccessesAssignedPropInBlock ( string name , DataFlow:: PropWrite assign , boolean after ) {
73+ exists ( ControlFlowNode write , ReachableBasicBlock block , int i , int j , Expr e |
74+ write = assign .getWriteNode ( ) and
7575 block = assign .getBasicBlock ( ) and
76- assign = block .getNode ( i ) and
76+ write = block .getNode ( i ) and
7777 e = block .getNode ( j ) and
7878 maybeAccessesProperty ( e , name ) |
7979 after = true and i < j
@@ -86,15 +86,17 @@ predicate maybeAccessesAssignedPropInBlock(string name, Assignment assign, boole
8686 * Holds if `assign1` and `assign2` both assign property `name`, and the assigned property may be accessed between the two assignments.
8787 */
8888bindingset [ name]
89- predicate noPropAccessBetween ( string name , Assignment assign1 , Assignment assign2 ) {
90- exists ( ReachableBasicBlock block1 , ReachableBasicBlock block2 |
91- assign1 .getBasicBlock ( ) = block1 and
92- assign2 .getBasicBlock ( ) = block2 and
89+ predicate noPropAccessBetween ( string name , DataFlow:: PropWrite assign1 , DataFlow:: PropWrite assign2 ) {
90+ exists ( ControlFlowNode write1 , ControlFlowNode write2 , ReachableBasicBlock block1 , ReachableBasicBlock block2 |
91+ write1 = assign1 .getWriteNode ( ) and
92+ write2 = assign2 .getWriteNode ( ) and
93+ write1 .getBasicBlock ( ) = block1 and
94+ write2 .getBasicBlock ( ) = block2 and
9395 if block1 = block2 then
9496 // same block: check for access between
9597 not exists ( int i1 , Expr mid , int i2 |
96- assign1 = block1 .getNode ( i1 ) and
97- assign2 = block2 .getNode ( i2 ) and
98+ assign1 . getWriteNode ( ) = block1 .getNode ( i1 ) and
99+ assign2 . getWriteNode ( ) = block2 .getNode ( i2 ) and
98100 mid = block1 .getNode ( [ i1 + 1 ..i2 - 1 ] ) and
99101 maybeAccessesProperty ( mid , name )
100102 )
@@ -115,23 +117,26 @@ predicate noPropAccessBetween(string name, Assignment assign1, Assignment assign
115117 )
116118}
117119
118- from string name , Assignment assign1 , Assignment assign2
120+ from string name , DataFlow :: PropWrite assign1 , DataFlow :: PropWrite assign2
119121where isDeadAssignment ( name , assign1 , assign2 ) and
120122 // whitelist
121123 not (
122124 // Google Closure Compiler pattern: `o.p = o['p'] = v`
123125 exists ( PropAccess p1 , PropAccess p2 |
124- p1 = assign1 .getLhs ( ) and
125- p2 = assign2 .getLhs ( ) |
126+ p1 = assign1 .getAstNode ( ) and
127+ p2 = assign2 .getAstNode ( ) |
126128 p1 instanceof DotExpr and p2 instanceof IndexExpr
127129 or
128130 p2 instanceof DotExpr and p1 instanceof IndexExpr
129131 )
130132 or
131133 // don't flag overwrites for default values
132- isDefaultInit ( assign1 .getRhs ( ) .getUnderlyingValue ( ) )
134+ isDefaultInit ( assign1 .getRhs ( ) .asExpr ( ) . getUnderlyingValue ( ) )
133135 or
134136 // don't flag assignments in externs
135- assign1 .inExternsFile ( )
137+ assign1 .getAstNode ( ) .inExternsFile ( )
138+ or
139+ // exclude result from js/overwritten-property
140+ assign2 .getBase ( ) instanceof DataFlow:: ObjectLiteralNode
136141 )
137- select assign1 , "This write to property '" + name + "' is useless, since $@ always overrides it." , assign2 , "another property write"
142+ select assign1 . getWriteNode ( ) , "This write to property '" + name + "' is useless, since $@ always overrides it." , assign2 . getWriteNode ( ) , "another property write"
0 commit comments