@@ -239,6 +239,8 @@ abstract class PostUpdateNode extends InstructionNode {
239239}
240240
241241/**
242+ * INTERNAL: do not use.
243+ *
242244 * The base class for nodes that perform "partial definitions".
243245 *
244246 * In contrast to a normal "definition", which provides a new value for
@@ -251,7 +253,7 @@ abstract class PostUpdateNode extends InstructionNode {
251253 * setY(&x); // a partial definition of the object `x`.
252254 * ```
253255 */
254- abstract private class PartialDefinitionNode extends PostUpdateNode , TInstructionNode { }
256+ abstract class PartialDefinitionNode extends PostUpdateNode , TInstructionNode { }
255257
256258private class ExplicitFieldStoreQualifierNode extends PartialDefinitionNode {
257259 override ChiInstruction instr ;
@@ -270,6 +272,17 @@ private class ExplicitFieldStoreQualifierNode extends PartialDefinitionNode {
270272 override Node getPreUpdateNode ( ) { result .asInstruction ( ) = instr .getTotal ( ) }
271273}
272274
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+
273286/**
274287 * Not every store instruction generates a chi instruction that we can attach a PostUpdateNode to.
275288 * 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
421434 */
422435predicate simpleLocalFlowStep ( Node nodeFrom , Node nodeTo ) {
423436 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+ )
424463}
425464
426465pragma [ noinline]
@@ -458,28 +497,6 @@ private predicate simpleInstructionLocalFlowStep(Instruction iFrom, Instruction
458497 // for now.
459498 iTo .getAnOperand ( ) .( ChiTotalOperand ) .getDef ( ) = iFrom
460499 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
483500 // Flow from stores to structs with a single field to a load of that field.
484501 iTo .( LoadInstruction ) .getSourceValueOperand ( ) .getAnyDef ( ) = iFrom and
485502 exists ( int size , Type type |
0 commit comments