@@ -102,7 +102,67 @@ private predicate summarizedLocalStep(Node nodeFrom, Node nodeTo) {
102
102
}
103
103
104
104
/** Holds if there is a level step from `nodeFrom` to `nodeTo`. */
105
- predicate levelStep ( Node nodeFrom , Node nodeTo ) { summarizedLocalStep ( nodeFrom , nodeTo ) }
105
+ predicate levelStep ( Node nodeFrom , Node nodeTo ) {
106
+ summarizedLocalStep ( nodeFrom , nodeTo )
107
+ or
108
+ localFieldStep ( nodeFrom , nodeTo )
109
+ }
110
+
111
+ /**
112
+ * Gets a method of `mod`, with `instance` indicating if this is an instance method.
113
+ *
114
+ * Does not take inheritance or the various forms of inclusion into account.
115
+ */
116
+ pragma [ nomagic]
117
+ private MethodBase getAMethod ( ModuleBase mod , boolean instance ) {
118
+ not mod instanceof SingletonClass and
119
+ result = mod .getAMethod ( ) and
120
+ if result instanceof SingletonMethod then instance = false else instance = true
121
+ or
122
+ exists ( SingletonClass cls |
123
+ cls .getValue ( ) .( SelfVariableAccess ) .getCfgScope ( ) = mod and
124
+ result = cls .getAMethod ( ) .( Method ) and
125
+ instance = false
126
+ )
127
+ }
128
+
129
+ /**
130
+ * Gets a value flowing into `field` in `mod`, with `instance` indicating if it's
131
+ * a field on an instance of `mod` (as opposed to the module object itself).
132
+ */
133
+ pragma [ nomagic]
134
+ private Node fieldPredecessor ( ModuleBase mod , boolean instance , string field ) {
135
+ exists ( InstanceVariableWriteAccess access , AssignExpr assign |
136
+ access .getReceiver ( ) .getCfgScope ( ) = getAMethod ( mod , instance ) and
137
+ field = access .getVariable ( ) .getName ( ) and
138
+ assign .getLeftOperand ( ) = access and
139
+ result .asExpr ( ) .getExpr ( ) = assign .getRightOperand ( )
140
+ )
141
+ }
142
+
143
+ /**
144
+ * Gets a reference to `field` in `mod`, with `instance` indicating if it's
145
+ * a field on an instance of `mod` (as opposed to the module object itself).
146
+ */
147
+ pragma [ nomagic]
148
+ private Node fieldSuccessor ( ModuleBase mod , boolean instance , string field ) {
149
+ exists ( InstanceVariableReadAccess access |
150
+ access .getReceiver ( ) .getCfgScope ( ) = getAMethod ( mod , instance ) and
151
+ result .asExpr ( ) .getExpr ( ) = access and
152
+ field = access .getVariable ( ) .getName ( )
153
+ )
154
+ }
155
+
156
+ /**
157
+ * Holds if `pred -> succ` should be used a level step, from a field assignment to
158
+ * a read within the same class.
159
+ */
160
+ private predicate localFieldStep ( Node pred , Node succ ) {
161
+ exists ( ModuleBase mod , boolean instance , string field |
162
+ pred = fieldPredecessor ( mod , instance , field ) and
163
+ succ = fieldSuccessor ( mod , instance , field )
164
+ )
165
+ }
106
166
107
167
pragma [ noinline]
108
168
private predicate argumentPositionMatch (
0 commit comments