@@ -21,15 +21,34 @@ private predicate comes_from_cfgnode(Node node) {
21
21
* A data flow node that is a source of local flow. This includes things like
22
22
* - Expressions
23
23
* - 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.
24
39
*/
25
40
class LocalSourceNode extends Node {
26
41
cached
27
42
LocalSourceNode ( ) {
28
43
not comes_from_cfgnode ( this ) and
29
44
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
33
52
or
34
53
this = any ( ModuleVariableNode mvn ) .getARead ( )
35
54
}
0 commit comments