@@ -71,9 +71,7 @@ class Node extends TIRDataFlowNode {
7171 * `x.set(taint())` is a partial definition of `x`, and `transfer(&x, taint())` is
7272 * a partial definition of `&x`).
7373 */
74- Expr asPartialDefinition ( ) {
75- result = this .( PartialDefinitionNode ) .getInstruction ( ) .getUnconvertedResultExpression ( )
76- }
74+ Expr asPartialDefinition ( ) { result = this .( PartialDefinitionNode ) .getDefinedExpr ( ) }
7775
7876 /**
7977 * DEPRECATED: See UninitializedNode.
@@ -162,11 +160,7 @@ class ExprNode extends InstructionNode {
162160 * as `x` in `f(x)` and implicit parameters such as `this` in `x.f()`
163161 */
164162class ParameterNode extends InstructionNode {
165- ParameterNode ( ) {
166- instr instanceof InitializeParameterInstruction
167- or
168- instr instanceof InitializeThisInstruction
169- }
163+ override InitializeParameterInstruction instr ;
170164
171165 /**
172166 * Holds if this node is the parameter of `c` at the specified (zero-based)
@@ -180,7 +174,7 @@ class ParameterNode extends InstructionNode {
180174 * flow graph.
181175 */
182176private class ExplicitParameterNode extends ParameterNode {
183- override InitializeParameterInstruction instr ;
177+ ExplicitParameterNode ( ) { exists ( instr . getParameter ( ) ) }
184178
185179 override predicate isParameterOf ( Function f , int i ) { f .getParameter ( i ) = instr .getParameter ( ) }
186180
@@ -191,7 +185,7 @@ private class ExplicitParameterNode extends ParameterNode {
191185}
192186
193187private class ThisParameterNode extends ParameterNode {
194- override InitializeThisInstruction instr ;
188+ ThisParameterNode ( ) { instr . getIRVariable ( ) instanceof IRThisVariable }
195189
196190 override predicate isParameterOf ( Function f , int i ) {
197191 i = - 1 and instr .getEnclosingFunction ( ) = f
@@ -251,14 +245,17 @@ abstract class PostUpdateNode extends InstructionNode {
251245 * setY(&x); // a partial definition of the object `x`.
252246 * ```
253247 */
254- abstract private class PartialDefinitionNode extends PostUpdateNode , TInstructionNode { }
248+ abstract private class PartialDefinitionNode extends PostUpdateNode , TInstructionNode {
249+ abstract Expr getDefinedExpr ( ) ;
250+ }
255251
256252private class ExplicitFieldStoreQualifierNode extends PartialDefinitionNode {
257253 override ChiInstruction instr ;
254+ FieldAddressInstruction field ;
258255
259256 ExplicitFieldStoreQualifierNode ( ) {
260257 not instr .isResultConflated ( ) and
261- exists ( StoreInstruction store , FieldInstruction field |
258+ exists ( StoreInstruction store |
262259 instr .getPartial ( ) = store and field = store .getDestinationAddress ( )
263260 )
264261 }
@@ -268,6 +265,10 @@ private class ExplicitFieldStoreQualifierNode extends PartialDefinitionNode {
268265 // DataFlowImplConsistency::Consistency. However, it's not clear what (if any) implications
269266 // this consistency failure has.
270267 override Node getPreUpdateNode ( ) { result .asInstruction ( ) = instr .getTotal ( ) }
268+
269+ override Expr getDefinedExpr ( ) {
270+ result = field .getObjectAddress ( ) .getUnconvertedResultExpression ( )
271+ }
271272}
272273
273274/**
@@ -278,15 +279,18 @@ private class ExplicitFieldStoreQualifierNode extends PartialDefinitionNode {
278279 */
279280private class ExplicitSingleFieldStoreQualifierNode extends PartialDefinitionNode {
280281 override StoreInstruction instr ;
282+ FieldAddressInstruction field ;
281283
282284 ExplicitSingleFieldStoreQualifierNode ( ) {
283- exists ( FieldAddressInstruction field |
284- field = instr .getDestinationAddress ( ) and
285- not exists ( ChiInstruction chi | chi .getPartial ( ) = instr )
286- )
285+ field = instr .getDestinationAddress ( ) and
286+ not exists ( ChiInstruction chi | chi .getPartial ( ) = instr )
287287 }
288288
289289 override Node getPreUpdateNode ( ) { none ( ) }
290+
291+ override Expr getDefinedExpr ( ) {
292+ result = field .getObjectAddress ( ) .getUnconvertedResultExpression ( )
293+ }
290294}
291295
292296/**
@@ -458,9 +462,9 @@ private predicate simpleInstructionLocalFlowStep(Instruction iFrom, Instruction
458462 // for now.
459463 iTo .getAnOperand ( ) .( ChiTotalOperand ) .getDef ( ) = iFrom
460464 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:
465+ // Add flow from write side-effects to non-conflated chi instructions through their
466+ // partial operands. From there, a `readStep` will find subsequent reads of that field.
467+ // Consider the following example:
464468 // ```
465469 // void setX(Point* p, int new_x) {
466470 // p->x = new_x;
@@ -470,14 +474,9 @@ private predicate simpleInstructionLocalFlowStep(Instruction iFrom, Instruction
470474 // ```
471475 // Here, a `WriteSideEffectInstruction` will provide a new definition for `p->x` after the call to
472476 // `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
477+ exists ( ChiInstruction chi | chi = iTo |
478+ chi .getPartialOperand ( ) .getDef ( ) = iFrom .( WriteSideEffectInstruction ) and
479+ not chi .isResultConflated ( )
481480 )
482481 or
483482 // Flow from stores to structs with a single field to a load of that field.
0 commit comments