@@ -239,6 +239,8 @@ abstract class PostUpdateNode extends InstructionNode {
239
239
}
240
240
241
241
/**
242
+ * INTERNAL: do not use.
243
+ *
242
244
* The base class for nodes that perform "partial definitions".
243
245
*
244
246
* In contrast to a normal "definition", which provides a new value for
@@ -251,7 +253,7 @@ abstract class PostUpdateNode extends InstructionNode {
251
253
* setY(&x); // a partial definition of the object `x`.
252
254
* ```
253
255
*/
254
- abstract private class PartialDefinitionNode extends PostUpdateNode , TInstructionNode { }
256
+ abstract class PartialDefinitionNode extends PostUpdateNode , TInstructionNode { }
255
257
256
258
private class ExplicitFieldStoreQualifierNode extends PartialDefinitionNode {
257
259
override ChiInstruction instr ;
@@ -270,6 +272,17 @@ private class ExplicitFieldStoreQualifierNode extends PartialDefinitionNode {
270
272
override Node getPreUpdateNode ( ) { result .asInstruction ( ) = instr .getTotal ( ) }
271
273
}
272
274
275
+ private class FieldStoreWriteSideEffectNode extends PartialDefinitionNode {
276
+ override ChiInstruction instr ;
277
+
278
+ FieldStoreWriteSideEffectNode ( ) {
279
+ not instr .isResultConflated ( ) and
280
+ exists ( WriteSideEffectInstruction sideEffect | instr .getPartial ( ) = sideEffect )
281
+ }
282
+
283
+ override Node getPreUpdateNode ( ) { result .asInstruction ( ) = instr .getTotal ( ) }
284
+ }
285
+
273
286
/**
274
287
* Not every store instruction generates a chi instruction that we can attach a PostUpdateNode to.
275
288
* For instance, an update to a field of a struct containing only one field. For these cases we
@@ -421,6 +434,32 @@ predicate localFlowStep(Node nodeFrom, Node nodeTo) { simpleLocalFlowStep(nodeFr
421
434
*/
422
435
predicate simpleLocalFlowStep ( Node nodeFrom , Node nodeTo ) {
423
436
simpleInstructionLocalFlowStep ( nodeFrom .asInstruction ( ) , nodeTo .asInstruction ( ) )
437
+ or
438
+ // The next two rules allow flow from partial definitions in setters to succeeding loads in the caller.
439
+ // First, we add flow from write side-effects to non-conflated chi instructions through their
440
+ // partial operands. Consider the following example:
441
+ // ```
442
+ // void setX(Point* p, int new_x) {
443
+ // p->x = new_x;
444
+ // }
445
+ // ...
446
+ // setX(&p, taint());
447
+ // ```
448
+ // Here, a `WriteSideEffectInstruction` will provide a new definition for `p->x` after the call to
449
+ // `setX`, which will be melded into `p` through a chi instruction.
450
+ nodeTo instanceof FieldStoreWriteSideEffectNode and
451
+ exists ( ChiInstruction chi | chi = nodeTo .asInstruction ( ) |
452
+ chi .getPartialOperand ( ) .getDef ( ) = nodeFrom .asInstruction ( ) .( WriteSideEffectInstruction ) and
453
+ not chi .isResultConflated ( )
454
+ )
455
+ or
456
+ // Next, we add flow from non-conflated chi instructions to loads (even when they are not precise).
457
+ // This ensures that loads of `p->x` gets data flow from the `WriteSideEffectInstruction` above.
458
+ nodeFrom instanceof FieldStoreWriteSideEffectNode and
459
+ exists ( ChiInstruction chi | chi = nodeFrom .asInstruction ( ) |
460
+ not chi .isResultConflated ( ) and
461
+ nodeTo .asInstruction ( ) .( LoadInstruction ) .getSourceValueOperand ( ) .getAnyDef ( ) = chi
462
+ )
424
463
}
425
464
426
465
pragma [ noinline]
@@ -458,28 +497,6 @@ private predicate simpleInstructionLocalFlowStep(Instruction iFrom, Instruction
458
497
// for now.
459
498
iTo .getAnOperand ( ) .( ChiTotalOperand ) .getDef ( ) = iFrom
460
499
or
461
- // The next two rules allow flow from partial definitions in setters to succeeding loads in the caller.
462
- // First, we add flow from write side-effects to non-conflated chi instructions through their
463
- // partial operands. Consider the following example:
464
- // ```
465
- // void setX(Point* p, int new_x) {
466
- // p->x = new_x;
467
- // }
468
- // ...
469
- // setX(&p, taint());
470
- // ```
471
- // Here, a `WriteSideEffectInstruction` will provide a new definition for `p->x` after the call to
472
- // `setX`, which will be melded into `p` through a chi instruction.
473
- iTo .getAnOperand ( ) .( ChiPartialOperand ) .getDef ( ) = iFrom .( WriteSideEffectInstruction ) and
474
- not iTo .isResultConflated ( )
475
- or
476
- // Next, we add flow from non-conflated chi instructions to loads (even when they are not precise).
477
- // This ensures that loads of `p->x` gets data flow from the `WriteSideEffectInstruction` above.
478
- exists ( ChiInstruction chi | iFrom = chi |
479
- not chi .isResultConflated ( ) and
480
- iTo .( LoadInstruction ) .getSourceValueOperand ( ) .getAnyDef ( ) = chi
481
- )
482
- or
483
500
// Flow from stores to structs with a single field to a load of that field.
484
501
iTo .( LoadInstruction ) .getSourceValueOperand ( ) .getAnyDef ( ) = iFrom and
485
502
exists ( int size , Type type |
0 commit comments