You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/codeql/codeql-language-guides/analyzing-control-flow-in-python.rst
+3-3Lines changed: 3 additions & 3 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -47,7 +47,7 @@ Example finding unreachable AST nodes
47
47
where not exists(node.getAFlowNode())
48
48
select node
49
49
50
-
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/669220024/>`__. The demo projects on LGTM.com all have some code that has no control flow node, and is therefore unreachable. However, since the ``Module`` class is also a subclass of the ``AstNode`` class, the query also finds any modules implemented in C or with no source code. Therefore, it is better to find all unreachable statements.
50
+
Many codebases have some code that has no control flow node, and is therefore unreachable. However, since the ``Module`` class is also a subclass of the ``AstNode`` class, the query also finds any modules implemented in C or with no source code. Therefore, it is better to find all unreachable statements.
51
51
52
52
Example finding unreachable statements
53
53
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -60,7 +60,7 @@ Example finding unreachable statements
60
60
where not exists(s.getAFlowNode())
61
61
select s
62
62
63
-
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/670720181/>`__. This query gives fewer results, but most of the projects have some unreachable nodes. These are also highlighted by the standard "Unreachable code" query. For more information, see `Unreachable code <https://lgtm.com/rules/3980095>`__ on LGTM.com.
63
+
This query should give fewer results. You can also find unreachable code using the standard "Unreachable code" query. For more information, see `Unreachable code <https://codeql.github.com/codeql-query-help/python/py-unreachable-statement/>`__.
64
64
65
65
The ``BasicBlock`` class
66
66
------------------------
@@ -114,7 +114,7 @@ Example finding mutually exclusive blocks within the same function
114
114
)
115
115
select b1, b2
116
116
117
-
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/671000028/>`__. This typically gives a very large number of results, because it is a common occurrence in normal control flow. It is, however, an example of the sort of control-flow analysis that is possible. Control-flow analyses such as this are an important aid to data flow analysis. For more information, see ":doc:`Analyzing data flow in Python <analyzing-data-flow-in-python>`."
117
+
This typically gives a very large number of results, because it is a common occurrence in normal control flow. It is, however, an example of the sort of control-flow analysis that is possible. Control-flow analyses such as this are an important aid to data flow analysis. For more information, see ":doc:`Analyzing data flow in Python <analyzing-data-flow-in-python>`."
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/8635258505893505141/>`__. Two of the demo projects make use of this low-level API.
101
-
102
100
Notice the use of the ``API`` module for referring to library functions. For more information, see ":doc:`Using API graphs in Python <using-api-graphs-in-python>`."
103
101
104
-
Unfortunately this will only give the expression in the argument, not the values which could be passed to it. So we use local data flow to find all expressions that flow into the argument:
102
+
Unfortunately this query will only give the expression in the argument, not the values which could be passed to it. So we use local data flow to find all expressions that flow into the argument:
105
103
106
104
.. code-block:: ql
107
105
@@ -115,9 +113,7 @@ Unfortunately this will only give the expression in the argument, not the values
115
113
DataFlow::localFlow(expr, call.getArg(0))
116
114
select call, expr
117
115
118
-
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/8213643003890447109/>`__. Many expressions flow to the same call.
119
-
120
-
We see that we get several data-flow nodes for an expression as it flows towards a call (notice repeated locations in the ``call`` column). We are mostly interested in the "first" of these, what might be called the local source for the file name. To restrict attention to such local sources, and to simultaneously make the analysis more performant, we have the QL class ``LocalSourceNode``. We could demand that ``expr`` is such a node:
116
+
Typically, you will see several data-flow nodes for an expression as it flows towards a call (notice repeated locations in the ``call`` column). We are mostly interested in the "first" of these, what might be called the local source for the file name. To restrict attention to such local sources, and to simultaneously make the analysis more performant, we have the QL class ``LocalSourceNode``. We could demand that ``expr`` is such a node:
121
117
122
118
.. code-block:: ql
123
119
@@ -160,9 +156,9 @@ As an alternative, we can ask more directly that ``expr`` is a local source of t
160
156
expr = call.getArg(0).getALocalSource()
161
157
select call, expr
162
158
163
-
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/6602079735954016687/>`__. All these three queries give identical results. We now mostly have one expression per call.
159
+
These three queries all give identical results. We now mostly have one expression per call.
164
160
165
-
We still have some cases of more than one expression flowing to a call, but then they flow through different code paths (possibly due to control-flow splitting, as in the second case).
161
+
We still have some cases of more than one expression flowing to a call, but then they flow through different code paths (possibly due to control-flow splitting).
166
162
167
163
We might want to make the source more specific, for example a parameter to a function or method. This query finds instances where a parameter is used as the name when opening a file:
168
164
@@ -178,7 +174,7 @@ We might want to make the source more specific, for example a parameter to a fun
178
174
DataFlow::localFlow(p, call.getArg(0))
179
175
select call, p
180
176
181
-
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/3998032643497238063/>`__. Very few results now; these could feasibly be inspected manually.
177
+
For most codebases, this will return only a few results and these could be inspected manually.
182
178
183
179
Using the exact name supplied via the parameter may be too strict. If we want to know if the parameter influences the file name, we can use taint tracking instead of data flow. This query finds calls to ``os.open`` where the filename is derived from a parameter:
184
180
@@ -194,7 +190,7 @@ Using the exact name supplied via the parameter may be too strict. If we want to
194
190
TaintTracking::localTaint(p, call.getArg(0))
195
191
select call, p
196
192
197
-
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/2129957933670836953/>`__. Now we get more results and in more projects.
193
+
Typically, this finds more results.
198
194
199
195
Global data flow
200
196
----------------
@@ -369,8 +365,6 @@ This data flow configuration tracks data flow from environment variables to open
369
365
select fileOpen, "This call to 'os.open' uses data from $@.",
370
366
environment, "call to 'os.getenv'"
371
367
372
-
➤ `Running this in the query console on LGTM.com <https://lgtm.com/query/6582374907796191895/>`__ unsurprisingly yields no results in the demo projects.
Copy file name to clipboardExpand all lines: docs/codeql/codeql-language-guides/codeql-for-python.rst
+1-1Lines changed: 1 addition & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -16,7 +16,7 @@ Experiment and learn how to write effective and efficient queries for CodeQL dat
16
16
expressions-and-statements-in-python
17
17
analyzing-control-flow-in-python
18
18
19
-
- :doc:`Basic query for Python code <basic-query-for-python-code>`: Learn to write and run a simple CodeQL query using LGTM.
19
+
- :doc:`Basic query for Python code <basic-query-for-python-code>`: Learn to write and run a simple CodeQL query.
20
20
21
21
- :doc:`CodeQL library for Python <codeql-library-for-python>`: When you need to analyze a Python program, you can make use of the large collection of classes in the CodeQL library for Python.
Copy file name to clipboardExpand all lines: docs/codeql/codeql-language-guides/codeql-library-for-python.rst
+4-6Lines changed: 4 additions & 6 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -53,7 +53,7 @@ All scopes are basically a list of statements, although ``Scope`` classes have a
53
53
where f.getScope() instanceof Function
54
54
select f
55
55
56
-
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/665620040/>`__. Many projects have nested functions.
56
+
Many codebases use nested functions.
57
57
58
58
Statement
59
59
^^^^^^^^^
@@ -95,7 +95,7 @@ As an example, to find expressions of the form ``a+2`` where the left is a simpl
95
95
where bin.getLeft() instanceof Name and bin.getRight() instanceof Num
96
96
select bin
97
97
98
-
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/669950026/>`__. Many projects include examples of this pattern.
98
+
Many codebases include examples of this pattern.
99
99
100
100
Variable
101
101
^^^^^^^^
@@ -126,7 +126,7 @@ For our first example, we can find all ``finally`` blocks by using the ``Try`` c
126
126
from Try t
127
127
select t.getFinalbody()
128
128
129
-
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/659662193/>`__. Many projects include examples of this pattern.
129
+
Many codebases include examples of this pattern.
130
130
131
131
2. Finding ``except`` blocks that do nothing
132
132
''''''''''''''''''''''''''''''''''''''''''''
@@ -157,7 +157,7 @@ Both forms are equivalent. Using the positive expression, the whole query looks
157
157
where forall(Stmt s | s = ex.getAStmt() | s instanceof Pass)
158
158
select ex
159
159
160
-
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/690010036/>`__. Many projects include pass-only ``except`` blocks.
160
+
Many codebases include pass-only ``except`` blocks.
161
161
162
162
Summary
163
163
^^^^^^^
@@ -278,8 +278,6 @@ Using this predicate we can select the longest ``BasicBlock`` by selecting the `
278
278
where bb_length(b) = max(bb_length(_))
279
279
select b
280
280
281
-
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/666730036/>`__. When we ran it on the LGTM.com demo projects, the *openstack/nova* and *ytdl-org/youtube-dl* projects both contained source code results for this query.
Copy file name to clipboardExpand all lines: docs/codeql/codeql-language-guides/expressions-and-statements-in-python.rst
+2-8Lines changed: 2 additions & 8 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -54,8 +54,6 @@ The ``global`` statement in Python declares a variable with a global (module-lev
54
54
where g.getScope() instanceof Module
55
55
select g
56
56
57
-
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/686330052/>`__. None of the demo projects on LGTM.com has a global statement that matches this pattern.
58
-
59
57
The line: ``g.getScope() instanceof Module`` ensures that the ``Scope`` of ``Global g`` is a ``Module``, rather than a class or function.
60
58
61
59
Example finding 'if' statements with redundant branches
@@ -81,7 +79,7 @@ To find statements like this that could be simplified we can write a query.
81
79
and forall(Stmt p | p = l.getAnItem() | p instanceof Pass)
82
80
select i
83
81
84
-
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/672230053/>`__. Many projects have some ``if`` statements that match this pattern.
82
+
Many codebases have some ``if`` statements that match this pattern.
85
83
86
84
The line: ``(l = i.getBody() or l = i.getOrelse())`` restricts the ``StmtList l`` to branches of the ``if`` statement.
87
85
@@ -150,8 +148,6 @@ We can check for these using a query.
150
148
and cmp.getOp(0) instanceof Is and cmp.getComparator(0) = literal
151
149
select cmp
152
150
153
-
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/688180010/>`__. Two of the demo projects on LGTM.com use this pattern: *saltstack/salt* and *openstack/nova*.
154
-
155
151
The clause ``cmp.getOp(0) instanceof Is and cmp.getComparator(0) = literal`` checks that the first comparison operator is "is" and that the first comparator is a literal.
156
152
157
153
.. pull-quote::
@@ -180,7 +176,7 @@ If there are duplicate keys in a Python dictionary, then the second key will ove
180
176
and k1 != k2 and same_key(k1, k2)
181
177
select k1, "Duplicate key in dict literal"
182
178
183
-
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/663330305/>`__. When we ran this query on LGTM.com, the source code of the *saltstack/salt* project contained an example of duplicate dictionary keys. The results were also highlighted as alerts by the standard "Duplicate key in dict literal" query. Two of the other demo projects on LGTM.com refer to duplicate dictionary keys in library files. For more information, see `Duplicate key in dict literal <https://lgtm.com/rules/3980087>`__ on LGTM.com.
179
+
When we ran this query on some test codebases, we found examples of duplicate dictionary keys. The results were also highlighted as alerts by the standard "Duplicate key in dict literal" query. For more information, see `Duplicate key in dict literal <https://codeql.github.com/codeql-query-help/python/py-duplicate-key-dict-literal/>`__.
184
180
185
181
The supporting predicate ``same_key`` checks that the keys have the same identifier. Separating this part of the logic into a supporting predicate, instead of directly including it in the query, makes it easier to understand the query as a whole. The casts defined in the predicate restrict the expression to the type specified and allow predicates to be called on the type that is cast-to. For example:
186
182
@@ -222,8 +218,6 @@ This basic query can be improved by checking that the one line of code is a Java
222
218
and attr.getObject() = self and self.getId() = "self"
223
219
select f, "This function is a Java-style getter."
224
220
225
-
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/669220054/>`__. Of the demo projects on LGTM.com, only the *openstack/nova* project has examples of functions that appear to be Java-style getters.
Copy file name to clipboardExpand all lines: docs/codeql/codeql-language-guides/functions-in-python.rst
+3-5Lines changed: 3 additions & 5 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -28,7 +28,7 @@ Using the member predicate ``Function.getName()``, we can list all of the getter
28
28
where f.getName().matches("get%")
29
29
select f, "This is a function called get..."
30
30
31
-
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/669220031/>`__. This query typically finds a large number of results. Usually, many of these results are for functions (rather than methods) which we are not interested in.
31
+
This query typically finds a large number of results. Usually, many of these results are for functions (rather than methods) which we are not interested in.
32
32
33
33
Finding all methods called "get..."
34
34
-----------------------------------
@@ -43,7 +43,7 @@ You can modify the query above to return more interesting results. As we are onl
43
43
where f.getName().matches("get%") and f.isMethod()
44
44
select f, "This is a method called get..."
45
45
46
-
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/690010035/>`__. This finds methods whose name starts with ``"get"``, but many of those are not the sort of simple getters we are interested in.
46
+
This finds methods whose name starts with ``"get"``, but many of those are not the sort of simple getters we are interested in.
47
47
48
48
Finding one line methods called "get..."
49
49
----------------------------------------
@@ -59,7 +59,7 @@ We can modify the query further to include only methods whose body consists of a
59
59
and count(f.getAStmt()) = 1
60
60
select f, "This function is (probably) a getter."
61
61
62
-
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/667290044/>`__. This query returns fewer results, but if you examine the results you can see that there are still refinements to be made. This is refined further in ":doc:`Expressions and statements in Python <expressions-and-statements-in-python>`."
62
+
This query returns fewer results, but if you examine the results you can see that there are still refinements to be made. This is refined further in ":doc:`Expressions and statements in Python <expressions-and-statements-in-python>`."
63
63
64
64
Finding a call to a specific function
65
65
-------------------------------------
@@ -74,8 +74,6 @@ This query uses ``Call`` and ``Name`` to find calls to the function ``eval`` - w
74
74
where call.getFunc() = name and name.getId() = "eval"
75
75
select call, "call to 'eval'."
76
76
77
-
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/6718356557331218618/>`__. Some of the demo projects on LGTM.com use this function.
78
-
79
77
The ``Call`` class represents calls in Python. The ``Call.getFunc()`` predicate gets the expression being called. ``Name.getId()`` gets the identifier (as a string) of the ``Name`` expression.
80
78
Due to the dynamic nature of Python, this query will select any call of the form ``eval(...)`` regardless of whether it is a call to the built-in function ``eval`` or not.
81
79
In a later tutorial we will see how to use the type-inference library to find calls to the built-in function ``eval`` regardless of name of the variable called.
Copy file name to clipboardExpand all lines: docs/codeql/codeql-language-guides/using-api-graphs-in-python.rst
-12Lines changed: 0 additions & 12 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -29,8 +29,6 @@ following snippet demonstrates.
29
29
30
30
select API::moduleImport("re")
31
31
32
-
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/1876172022264324639/>`__.
33
-
34
32
This query selects the API graph node corresponding to the ``re`` module. This node represents the fact that the ``re`` module has been imported rather than a specific location in the program where the import happens. Therefore, there will be at most one result per project, and it will not have a useful location, so you'll have to click `Show 1 non-source result` in order to see it.
35
33
36
34
To find where the ``re`` module is referenced in the program, you can use the ``getAUse`` method. The following query selects all references to the ``re`` module in the current database.
@@ -42,8 +40,6 @@ To find where the ``re`` module is referenced in the program, you can use the ``
42
40
43
41
select API::moduleImport("re").getAUse()
44
42
45
-
➤ `See this in the query console on LGTM.com <https://lgtm.com/query/8072356519514905526/>`__.
46
-
47
43
Note that the ``getAUse`` method accounts for local flow, so that ``my_re_compile``
48
44
in the following snippet is
49
45
correctly recognized as a reference to the ``re.compile`` function.
@@ -77,8 +73,6 @@ the above ``re.compile`` example, you can now find references to ``re.compile``.
0 commit comments