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/language/learn-ql/python/control-flow.rst
+8-5Lines changed: 8 additions & 5 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -31,7 +31,8 @@ An annotated flow graph:
31
31
32
32
The simplest use of the ``ControlFlowNode`` and ``AstNode`` classes is to find unreachable code. There is one ``ControlFlowNode`` per path through any ``AstNode`` and any ``AstNode`` that is unreachable has no paths flowing through it. Therefore, any ``AstNode`` without a corresponding ``ControlFlowNode`` is unreachable.
33
33
34
-
**Unreachable AST nodes**
34
+
Example finding unreachable AST nodes
35
+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
35
36
36
37
.. code-block:: ql
37
38
@@ -43,7 +44,8 @@ The simplest use of the ``ControlFlowNode`` and ``AstNode`` classes is to find u
43
44
44
45
➤ `See this in the query console <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:
45
46
46
-
**Unreachable statements**
47
+
Example finding unreachable statements
48
+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
47
49
48
50
.. code-block:: ql
49
51
@@ -60,8 +62,8 @@ The ``BasicBlock`` class
60
62
61
63
The ``BasicBlock`` class represents a `basic block <http://en.wikipedia.org/wiki/Basic_block>`__ of control flow nodes. The ``BasicBlock`` class is not that useful for writing queries directly, but is very useful for building complex analyses, such as data flow. The reason it is useful is that it shares many of the interesting properties of control flow nodes, such as what can reach what and what `dominates <http://en.wikipedia.org/wiki/Dominator_%28graph_theory%29>`__ what, but there are fewer basic blocks than control flow nodes - resulting in queries that are faster and use less memory.
62
64
63
-
Example: Finding mutually exclusive basic blocks
64
-
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
65
+
Example finding mutually exclusive basic blocks
66
+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
65
67
66
68
Suppose we have the following Python code:
67
69
@@ -92,7 +94,8 @@ However, by that definition, two basic blocks are mutually exclusive if they are
92
94
93
95
Combining these conditions we get:
94
96
95
-
**Mutually exclusive blocks within the same function**
97
+
Example finding mutually exclusive blocks within the same function
Copy file name to clipboardExpand all lines: docs/language/learn-ql/python/functions.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
@@ -3,7 +3,7 @@ Functions in Python
3
3
4
4
Functions are key building blocks of Python code bases. You can find functions and identify calls to them using syntactic classes from the standard CodeQL library.
5
5
6
-
This example uses the standard CodeQL class ``Function`` (see :doc:`Introducing the Python libraries <introduce-libraries-python>`).
6
+
These examples use the standard CodeQL class `Function<https://help.semmle.com/qldoc/python/semmle/python/Function.qll/type.Function$Function.html>`__. For more information, see :doc:`Introducing the Python libraries <introduce-libraries-python>`.
Copy file name to clipboardExpand all lines: docs/language/learn-ql/python/introduce-libraries-python.rst
+26-18Lines changed: 26 additions & 18 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -3,14 +3,14 @@ CodeQL library for Python
3
3
4
4
Overview of the extensive library you use to analyze databases generated from Python code bases. This library uses classes with abstractions and predicates to present the data in an object-oriented form. This abstraction makes it easier for you to write queries.
5
5
6
-
.. code-block:: ql
6
+
About the CodeQL library for Python
7
+
-----------------------------------
7
8
8
-
import python
9
+
The CodeQL library for each programming language is implemented as a set of QL modules, that is, files with the extension ``.qll``. The module ``python.qll`` imports all the core Python library modules, so you can include the complete library by beginning your query with:
9
10
10
-
The rest of this tutorial summarizes the contents of the standard libraries for Python. We recommend that you read this and then work through the practical examples in the tutorials shown at the end of the page.
11
+
.. code-block:: ql
11
12
12
-
Overview of the library
13
-
-----------------------
13
+
import python
14
14
15
15
The CodeQL library for Python incorporates a large number of classes. Each class corresponds either to one kind of entity in Python source code or to an entity that can be derived from the source code using static analysis. These classes can be divided into four categories:
16
16
@@ -20,16 +20,16 @@ The CodeQL library for Python incorporates a large number of classes. Each class
20
20
- **Taint tracking** - classes that represent the source, sinks and kinds of taint used to implement taint-tracking queries.
21
21
22
22
Syntactic classes
23
-
~~~~~~~~~~~~~~~~~
23
+
-----------------
24
24
25
-
This part of the library represents the Python source code. The ``Module``, ``Class``, and ``Function`` classes correspond to Python modules, classes, and functions respectively, collectively these are known as ``Scope`` classes. Each ``Scope`` contains a list of statements each of which is represented by a subclass of the class ``Stmt``. Statements themselves can contain other statements or expressions which are represented by subclasses of ``Expr``. Finally, there are a few additional classes for the parts of more complex expressions such as list comprehensions. Collectively these classes are subclasses of ``AstNode`` and form an `Abstract syntax tree <http://en.wikipedia.org/wiki/Abstract_syntax_tree>`__ (AST). The root of each AST is a ``Module``.
25
+
This part of the library represents the Python source code. The ``Module``, ``Class``, and ``Function`` classes correspond to Python modules, classes, and functions respectively, collectively these are known as ``Scope`` classes. Each ``Scope`` contains a list of statements each of which is represented by a subclass of the class ``Stmt``. Statements themselves can contain other statements or expressions which are represented by subclasses of ``Expr``. Finally, there are a few additional classes for the parts of more complex expressions such as list comprehensions. Collectively these classes are subclasses of ``AstNode`` and form an Abstract syntax tree (AST). The root of each AST is a ``Module``. For more information, see `Abstract syntax tree <http://en.wikipedia.org/wiki/Abstract_syntax_tree>`__.
26
26
27
-
`Symbolic information <http://en.wikipedia.org/wiki/Symbol_table>`__ is attached to the AST in the form of variables (represented by the class ``Variable``).
27
+
Symbolic information is attached to the AST in the form of variables (represented by the class ``Variable``). For more information, see `Symbolic information <http://en.wikipedia.org/wiki/Symbol_table>`__.
28
28
29
29
Scope
30
30
^^^^^
31
31
32
-
A Python program is a group of modules. Technically a module is just a list of statements, but we often think of it as composed of classes and functions. These top-level entities, the module, class, and function are represented by the three CodeQL classes (`Module <https://help.semmle.com/qldoc/python/semmle/python/Module.qll/type.Module$Module.html>`__, `Class <https://help.semmle.com/qldoc/python/semmle/python/Class.qll/type.Class$Class.html>`__ and `Function <https://help.semmle.com/qldoc/python/semmle/python/Function.qll/type.Function$Function.html>`__ which are all subclasses of ``Scope``.
32
+
A Python program is a group of modules. Technically a module is just a list of statements, but we often think of it as composed of classes and functions. These top-level entities, the module, class, and function are represented by the three CodeQL classes (`Module <https://help.semmle.com/qldoc/python/semmle/python/Module.qll/type.Module$Module.html>`__, `Class <https://help.semmle.com/qldoc/python/semmle/python/Class.qll/type.Class$Class.html>`__ and `Function <https://help.semmle.com/qldoc/python/semmle/python/Function.qll/type.Function$Function.html>`__ which are all subclasses of ``Scope``).
33
33
34
34
- ``Scope``
35
35
@@ -153,8 +153,8 @@ Both forms are equivalent. Using the positive expression, the whole query looks
153
153
154
154
➤ `See this in the query console <https://lgtm.com/query/690010036/>`__. Many projects include pass-only ``except`` blocks.
155
155
156
-
Summary
157
-
^^^^^^^
156
+
Summary of syntactic classes
157
+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
158
158
159
159
The most commonly used standard classes in the syntactic part of the library are organized as follows:
160
160
@@ -237,11 +237,14 @@ Other
237
237
- ``Comment`` – A comment
238
238
239
239
Control flow classes
240
-
~~~~~~~~~~~~~~~~~~~~
240
+
--------------------
241
241
242
242
This part of the library represents the control flow graph of each ``Scope`` (classes, functions, and modules). Each ``Scope`` contains a graph of ``ControlFlowNode`` elements. Each scope has a single entry point and at least one (potentially many) exit points. To speed up control and data flow analysis, control flow nodes are grouped into `basic blocks <http://en.wikipedia.org/wiki/Basic_block>`__.
243
243
244
-
As an example, we might want to find the longest sequence of code without any branches. A ``BasicBlock`` is, by definition, a sequence of code without any branches, so we just need to find the longest ``BasicBlock``.
244
+
Example
245
+
^^^^^^^
246
+
247
+
If we want to find the longest sequence of code without any branches, we need to consider control flow. A ``BasicBlock`` is, by definition, a sequence of code without any branches, so we just need to find the longest ``BasicBlock``.
245
248
246
249
First of all we introduce a simple predicate ``bb_length()`` which relates ``BasicBlock``\ s to their length.
247
250
@@ -289,7 +292,12 @@ The classes in the control-flow part of the library are:
289
292
Type-inference classes
290
293
----------------------
291
294
292
-
The CodeQL library for Python also supplies some classes for accessing the inferred types of values. The classes ``Value`` and ``ClassValue`` allow you to query the possible classes that an expression may have at runtime. For example, which ``ClassValue``\ s are iterable can be determined using the query:
295
+
The CodeQL library for Python also supplies some classes for accessing the inferred types of values. The classes ``Value`` and ``ClassValue`` allow you to query the possible classes that an expression may have at runtime.
296
+
297
+
Example
298
+
^^^^^^^
299
+
300
+
For example, which ``ClassValue``\ s are iterable can be determined using the query:
293
301
294
302
**Find iterable "ClassValue"s**
295
303
@@ -304,15 +312,15 @@ The CodeQL library for Python also supplies some classes for accessing the infer
304
312
➤ `See this in the query console <https://lgtm.com/query/5151030165280978402/>`__ This query returns a list of classes for the projects analyzed. If you want to include the results for `builtin classes <http://docs.python.org/library/stdtypes.html>`__, which do not have any Python source code, show the non-source results.
Copy file name to clipboardExpand all lines: docs/language/learn-ql/python/pointsto-type-infer.rst
+2-1Lines changed: 2 additions & 1 deletion
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -3,6 +3,7 @@ Pointer analysis and type inference in Python
3
3
4
4
At run time, each Python expression has a value with an associated type. You can learn how an expression behaves at run time using type-inference classes from the standard CodeQL library.
5
5
6
+
6
7
This topic contains worked examples of how to write queries using the standard CodeQL library classes for Python type inference.
7
8
8
9
The ``Value`` class
@@ -11,7 +12,7 @@ The ``Value`` class
11
12
The ``Value`` class and its subclasses ``FunctionValue``, ``ClassValue``, and ``ModuleValue`` represent the values an expression may hold at runtime.
Copy file name to clipboardExpand all lines: docs/language/learn-ql/python/statements-expressions.rst
+16-36Lines changed: 16 additions & 36 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -39,13 +39,11 @@ Here is the full class hierarchy:
39
39
- ``While`` – A ``while`` statement
40
40
- ``With`` – A ``with`` statement
41
41
42
-
Example: Finding redundant 'global' statements
43
-
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
42
+
Example finding redundant 'global' statements
43
+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
44
44
45
45
The ``global`` statement in Python declares a variable with a global (module-level) scope, when it would otherwise be local. Using the ``global`` statement outside a class or function is redundant as the variable is already global.
46
46
47
-
**Finding redundant global statements**
48
-
49
47
.. code-block:: ql
50
48
51
49
import python
@@ -58,23 +56,19 @@ The ``global`` statement in Python declares a variable with a global (module-lev
58
56
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
-
Example: Finding 'if' statements with redundant branches
An ``if`` statement where one branch is composed of just ``pass`` statements could be simplified by negating the condition and dropping the ``else`` clause.
65
63
66
-
**An 'if' statement that could be simplified**
67
-
68
64
.. code-block:: python
69
65
70
66
if cond():
71
67
pass
72
68
else:
73
69
do_something
74
70
75
-
To find statements like this we can run the following query:
76
-
77
-
**Find 'if' statements with empty branches**
71
+
To find statements like this that could be simplified we can write a query.
78
72
79
73
.. code-block:: ql
80
74
@@ -133,8 +127,8 @@ Each kind of Python expression has its own class. Here is the full class hierarc
133
127
- ``Yield`` – A ``yield`` expression
134
128
- ``YieldFrom`` – A ``yield from`` expression (Python 3.3+)
135
129
136
-
Example: Finding comparisons to integer or string literals using 'is'
Python implementations commonly cache small integers and single character strings, which means that comparisons such as the following often work correctly, but this is not guaranteed and we might want to check for them.
140
134
@@ -143,9 +137,7 @@ Python implementations commonly cache small integers and single character string
143
137
x is10
144
138
x is"A"
145
139
146
-
We can check for these as follows:
147
-
148
-
**Find comparisons to integer or string literals using** ``is``
140
+
We can check for these using a query.
149
141
150
142
.. code-block:: ql
151
143
@@ -166,15 +158,11 @@ The clause ``cmp.getOp(0) instanceof Is and cmp.getComparator(0) = literal`` che
166
158
167
159
We have to use ``cmp.getOp(0)`` and ``cmp.getComparator(0)``\ as there is no ``cmp.getOp()`` or ``cmp.getComparator()``. The reason for this is that a ``Compare`` expression can have multiple operators. For example, the expression ``3 < x < 7`` has two operators and two comparators. You use ``cmp.getComparator(0)`` to get the first comparator (in this example the ``3``) and ``cmp.getComparator(1)`` to get the second comparator (in this example the ``7``).
168
160
169
-
Example: Duplicates in dictionary literals
170
-
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
161
+
Example finding duplicates in dictionary literals
162
+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
171
163
172
164
If there are duplicate keys in a Python dictionary, then the second key will overwrite the first, which is almost certainly a mistake. We can find these duplicates with CodeQL, but the query is more complex than previous examples and will require us to write a ``predicate`` as a helper.
173
165
174
-
Here is the query:
175
-
176
-
**Find duplicate dictionary keys**
177
-
178
166
.. code-block:: ql
179
167
180
168
import python
@@ -206,12 +194,10 @@ is equivalent to
206
194
207
195
The short version is usually used as this is easier to read.
208
196
209
-
Example: Finding Java-style getters
210
-
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
211
-
212
-
Returning to the example from :doc:`Tutorial: Functions <functions>`, the query identified all methods with a single line of code and a name starting with ``get``:
197
+
Example finding Java-style getters
198
+
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
213
199
214
-
**Basic: Find Java-style getters**
200
+
Returning to the example from :doc:`Tutorial: Functions <functions>`, the query identified all methods with a single line of code and a name starting with ``get``.
215
201
216
202
.. code-block:: ql
217
203
@@ -222,9 +208,7 @@ Returning to the example from :doc:`Tutorial: Functions <functions>`, the query
222
208
and count(f.getAStmt()) = 1
223
209
select f, "This function is (probably) a getter."
224
210
225
-
This basic query can be improved by checking that the one line of code is of the form ``return self.attr``
226
-
227
-
**Improved: Find Java-style getters**
211
+
This basic query can be improved by checking that the one line of code is a Java-style getter of the form ``return self.attr``.
228
212
229
213
.. code-block:: ql
230
214
@@ -238,21 +222,17 @@ This basic query can be improved by checking that the one line of code is of the
238
222
239
223
➤ `See this in the query console <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.
240
224
241
-
In this query, the condition:
242
-
243
225
.. code-block:: ql
244
226
245
227
ret = f.getStmt(0) and ret.getValue() = attr
246
228
247
-
checks that the first line in the method is a return statement and that the expression returned (``ret.getValue()``) is an ``Attribute`` expression. Note that the equality ``ret.getValue() = attr`` means that ``ret.getValue()`` is restricted to ``Attribute``\ s, since ``attr`` is an ``Attribute``.
248
-
249
-
The condition:
229
+
This condition checks that the first line in the method is a return statement and that the expression returned (``ret.getValue()``) is an ``Attribute`` expression. Note that the equality ``ret.getValue() = attr`` means that ``ret.getValue()`` is restricted to ``Attribute``\ s, since ``attr`` is an ``Attribute``.
250
230
251
231
.. code-block:: ql
252
232
253
233
attr.getObject() = self and self.getId() = "self"
254
234
255
-
checks that the value of the attribute (the expression to the left of the dot in ``value.attr``) is an access to a variable called ``"self"``.
235
+
This condition checks that the value of the attribute (the expression to the left of the dot in ``value.attr``) is an access to a variable called ``"self"``.
0 commit comments