@@ -144,8 +144,23 @@ OutNode getAnOutNode(DataFlowCall call, ReturnKind kind) {
144144 */
145145predicate jumpStep ( Node n1 , Node n2 ) { none ( ) }
146146
147+ /**
148+ * Gets a field corresponding to the bit range `[startBit..endBit)` of class `c`, if any.
149+ */
150+ private Field getAField ( Class c , int startBit , int endBit ) {
151+ result .getDeclaringType ( ) = c and
152+ startBit = 8 * result .getByteOffset ( ) and
153+ endBit = 8 * result .getType ( ) .getSize ( ) + startBit
154+ or
155+ exists ( Field f , Class cInner |
156+ f = c .getAField ( ) and
157+ cInner = f .getUnderlyingType ( ) and
158+ result = getAField ( cInner , startBit - 8 * f .getByteOffset ( ) , endBit - 8 * f .getByteOffset ( ) )
159+ )
160+ }
161+
147162private newtype TContent =
148- TFieldContent ( Field f ) or
163+ TFieldContent ( Class c , int startBit , int endBit ) { exists ( getAField ( c , startBit , endBit ) ) } or
149164 TCollectionContent ( ) or
150165 TArrayContent ( )
151166
@@ -163,17 +178,18 @@ class Content extends TContent {
163178}
164179
165180private class FieldContent extends Content , TFieldContent {
166- Field f ;
181+ Class c ;
182+ int startBit ;
183+ int endBit ;
167184
168- FieldContent ( ) { this = TFieldContent ( f ) }
185+ FieldContent ( ) { this = TFieldContent ( c , startBit , endBit ) }
169186
170- Field getField ( ) { result = f }
187+ // Ensure that there's just 1 result for `toString`.
188+ override string toString ( ) { result = min ( Field f | f = getAField ( ) | f .toString ( ) ) }
171189
172- override string toString ( ) { result = f . toString ( ) }
190+ predicate hasOffset ( Class cl , int start , int end ) { cl = c and start = startBit and end = endBit }
173191
174- override predicate hasLocationInfo ( string path , int sl , int sc , int el , int ec ) {
175- f .getLocation ( ) .hasLocationInfo ( path , sl , sc , el , ec )
176- }
192+ Field getAField ( ) { result = getAField ( c , startBit , endBit ) }
177193}
178194
179195private class CollectionContent extends Content , TCollectionContent {
@@ -185,20 +201,38 @@ private class ArrayContent extends Content, TArrayContent {
185201}
186202
187203private predicate storeStepNoChi ( Node node1 , Content f , PostUpdateNode node2 ) {
188- exists ( FieldAddressInstruction fa , StoreInstruction store |
204+ exists ( StoreInstruction store , Class c |
189205 store = node2 .asInstruction ( ) and
190- store .getDestinationAddress ( ) = fa and
191206 store .getSourceValue ( ) = node1 .asInstruction ( ) and
192- f .( FieldContent ) .getField ( ) = fa .getField ( )
207+ getWrittenField ( store , f .( FieldContent ) .getAField ( ) , c ) and
208+ f .( FieldContent ) .hasOffset ( c , _, _)
209+ )
210+ }
211+
212+ pragma [ noinline]
213+ private predicate getWrittenField ( StoreInstruction store , Field f , Class c ) {
214+ exists ( FieldAddressInstruction fa |
215+ fa = store .getDestinationAddress ( ) and
216+ f = fa .getField ( ) and
217+ c = f .getDeclaringType ( )
193218 )
194219}
195220
196221private predicate storeStepChi ( Node node1 , Content f , PostUpdateNode node2 ) {
197- exists ( FieldAddressInstruction fa , StoreInstruction store |
222+ exists ( StoreInstruction store , ChiInstruction chi |
198223 node1 .asInstruction ( ) = store and
199- store .getDestinationAddress ( ) = fa and
200- node2 .asInstruction ( ) .( ChiInstruction ) .getPartial ( ) = store and
201- f .( FieldContent ) .getField ( ) = fa .getField ( )
224+ node2 .asInstruction ( ) = chi and
225+ chi .getPartial ( ) = store and
226+ exists ( Class c |
227+ c = chi .getResultType ( ) and
228+ exists ( int startBit , int endBit |
229+ chi .getUpdatedInterval ( startBit , endBit ) and
230+ f .( FieldContent ) .hasOffset ( c , startBit , endBit )
231+ )
232+ or
233+ getWrittenField ( store , f .( FieldContent ) .getAField ( ) , c ) and
234+ f .( FieldContent ) .hasOffset ( c , _, _)
235+ )
202236 )
203237}
204238
@@ -212,17 +246,37 @@ predicate storeStep(Node node1, Content f, PostUpdateNode node2) {
212246 storeStepChi ( node1 , f , node2 )
213247}
214248
249+ bindingset [ result , i]
250+ private int unbindInt ( int i ) { i <= result and i >= result }
251+
252+ pragma [ noinline]
253+ private predicate getLoadedField ( LoadInstruction load , Field f , Class c ) {
254+ exists ( FieldAddressInstruction fa |
255+ fa = load .getSourceAddress ( ) and
256+ f = fa .getField ( ) and
257+ c = f .getDeclaringType ( )
258+ )
259+ }
260+
215261/**
216262 * Holds if data can flow from `node1` to `node2` via a read of `f`.
217263 * Thus, `node1` references an object with a field `f` whose value ends up in
218264 * `node2`.
219265 */
220266predicate readStep ( Node node1 , Content f , Node node2 ) {
221- exists ( FieldAddressInstruction fa , LoadInstruction load |
222- load . getSourceAddress ( ) = fa and
267+ exists ( LoadInstruction load |
268+ node2 . asInstruction ( ) = load and
223269 node1 .asInstruction ( ) = load .getSourceValueOperand ( ) .getAnyDef ( ) and
224- fa .getField ( ) = f .( FieldContent ) .getField ( ) and
225- load = node2 .asInstruction ( )
270+ exists ( Class c |
271+ c = load .getSourceValueOperand ( ) .getAnyDef ( ) .getResultType ( ) and
272+ exists ( int startBit , int endBit |
273+ load .getSourceValueOperand ( ) .getUsedInterval ( unbindInt ( startBit ) , unbindInt ( endBit ) ) and
274+ f .( FieldContent ) .hasOffset ( c , startBit , endBit )
275+ )
276+ or
277+ getLoadedField ( load , f .( FieldContent ) .getAField ( ) , c ) and
278+ f .( FieldContent ) .hasOffset ( c , _, _)
279+ )
226280 )
227281}
228282
0 commit comments