@@ -21,15 +21,34 @@ private predicate comes_from_cfgnode(Node node) {
2121 * A data flow node that is a source of local flow. This includes things like
2222 * - Expressions
2323 * - Function parameters
24+ *
25+ *
26+ * Local source nodes and the `flowsTo` relation should be thought of in terms of the reference
27+ * semantics of the underlying object. For instance, in the following snippet of code
28+ *
29+ * ```python
30+ * x = []
31+ * x.append(1)
32+ * x.append(2)
33+ * ```
34+ *
35+ * the local source node corresponding to the occurrences of `x` is the empty list that is assigned to `x`
36+ * originally. Even though the two `append` calls modify the value of `x`, they do not change the fact that
37+ * `x` still points to the same object. If, however, we next do `x = x + [3]`, then the expression `x + [3]`
38+ * will be the new local source of what `x` now points to.
2439 */
2540class LocalSourceNode extends Node {
2641 cached
2742 LocalSourceNode ( ) {
2843 not comes_from_cfgnode ( this ) and
2944 not this instanceof ModuleVariableNode and
30- not this .( PostUpdateNode ) .getPreUpdateNode ( ) in [
31- syntheticPostUpdateNode:: storePreUpdateNode ( ) , syntheticPostUpdateNode:: readPreUpdateNode ( )
32- ]
45+ // Currently, we create synthetic post-update nodes for
46+ // - arguments to calls that may modify said argument
47+ // - direct reads a writes of object attributes
48+ // Both of these preserve the identity of the underlying pointer, and hence we exclude these as
49+ // local source nodes.
50+ // We do, however, allow the post-update nodes that arise from object creation (which are non-synthetic).
51+ not this instanceof SyntheticPostUpdateNode
3352 or
3453 this = any ( ModuleVariableNode mvn ) .getARead ( )
3554 }
0 commit comments