@@ -112,11 +112,9 @@ class ReturnNode extends InstructionNode {
112
112
Instruction primary ;
113
113
114
114
ReturnNode ( ) {
115
- exists ( ReturnValueInstruction ret | instr = ret . getReturnValue ( ) and primary = ret )
115
+ exists ( ReturnValueInstruction ret | instr = ret and primary = ret )
116
116
or
117
- exists ( ReturnIndirectionInstruction rii |
118
- instr = rii .getSideEffectOperand ( ) .getAnyDef ( ) and primary = rii
119
- )
117
+ exists ( ReturnIndirectionInstruction rii | instr = rii and primary = rii )
120
118
}
121
119
122
120
/** Gets the kind of this returned value. */
@@ -190,108 +188,16 @@ OutNode getAnOutNode(DataFlowCall call, ReturnKind kind) {
190
188
*/
191
189
predicate jumpStep ( Node n1 , Node n2 ) { none ( ) }
192
190
193
- private predicate fieldStoreStepNoChi ( Node node1 , FieldContent f , PostUpdateNode node2 ) {
194
- exists ( StoreInstruction store , Class c |
195
- store = node2 .asInstruction ( ) and
196
- store .getSourceValueOperand ( ) = node1 .asOperand ( ) and
197
- getWrittenField ( store , f .getAField ( ) , c ) and
198
- f .hasOffset ( c , _, _)
199
- )
200
- }
201
-
202
- private FieldAddressInstruction getFieldInstruction ( Instruction instr ) {
203
- result = instr or
204
- result = instr .( CopyValueInstruction ) .getUnary ( )
205
- }
206
-
207
- pragma [ noinline]
208
- private predicate getWrittenField ( Instruction instr , Field f , Class c ) {
209
- exists ( FieldAddressInstruction fa |
210
- fa =
211
- getFieldInstruction ( [
212
- instr .( StoreInstruction ) .getDestinationAddress ( ) ,
213
- instr .( WriteSideEffectInstruction ) .getDestinationAddress ( )
214
- ] ) and
215
- f = fa .getField ( ) and
216
- c = f .getDeclaringType ( )
217
- )
218
- }
219
-
220
- private predicate fieldStoreStepChi ( Node node1 , FieldContent f , PostUpdateNode node2 ) {
221
- exists ( ChiPartialOperand operand , ChiInstruction chi |
222
- chi .getPartialOperand ( ) = operand and
223
- node1 .asOperand ( ) = operand and
224
- node2 .asInstruction ( ) = chi and
225
- exists ( Class c |
226
- c = chi .getResultType ( ) and
227
- exists ( int startBit , int endBit |
228
- chi .getUpdatedInterval ( startBit , endBit ) and
229
- f .hasOffset ( c , startBit , endBit )
230
- )
231
- or
232
- getWrittenField ( operand .getDef ( ) , f .getAField ( ) , c ) and
233
- f .hasOffset ( c , _, _)
234
- )
235
- )
236
- }
237
-
238
- private predicate arrayStoreStepChi ( Node node1 , ArrayContent a , PostUpdateNode node2 ) {
239
- exists ( a ) and
240
- exists ( ChiPartialOperand operand , ChiInstruction chi , StoreInstruction store |
241
- chi .getPartialOperand ( ) = operand and
242
- store = operand .getDef ( ) and
243
- node1 .asOperand ( ) = operand and
244
- // This `ChiInstruction` will always have a non-conflated result because both `ArrayStoreNode`
245
- // and `PointerStoreNode` require it in their characteristic predicates.
246
- node2 .asInstruction ( ) = chi and
247
- (
248
- // `x[i] = taint()`
249
- // This matches the characteristic predicate in `ArrayStoreNode`.
250
- store .getDestinationAddress ( ) instanceof PointerAddInstruction
251
- or
252
- // `*p = taint()`
253
- // This matches the characteristic predicate in `PointerStoreNode`.
254
- store .getDestinationAddress ( ) .( CopyValueInstruction ) .getUnary ( ) instanceof LoadInstruction
255
- )
256
- )
257
- }
258
-
259
191
/**
260
192
* Holds if data can flow from `node1` to `node2` via an assignment to `f`.
261
193
* Thus, `node2` references an object with a field `f` that contains the
262
194
* value of `node1`.
263
195
*/
264
- predicate storeStep ( Node node1 , Content f , PostUpdateNode node2 ) {
265
- fieldStoreStepNoChi ( node1 , f , node2 ) or
266
- fieldStoreStepChi ( node1 , f , node2 ) or
267
- arrayStoreStepChi ( node1 , f , node2 ) or
268
- fieldStoreStepAfterArraySuppression ( node1 , f , node2 )
269
- }
270
-
271
- // This predicate pushes the correct `FieldContent` onto the access path when the
272
- // `suppressArrayRead` predicate has popped off an `ArrayContent`.
273
- private predicate fieldStoreStepAfterArraySuppression (
274
- Node node1 , FieldContent f , PostUpdateNode node2
275
- ) {
276
- exists ( WriteSideEffectInstruction write , ChiInstruction chi , Class c |
277
- not chi .isResultConflated ( ) and
278
- node1 .asInstruction ( ) = chi and
279
- node2 .asInstruction ( ) = chi and
280
- chi .getPartial ( ) = write and
281
- getWrittenField ( write , f .getAField ( ) , c ) and
282
- f .hasOffset ( c , _, _)
283
- )
284
- }
285
-
286
- bindingset [ result , i]
287
- private int unbindInt ( int i ) { i <= result and i >= result }
288
-
289
- pragma [ noinline]
290
- private predicate getLoadedField ( LoadInstruction load , Field f , Class c ) {
291
- exists ( FieldAddressInstruction fa |
292
- fa = load .getSourceAddress ( ) and
293
- f = fa .getField ( ) and
294
- c = f .getDeclaringType ( )
196
+ predicate storeStep ( StoreNodeInstr node1 , FieldContent f , StoreNodeInstr node2 ) {
197
+ exists ( FieldAddressInstruction fai |
198
+ node1 .getInstruction ( ) = fai and
199
+ node2 .getInstruction ( ) = fai .getObjectAddress ( ) and
200
+ f .getField ( ) = fai .getField ( )
295
201
)
296
202
}
297
203
@@ -300,122 +206,14 @@ private predicate getLoadedField(LoadInstruction load, Field f, Class c) {
300
206
* Thus, `node1` references an object with a field `f` whose value ends up in
301
207
* `node2`.
302
208
*/
303
- private predicate fieldReadStep ( Node node1 , FieldContent f , Node node2 ) {
304
- exists ( LoadOperand operand |
305
- node2 .asOperand ( ) = operand and
306
- node1 .asInstruction ( ) = operand .getAnyDef ( ) and
307
- exists ( Class c |
308
- c = operand .getAnyDef ( ) .getResultType ( ) and
309
- exists ( int startBit , int endBit |
310
- operand .getUsedInterval ( unbindInt ( startBit ) , unbindInt ( endBit ) ) and
311
- f .hasOffset ( c , startBit , endBit )
312
- )
313
- or
314
- getLoadedField ( operand .getUse ( ) , f .getAField ( ) , c ) and
315
- f .hasOffset ( c , _, _)
316
- )
209
+ predicate readStep ( ReadNode node1 , FieldContent f , ReadNode node2 ) {
210
+ exists ( FieldAddressInstruction fai |
211
+ node1 .getInstruction ( ) = fai .getObjectAddress ( ) and
212
+ node2 .getInstruction ( ) = fai and
213
+ f .getField ( ) = fai .getField ( )
317
214
)
318
215
}
319
216
320
- /**
321
- * When a store step happens in a function that looks like an array write such as:
322
- * ```cpp
323
- * void f(int* pa) {
324
- * pa = source();
325
- * }
326
- * ```
327
- * it can be a write to an array, but it can also happen that `f` is called as `f(&a.x)`. If that is
328
- * the case, the `ArrayContent` that was written by the call to `f` should be popped off the access
329
- * path, and a `FieldContent` containing `x` should be pushed instead.
330
- * So this case pops `ArrayContent` off the access path, and the `fieldStoreStepAfterArraySuppression`
331
- * predicate in `storeStep` ensures that we push the right `FieldContent` onto the access path.
332
- */
333
- predicate suppressArrayRead ( Node node1 , ArrayContent a , Node node2 ) {
334
- exists ( a ) and
335
- exists ( WriteSideEffectInstruction write , ChiInstruction chi |
336
- node1 .asInstruction ( ) = write and
337
- node2 .asInstruction ( ) = chi and
338
- chi .getPartial ( ) = write and
339
- getWrittenField ( write , _, _)
340
- )
341
- }
342
-
343
- private class ArrayToPointerConvertInstruction extends ConvertInstruction {
344
- ArrayToPointerConvertInstruction ( ) {
345
- this .getUnary ( ) .getResultType ( ) instanceof ArrayType and
346
- this .getResultType ( ) instanceof PointerType
347
- }
348
- }
349
-
350
- private Instruction skipOneCopyValueInstructionRec ( CopyValueInstruction copy ) {
351
- copy .getUnary ( ) = result and not result instanceof CopyValueInstruction
352
- or
353
- result = skipOneCopyValueInstructionRec ( copy .getUnary ( ) )
354
- }
355
-
356
- private Instruction skipCopyValueInstructions ( Operand op ) {
357
- not result instanceof CopyValueInstruction and result = op .getDef ( )
358
- or
359
- result = skipOneCopyValueInstructionRec ( op .getDef ( ) )
360
- }
361
-
362
- private predicate arrayReadStep ( Node node1 , ArrayContent a , Node node2 ) {
363
- exists ( a ) and
364
- // Explicit dereferences such as `*p` or `p[i]` where `p` is a pointer or array.
365
- exists ( LoadOperand operand , Instruction address |
366
- operand .isDefinitionInexact ( ) and
367
- node1 .asInstruction ( ) = operand .getAnyDef ( ) and
368
- operand = node2 .asOperand ( ) and
369
- address = skipCopyValueInstructions ( operand .getAddressOperand ( ) ) and
370
- (
371
- address instanceof LoadInstruction or
372
- address instanceof ArrayToPointerConvertInstruction or
373
- address instanceof PointerOffsetInstruction
374
- )
375
- )
376
- }
377
-
378
- /**
379
- * In cases such as:
380
- * ```cpp
381
- * void f(int* pa) {
382
- * *pa = source();
383
- * }
384
- * ...
385
- * int x;
386
- * f(&x);
387
- * use(x);
388
- * ```
389
- * the load on `x` in `use(x)` will exactly overlap with its definition (in this case the definition
390
- * is a `WriteSideEffect`). This predicate pops the `ArrayContent` (pushed by the store in `f`)
391
- * from the access path.
392
- */
393
- private predicate exactReadStep ( Node node1 , ArrayContent a , Node node2 ) {
394
- exists ( a ) and
395
- exists ( WriteSideEffectInstruction write , ChiInstruction chi |
396
- not chi .isResultConflated ( ) and
397
- chi .getPartial ( ) = write and
398
- node1 .asInstruction ( ) = write and
399
- node2 .asInstruction ( ) = chi and
400
- // To distinquish this case from the `arrayReadStep` case we require that the entire variable was
401
- // overwritten by the `WriteSideEffectInstruction` (i.e., there is a load that reads the
402
- // entire variable).
403
- exists ( LoadInstruction load | load .getSourceValue ( ) = chi )
404
- )
405
- }
406
-
407
- /**
408
- * Holds if data can flow from `node1` to `node2` via a read of `f`.
409
- * Thus, `node1` references an object with a field `f` whose value ends up in
410
- * `node2`.
411
- */
412
- predicate readStep ( Node node1 , Content f , Node node2 ) {
413
- fieldReadStep ( node1 , f , node2 ) or
414
- arrayReadStep ( node1 , f , node2 ) or
415
- exactReadStep ( node1 , f , node2 ) or
416
- suppressArrayRead ( node1 , f , node2 )
417
- }
418
-
419
217
/**
420
218
* Holds if values stored inside content `c` are cleared at node `n`.
421
219
*/
@@ -447,7 +245,7 @@ private predicate suppressUnusedNode(Node n) { any() }
447
245
// Java QL library compatibility wrappers
448
246
//////////////////////////////////////////////////////////////////////////////
449
247
/** A node that performs a type cast. */
450
- class CastNode extends InstructionNode {
248
+ class CastNode extends Node {
451
249
CastNode ( ) { none ( ) } // stub implementation
452
250
}
453
251
0 commit comments