@@ -54,8 +54,8 @@ class Node extends TIRDataFlowNode {
5454 /** Gets the argument that defines this `DefinitionByReferenceNode`, if any. */
5555 Expr asDefiningArgument ( ) { result = this .( DefinitionByReferenceNode ) .getArgument ( ) }
5656
57- /** Gets the parameter corresponding to this node, if any. */
58- Parameter asParameter ( ) { result = this .( ParameterNode ) .getParameter ( ) }
57+ /** Gets the positional parameter corresponding to this node, if any. */
58+ Parameter asParameter ( ) { result = this .( PositionalParameterNode ) .getParameter ( ) }
5959
6060 /**
6161 * Gets the variable corresponding to this node, if any. This can be used for
@@ -142,28 +142,70 @@ class ExprNode extends InstructionNode {
142142 override string toString ( ) { result = this .asConvertedExpr ( ) .toString ( ) }
143143}
144144
145+ /**
146+ * INTERNAL: do not use. Translates a parameter/argument index into a negative
147+ * number that denotes the index of its side effect (pointer indirection).
148+ */
149+ bindingset [ index]
150+ int getArgumentPosOfSideEffect ( int index ) {
151+ // -1 -> -2
152+ // 0 -> -3
153+ // 1 -> -4
154+ // ...
155+ result = - 3 - index
156+ }
157+
145158/**
146159 * The value of a parameter at function entry, viewed as a node in a data
147160 * flow graph.
148161 */
149- class ParameterNode extends InstructionNode {
150- override InitializeParameterInstruction instr ;
151-
162+ abstract class ParameterNode extends InstructionNode {
152163 /**
153- * Holds if this node is the parameter of `c` at the specified (zero-based)
154- * position. The implicit `this` parameter is considered to have index `-1`.
164+ * Holds if this node is the parameter of `f` at the specified position. The
165+ * implicit `this` parameter is considered to have position `-1`, and
166+ * pointer-indirection parameters are at further negative positions.
155167 */
156- predicate isParameterOf ( Function f , int i ) { f .getParameter ( i ) = instr .getParameter ( ) }
168+ abstract predicate isParameterOf ( Function f , int pos ) ;
169+ }
170+
171+ private class ThisParameterNode extends ParameterNode {
172+ override InitializeThisInstruction instr ;
173+
174+ override predicate isParameterOf ( Function f , int pos ) {
175+ pos = - 1 and
176+ instr .getEnclosingFunction ( ) = f
177+ }
178+
179+ override string toString ( ) { result = "this" }
180+ }
157181
182+ class PositionalParameterNode extends ParameterNode {
183+ override InitializeParameterInstruction instr ;
184+
185+ override predicate isParameterOf ( Function f , int pos ) {
186+ f .getParameter ( pos ) = instr .getParameter ( )
187+ }
188+
189+ /** Gets the `Parameter` associated with this node. */
158190 Parameter getParameter ( ) { result = instr .getParameter ( ) }
159191
160- override string toString ( ) { result = instr .getParameter ( ) .toString ( ) }
192+ override string toString ( ) { result = this .getParameter ( ) .toString ( ) }
161193}
162194
163- private class ThisParameterNode extends InstructionNode {
164- override InitializeThisInstruction instr ;
195+ private class ParameterIndirectionNode extends ParameterNode {
196+ override InitializeIndirectionInstruction instr ;
165197
166- override string toString ( ) { result = "this" }
198+ override predicate isParameterOf ( Function f , int pos ) {
199+ exists ( int index |
200+ f .getParameter ( index ) = instr .getParameter ( ) and
201+ pos = getArgumentPosOfSideEffect ( index )
202+ )
203+ }
204+
205+ /** Gets the `Parameter` associated with this node. */
206+ Parameter getParameter ( ) { result = instr .getParameter ( ) }
207+
208+ override string toString ( ) { result = "*" + this .getParameter ( ) .toString ( ) }
167209}
168210
169211/**
@@ -294,7 +336,7 @@ ExprNode convertedExprNode(Expr e) { result.getExpr() = e }
294336/**
295337 * Gets the `Node` corresponding to the value of `p` at function entry.
296338 */
297- ParameterNode parameterNode ( Parameter p ) { result .getParameter ( ) = p }
339+ PositionalParameterNode parameterNode ( Parameter p ) { result .getParameter ( ) = p }
298340
299341/** Gets the `VariableNode` corresponding to the variable `v`. */
300342VariableNode variableNode ( Variable v ) { result .getVariable ( ) = v }
@@ -328,6 +370,24 @@ private predicate simpleInstructionLocalFlowStep(Instruction iFrom, Instruction
328370 or
329371 iTo .( PhiInstruction ) .getAnOperand ( ) .getDef ( ) = iFrom
330372 or
373+ // A read side effect is almost never exact since we don't know exactly how
374+ // much memory the callee will read.
375+ iTo .( ReadSideEffectInstruction ) .getSideEffectOperand ( ) .getAnyDef ( ) = iFrom and
376+ not iFrom .isResultConflated ( )
377+ or
378+ // Loading a single `int` from an `int *` parameter is not an exact load since
379+ // the parameter may point to an entire array rather than a single `int`. The
380+ // following rule ensures that any flow going into the
381+ // `InitializeIndirectionInstruction`, even if it's for a different array
382+ // element, will propagate to a load of the first element.
383+ //
384+ // Since we're linking `InitializeIndirectionInstruction` and
385+ // `LoadInstruction` together directly, this rule will break if there's any
386+ // reassignment of the parameter indirection, including a conditional one that
387+ // leads to a phi node.
388+ iTo .( LoadInstruction ) .getSourceValueOperand ( ) .getAnyDef ( ) =
389+ iFrom .( InitializeIndirectionInstruction )
390+ or
331391 // Treat all conversions as flow, even conversions between different numeric types.
332392 iTo .( ConvertInstruction ) .getUnary ( ) = iFrom
333393 or
0 commit comments