@@ -93,8 +93,32 @@ where the return value of ``re.compile`` is used:
93
93
94
94
Note that this includes all uses of the result of ``re.compile ``, including those reachable via
95
95
local flow. To get just the *calls * to ``re.compile ``, you can use ``asSource `` instead of
96
- ``getAValueReachableFromSource ``. As this is a common occurrence, you can use ``getACall `` instead of
97
- ``getReturn `` followed by ``asSource ``.
96
+ ``getAValueReachableFromSource ``. As this is a common occurrence, you can, instead of
97
+ ``getReturn `` followed by ``asSource ``, simply use ``getACall ``. This will result in an
98
+ ``API::CallNode ``, which deserves a small description of its own.
99
+
100
+ ``API::CallNode``s are not ``API::Node``s. Instead they are ``DataFlow::Node``s with some convenience
101
+ predicates that allows you to recover ``API::Node``s for the return value as well as for parameters
102
+ to the call. This enables you to constrain the call in various ways using the API graph. The following
103
+ snippet finds all calls to ``re.compile `` where the ``pattern `` argument comes from parsing a command
104
+ line argument using the ``argparse `` library.
105
+
106
+ .. code-block :: ql
107
+
108
+ import python
109
+ import semmle.python.ApiGraphs
110
+
111
+ from API::CallNode call
112
+ where
113
+ call = API::moduleImport("re").getMember("compile").getACall() and
114
+ call.getParameter(0, "pattern") =
115
+ API::moduleImport("argparse")
116
+ .getMember("ArgumentParser")
117
+ .getReturn()
118
+ .getMember("parse_args")
119
+ .getMember(_)
120
+ select call
121
+
98
122
99
123
Note that the API graph does not distinguish between class instantiations and function calls. As far
100
124
as it's concerned, both are simply places where an API graph node is called.
0 commit comments