Files
codeql-info/ql/docs/language/learn-ql/build.html-5f4acb8/codeql-language-guides/expressions-and-statements-in-python.html
2023-11-20 11:57:03 -08:00

456 lines
43 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="en" data-content_root="../">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="viewport" content="width=device-width, initial-scale=1" />
<title>Expressions and statements in Python &#8212; CodeQL</title>
<link rel="stylesheet" type="text/css" href="../_static/pygments.css?v=fa44fd50" />
<link rel="stylesheet" type="text/css" href="../_static/alabaster.css?v=93459777" />
<script src="../_static/documentation_options.js?v=5929fcd5"></script>
<script src="../_static/doctools.js?v=888ff710"></script>
<script src="../_static/sphinx_highlight.js?v=dc90522c"></script>
<link rel="icon" href="../_static/favicon.ico"/>
<link rel="index" title="Index" href="../genindex.html" />
<link rel="search" title="Search" href="../search.html" />
<link rel="next" title="Analyzing control flow in Python" href="analyzing-control-flow-in-python.html" />
<link rel="prev" title="Functions in Python" href="functions-in-python.html" />
<title>CodeQL docs</title>
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link rel="stylesheet" href="../_static/custom.css" type="text/css" />
<link rel="stylesheet" href="../_static/primer.css" type="text/css" />
</head><body>
<header class="Header">
<div class="Header-item--full">
<a href="https://codeql.github.com/docs" class="Header-link f2 d-flex flex-items-center">
<!-- <%= octicon "mark-github", class: "mr-2", height: 32 %> -->
<svg height="32" class="octicon octicon-mark-github mr-2" viewBox="0 0 16 16" version="1.1" width="32"
aria-hidden="true">
<path fill-rule="evenodd"
d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0 0 16 8c0-4.42-3.58-8-8-8z">
</path>
</svg>
<span class="hide-sm">CodeQL documentation</span>
</a>
</div>
<div class="Header-item hide-sm hide-md">
<script src="https://addsearch.com/js/?key=93b4d287e2fc079a4089412b669785d5&categories=!0xhelp.semmle.com,0xcodeql.github.com,1xdocs,1xcodeql-standard-libraries,1xcodeql-query-help"></script>
</div>
<div class="Header-item">
<details class="dropdown details-reset details-overlay d-inline-block">
<summary class="btn bg-gray-dark text-white border" aria-haspopup="true">
CodeQL resources
<div class="dropdown-caret"></div>
</summary>
<ul class="dropdown-menu dropdown-menu-se dropdown-menu-dark">
<li><a class="dropdown-item" href="https://codeql.github.com/docs/codeql-overview">CodeQL overview</a></li>
<li class="dropdown-divider" role="separator"></li>
<div class="dropdown-header">
CodeQL tools
</div>
<li><a class="dropdown-item" href="https://codeql.github.com/docs/codeql-for-visual-studio-code">CodeQL for VS Code</a>
<li><a class="dropdown-item" href="https://codeql.github.com/docs/codeql-cli">CodeQL CLI</a>
</li>
<li class="dropdown-divider" role="separator"></li>
<div class="dropdown-header">
CodeQL guides
</div>
<li><a class="dropdown-item" href="https://codeql.github.com/docs/writing-codeql-queries">Writing CodeQL queries</a></li>
<li><a class="dropdown-item" href="https://codeql.github.com/docs/codeql-language-guides">CodeQL language guides</a>
<li class="dropdown-divider" role="separator"></li>
<div class="dropdown-header">
Reference docs
</div>
<li><a class="dropdown-item" href="https://codeql.github.com/docs/ql-language-reference/">QL language
reference</a>
<li><a class="dropdown-item" href="https://codeql.github.com/codeql-standard-libraries">CodeQL
standard-libraries</a>
<li><a class="dropdown-item" href="https://codeql.github.com/codeql-query-help">CodeQL
query help</a>
<li class="dropdown-divider" role="separator"></li>
<div class="dropdown-header">
Source files
</div>
<li><a class="dropdown-item" href="https://github.com/github/codeql">CodeQL repository</a>
</ul>
</details>
</div>
</header>
<main class="bg-gray-light clearfix">
<nav class="SideNav position-sticky top-0 col-lg-3 col-md-3 float-left p-4 hide-sm hide-md overflow-y-auto">
<ul class="current">
<li class="toctree-l1"><a class="reference internal" href="../codeql-overview/index.html">CodeQL overview</a></li>
<li class="toctree-l1"><a class="reference internal" href="../codeql-for-visual-studio-code/index.html">CodeQL for Visual Studio Code</a></li>
<li class="toctree-l1"><a class="reference internal" href="../codeql-cli/index.html">CodeQL CLI</a></li>
<li class="toctree-l1"><a class="reference internal" href="../writing-codeql-queries/index.html">Writing CodeQL queries</a></li>
<li class="toctree-l1 current"><a class="reference internal" href="index.html">CodeQL language guides</a><ul class="current">
<li class="toctree-l2"><a class="reference internal" href="codeql-for-cpp.html">CodeQL for C and C++</a></li>
<li class="toctree-l2"><a class="reference internal" href="codeql-for-csharp.html">CodeQL for C#</a></li>
<li class="toctree-l2"><a class="reference internal" href="codeql-for-go.html">CodeQL for Go</a></li>
<li class="toctree-l2"><a class="reference internal" href="codeql-for-java.html">CodeQL for Java</a></li>
<li class="toctree-l2"><a class="reference internal" href="codeql-for-javascript.html">CodeQL for JavaScript</a></li>
<li class="toctree-l2 current"><a class="reference internal" href="codeql-for-python.html">CodeQL for Python</a><ul class="current">
<li class="toctree-l3"><a class="reference internal" href="basic-query-for-python-code.html">Basic query for Python code</a></li>
<li class="toctree-l3"><a class="reference internal" href="codeql-library-for-python.html">CodeQL library for Python</a></li>
<li class="toctree-l3"><a class="reference internal" href="analyzing-data-flow-in-python.html">Analyzing data flow in Python</a></li>
<li class="toctree-l3"><a class="reference internal" href="using-api-graphs-in-python.html">Using API graphs in Python</a></li>
<li class="toctree-l3"><a class="reference internal" href="functions-in-python.html">Functions in Python</a></li>
<li class="toctree-l3 current"><a class="current reference internal" href="#">Expressions and statements in Python</a></li>
<li class="toctree-l3"><a class="reference internal" href="analyzing-control-flow-in-python.html">Analyzing control flow in Python</a></li>
</ul>
</li>
<li class="toctree-l2"><a class="reference internal" href="codeql-for-ruby.html">CodeQL for Ruby</a></li>
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="../ql-language-reference/index.html">QL language reference</a></li>
</ul>
</nav>
<div class="body col-sm-12 col-md-9 col-lg-9 float-left border-left">
<div class="hide-lg hide-xl px-4 pt-4">
<div class="related" role="navigation" aria-label="related navigation">
<ul>
<li class="nav-item nav-item-0"><a href="../contents.html">CodeQL</a> &#187;</li>
<li class="nav-item nav-item-1"><a href="index.html"
>CodeQL language guides</a> &#187;</li>
<li class="nav-item nav-item-2"><a href="codeql-for-python.html"
accesskey="U">CodeQL for Python</a> &#187;</li>
</ul>
</div>
</div>
<article class="p-4 col-lg-10 col-md-10 col-sm-12">
<section id="expressions-and-statements-in-python">
<span id="id1"></span><h1>Expressions and statements in Python<a class="headerlink" href="#expressions-and-statements-in-python" title="Link to this heading"></a></h1>
<p>You can use syntactic classes from the CodeQL library to explore how Python expressions and statements are used in a code base.</p>
<section id="statements">
<h2>Statements<a class="headerlink" href="#statements" title="Link to this heading"></a></h2>
<p>The bulk of Python code takes the form of statements. Each different type of statement in Python is represented by a separate CodeQL class.</p>
<p>Here is the full class hierarchy:</p>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">Stmt</span></code> A statement</p>
<ul>
<li><p><code class="docutils literal notranslate"><span class="pre">Assert</span></code> An <code class="docutils literal notranslate"><span class="pre">assert</span></code> statement</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">Assign</span></code></p>
<ul>
<li><p><code class="docutils literal notranslate"><span class="pre">AssignStmt</span></code> An assignment statement, <code class="docutils literal notranslate"><span class="pre">x</span> <span class="pre">=</span> <span class="pre">y</span></code></p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">ClassDef</span></code> A class definition statement</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">FunctionDef</span></code> A function definition statement</p></li>
</ul>
</li>
<li><p><code class="docutils literal notranslate"><span class="pre">AugAssign</span></code> An augmented assignment, <code class="docutils literal notranslate"><span class="pre">x</span> <span class="pre">+=</span> <span class="pre">y</span></code></p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">Break</span></code> A <code class="docutils literal notranslate"><span class="pre">break</span></code> statement</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">Continue</span></code> A <code class="docutils literal notranslate"><span class="pre">continue</span></code> statement</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">Delete</span></code> A <code class="docutils literal notranslate"><span class="pre">del</span></code> statement</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">ExceptStmt</span></code> The <code class="docutils literal notranslate"><span class="pre">except</span></code> part of a <code class="docutils literal notranslate"><span class="pre">try</span></code> statement</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">Exec</span></code> An <code class="docutils literal notranslate"><span class="pre">exec</span></code> statement</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">For</span></code> A <code class="docutils literal notranslate"><span class="pre">for</span></code> statement</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">Global</span></code> A <code class="docutils literal notranslate"><span class="pre">global</span></code> statement</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">If</span></code> An <code class="docutils literal notranslate"><span class="pre">if</span></code> statement</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">ImportStar</span></code> A <code class="docutils literal notranslate"><span class="pre">from</span> <span class="pre">xxx</span> <span class="pre">import</span> <span class="pre">*</span></code> statement</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">Import</span></code> Any other <code class="docutils literal notranslate"><span class="pre">import</span></code> statement</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">Nonlocal</span></code> A <code class="docutils literal notranslate"><span class="pre">nonlocal</span></code> statement</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">Pass</span></code> A <code class="docutils literal notranslate"><span class="pre">pass</span></code> statement</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">Print</span></code> A <code class="docutils literal notranslate"><span class="pre">print</span></code> statement (Python 2 only)</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">Raise</span></code> A <code class="docutils literal notranslate"><span class="pre">raise</span></code> statement</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">Return</span></code> A <code class="docutils literal notranslate"><span class="pre">return</span></code> statement</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">Try</span></code> A <code class="docutils literal notranslate"><span class="pre">try</span></code> statement</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">While</span></code> A <code class="docutils literal notranslate"><span class="pre">while</span></code> statement</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">With</span></code> A <code class="docutils literal notranslate"><span class="pre">with</span></code> statement</p></li>
</ul>
</li>
</ul>
<section id="example-finding-redundant-global-statements">
<h3>Example finding redundant global statements<a class="headerlink" href="#example-finding-redundant-global-statements" title="Link to this heading"></a></h3>
<p>The <code class="docutils literal notranslate"><span class="pre">global</span></code> statement in Python declares a variable with a global (module-level) scope, when it would otherwise be local. Using the <code class="docutils literal notranslate"><span class="pre">global</span></code> statement outside a class or function is redundant as the variable is already global.</p>
<div class="highlight-ql notranslate"><div class="highlight"><pre><span></span>import python
from Global g
where g.getScope() instanceof Module
select g
</pre></div>
</div>
<p><a class="reference external" href="https://lgtm.com/query/686330052/">See this in the query console on LGTM.com</a>. None of the demo projects on LGTM.com has a global statement that matches this pattern.</p>
<p>The line: <code class="docutils literal notranslate"><span class="pre">g.getScope()</span> <span class="pre">instanceof</span> <span class="pre">Module</span></code> ensures that the <code class="docutils literal notranslate"><span class="pre">Scope</span></code> of <code class="docutils literal notranslate"><span class="pre">Global</span> <span class="pre">g</span></code> is a <code class="docutils literal notranslate"><span class="pre">Module</span></code>, rather than a class or function.</p>
</section>
<section id="example-finding-if-statements-with-redundant-branches">
<h3>Example finding if statements with redundant branches<a class="headerlink" href="#example-finding-if-statements-with-redundant-branches" title="Link to this heading"></a></h3>
<p>An <code class="docutils literal notranslate"><span class="pre">if</span></code> statement where one branch is composed of just <code class="docutils literal notranslate"><span class="pre">pass</span></code> statements could be simplified by negating the condition and dropping the <code class="docutils literal notranslate"><span class="pre">else</span></code> clause.</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="k">if</span> <span class="n">cond</span><span class="p">():</span>
<span class="k">pass</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">do_something</span>
</pre></div>
</div>
<p>To find statements like this that could be simplified we can write a query.</p>
<div class="highlight-ql notranslate"><div class="highlight"><pre><span></span>import python
from If i, StmtList l
where (l = i.getBody() or l = i.getOrelse())
and forall(Stmt p | p = l.getAnItem() | p instanceof Pass)
select i
</pre></div>
</div>
<p><a class="reference external" href="https://lgtm.com/query/672230053/">See this in the query console on LGTM.com</a>. Many projects have some <code class="docutils literal notranslate"><span class="pre">if</span></code> statements that match this pattern.</p>
<p>The line: <code class="docutils literal notranslate"><span class="pre">(l</span> <span class="pre">=</span> <span class="pre">i.getBody()</span> <span class="pre">or</span> <span class="pre">l</span> <span class="pre">=</span> <span class="pre">i.getOrelse())</span></code> restricts the <code class="docutils literal notranslate"><span class="pre">StmtList</span> <span class="pre">l</span></code> to branches of the <code class="docutils literal notranslate"><span class="pre">if</span></code> statement.</p>
<p>The line: <code class="docutils literal notranslate"><span class="pre">forall(Stmt</span> <span class="pre">p</span> <span class="pre">|</span> <span class="pre">p</span> <span class="pre">=</span> <span class="pre">l.getAnItem()</span> <span class="pre">|</span> <span class="pre">p</span> <span class="pre">instanceof</span> <span class="pre">Pass)</span></code> ensures that all statements in <code class="docutils literal notranslate"><span class="pre">l</span></code> are <code class="docutils literal notranslate"><span class="pre">pass</span></code> statements.</p>
</section>
</section>
<section id="expressions">
<h2>Expressions<a class="headerlink" href="#expressions" title="Link to this heading"></a></h2>
<p>Each kind of Python expression has its own class. Here is the full class hierarchy:</p>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">Expr</span></code> An expression</p>
<ul>
<li><p><code class="docutils literal notranslate"><span class="pre">Attribute</span></code> An attribute, <code class="docutils literal notranslate"><span class="pre">obj.attr</span></code></p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">BinaryExpr</span></code> A binary operation, <code class="docutils literal notranslate"><span class="pre">x+y</span></code></p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">BoolExpr</span></code> Short circuit logical operations, <code class="docutils literal notranslate"><span class="pre">x</span> <span class="pre">and</span> <span class="pre">y</span></code>, <code class="docutils literal notranslate"><span class="pre">x</span> <span class="pre">or</span> <span class="pre">y</span></code></p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">Bytes</span></code> A bytes literal, <code class="docutils literal notranslate"><span class="pre">b&quot;x&quot;</span></code> or (in Python 2) <code class="docutils literal notranslate"><span class="pre">&quot;x&quot;</span></code></p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">Call</span></code> A function call, <code class="docutils literal notranslate"><span class="pre">f(arg)</span></code></p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">Compare</span></code> A comparison operation, <code class="docutils literal notranslate"><span class="pre">0</span> <span class="pre">&lt;</span> <span class="pre">x</span> <span class="pre">&lt;</span> <span class="pre">10</span></code></p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">Dict</span></code> A dictionary literal, <code class="docutils literal notranslate"><span class="pre">{'a':</span> <span class="pre">2}</span></code></p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">DictComp</span></code> A dictionary comprehension, <code class="docutils literal notranslate"><span class="pre">{k:</span> <span class="pre">v</span> <span class="pre">for</span> <span class="pre">...}</span></code></p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">Ellipsis</span></code> An ellipsis expression, <code class="docutils literal notranslate"><span class="pre">...</span></code></p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">GeneratorExp</span></code> A generator expression</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">IfExp</span></code> A conditional expression, <code class="docutils literal notranslate"><span class="pre">x</span> <span class="pre">if</span> <span class="pre">cond</span> <span class="pre">else</span> <span class="pre">y</span></code></p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">ImportExpr</span></code> An artificial expression representing the module imported</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">ImportMember</span> <span class="pre"></span> <span class="pre">A</span></code>n artificial expression representing importing a value from a module (part of an <code class="docutils literal notranslate"><span class="pre">from</span> <span class="pre">xxx</span> <span class="pre">import</span> <span class="pre">*</span></code> statement)</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">Lambda</span> <span class="pre"></span> <span class="pre">A</span> <span class="pre">lambda</span> <span class="pre">expression</span></code></p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">List</span></code> A list literal, <code class="docutils literal notranslate"><span class="pre">['a',</span> <span class="pre">'b']</span></code></p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">ListComp</span></code> A list comprehension, <code class="docutils literal notranslate"><span class="pre">[x</span> <span class="pre">for</span> <span class="pre">...]</span></code></p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">Name</span></code> A reference to a variable, <code class="docutils literal notranslate"><span class="pre">var</span></code></p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">Num</span></code> A numeric literal, <code class="docutils literal notranslate"><span class="pre">3</span></code> or <code class="docutils literal notranslate"><span class="pre">4.2</span></code></p>
<ul>
<li><p><code class="docutils literal notranslate"><span class="pre">FloatLiteral</span></code></p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">ImaginaryLiteral</span></code></p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">IntegerLiteral</span></code></p></li>
</ul>
</li>
<li><p><code class="docutils literal notranslate"><span class="pre">Repr</span></code> A backticks expression, <code class="docutils literal notranslate"><span class="pre">x</span></code> (Python 2 only)</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">Set</span></code> A set literal, <code class="docutils literal notranslate"><span class="pre">{'a',</span> <span class="pre">'b'}</span></code></p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">SetComp</span></code> A set comprehension, <code class="docutils literal notranslate"><span class="pre">{x</span> <span class="pre">for</span> <span class="pre">...}</span></code></p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">Slice</span></code> A slice; the <code class="docutils literal notranslate"><span class="pre">0:1</span></code> in the expression <code class="docutils literal notranslate"><span class="pre">seq[0:1]</span></code></p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">Starred</span></code> A starred expression, <code class="docutils literal notranslate"><span class="pre">*x</span></code> in the context of a multiple assignment: <code class="docutils literal notranslate"><span class="pre">y,</span> <span class="pre">*x</span> <span class="pre">=</span> <span class="pre">1,2,3</span></code> (Python 3 only)</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">StrConst</span></code> A string literal. In Python 2 either bytes or unicode. In Python 3 only unicode.</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">Subscript</span></code> A subscript operation, <code class="docutils literal notranslate"><span class="pre">seq[index]</span></code></p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">UnaryExpr</span></code> A unary operation, <code class="docutils literal notranslate"><span class="pre">-x</span></code></p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">Unicode</span></code> A unicode literal, <code class="docutils literal notranslate"><span class="pre">u&quot;x&quot;</span></code> or (in Python 3) <code class="docutils literal notranslate"><span class="pre">&quot;x&quot;</span></code></p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">Yield</span></code> A <code class="docutils literal notranslate"><span class="pre">yield</span></code> expression</p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">YieldFrom</span></code> A <code class="docutils literal notranslate"><span class="pre">yield</span> <span class="pre">from</span></code> expression (Python 3.3+)</p></li>
</ul>
</li>
</ul>
<section id="example-finding-comparisons-to-integer-or-string-literals-using-is">
<h3>Example finding comparisons to integer or string literals using is<a class="headerlink" href="#example-finding-comparisons-to-integer-or-string-literals-using-is" title="Link to this heading"></a></h3>
<p>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.</p>
<div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="n">x</span> <span class="ow">is</span> <span class="mi">10</span>
<span class="n">x</span> <span class="ow">is</span> <span class="s2">&quot;A&quot;</span>
</pre></div>
</div>
<p>We can check for these using a query.</p>
<div class="highlight-ql notranslate"><div class="highlight"><pre><span></span>import python
from Compare cmp, Expr literal
where (literal instanceof StrConst or literal instanceof Num)
and cmp.getOp(0) instanceof Is and cmp.getComparator(0) = literal
select cmp
</pre></div>
</div>
<p><a class="reference external" href="https://lgtm.com/query/688180010/">See this in the query console on LGTM.com</a>. Two of the demo projects on LGTM.com use this pattern: <em>saltstack/salt</em> and <em>openstack/nova</em>.</p>
<p>The clause <code class="docutils literal notranslate"><span class="pre">cmp.getOp(0)</span> <span class="pre">instanceof</span> <span class="pre">Is</span> <span class="pre">and</span> <span class="pre">cmp.getComparator(0)</span> <span class="pre">=</span> <span class="pre">literal</span></code> checks that the first comparison operator is “is” and that the first comparator is a literal.</p>
<blockquote class="pull-quote">
<div><p>Tip</p>
<p>We have to use <code class="docutils literal notranslate"><span class="pre">cmp.getOp(0)</span></code> and <code class="docutils literal notranslate"><span class="pre">cmp.getComparator(0)</span></code>as there is no <code class="docutils literal notranslate"><span class="pre">cmp.getOp()</span></code> or <code class="docutils literal notranslate"><span class="pre">cmp.getComparator()</span></code>. The reason for this is that a <code class="docutils literal notranslate"><span class="pre">Compare</span></code> expression can have multiple operators. For example, the expression <code class="docutils literal notranslate"><span class="pre">3</span> <span class="pre">&lt;</span> <span class="pre">x</span> <span class="pre">&lt;</span> <span class="pre">7</span></code> has two operators and two comparators. You use <code class="docutils literal notranslate"><span class="pre">cmp.getComparator(0)</span></code> to get the first comparator (in this example the <code class="docutils literal notranslate"><span class="pre">x</span></code>) and <code class="docutils literal notranslate"><span class="pre">cmp.getComparator(1)</span></code> to get the second comparator (in this example the <code class="docutils literal notranslate"><span class="pre">7</span></code>).</p>
</div></blockquote>
</section>
<section id="example-finding-duplicates-in-dictionary-literals">
<h3>Example finding duplicates in dictionary literals<a class="headerlink" href="#example-finding-duplicates-in-dictionary-literals" title="Link to this heading"></a></h3>
<p>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 <code class="docutils literal notranslate"><span class="pre">predicate</span></code> as a helper.</p>
<div class="highlight-ql notranslate"><div class="highlight"><pre><span></span>import python
predicate same_key(Expr k1, Expr k2) {
k1.(Num).getN() = k2.(Num).getN()
or
k1.(StrConst).getText() = k2.(StrConst).getText()
}
from Dict d, Expr k1, Expr k2
where k1 = d.getAKey() and k2 = d.getAKey()
and k1 != k2 and same_key(k1, k2)
select k1, &quot;Duplicate key in dict literal&quot;
</pre></div>
</div>
<p><a class="reference external" href="https://lgtm.com/query/663330305/">See this in the query console on LGTM.com</a>. When we ran this query on LGTM.com, the source code of the <em>saltstack/salt</em> 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 <a class="reference external" href="https://lgtm.com/rules/3980087">Duplicate key in dict literal</a> on LGTM.com.</p>
<p>The supporting predicate <code class="docutils literal notranslate"><span class="pre">same_key</span></code> 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:</p>
<div class="highlight-ql notranslate"><div class="highlight"><pre><span></span>x = k1.(Num).getN()
</pre></div>
</div>
<p>is equivalent to</p>
<div class="highlight-ql notranslate"><div class="highlight"><pre><span></span>exists(Num num | num = k1 | x = num.getN())
</pre></div>
</div>
<p>The short version is usually used as this is easier to read.</p>
</section>
<section id="example-finding-java-style-getters">
<h3>Example finding Java-style getters<a class="headerlink" href="#example-finding-java-style-getters" title="Link to this heading"></a></h3>
<p>Returning to the example from “<a class="reference internal" href="functions-in-python.html"><span class="doc">Functions in Python</span></a>,” the query identified all methods with a single line of code and a name starting with <code class="docutils literal notranslate"><span class="pre">get</span></code>.</p>
<div class="highlight-ql notranslate"><div class="highlight"><pre><span></span>import python
from Function f
where f.getName().matches(&quot;get%&quot;) and f.isMethod()
and count(f.getAStmt()) = 1
select f, &quot;This function is (probably) a getter.&quot;
</pre></div>
</div>
<p>This basic query can be improved by checking that the one line of code is a Java-style getter of the form <code class="docutils literal notranslate"><span class="pre">return</span> <span class="pre">self.attr</span></code>.</p>
<div class="highlight-ql notranslate"><div class="highlight"><pre><span></span>import python
from Function f, Return ret, Attribute attr, Name self
where f.getName().matches(&quot;get%&quot;) and f.isMethod()
and ret = f.getStmt(0) and ret.getValue() = attr
and attr.getObject() = self and self.getId() = &quot;self&quot;
select f, &quot;This function is a Java-style getter.&quot;
</pre></div>
</div>
<p><a class="reference external" href="https://lgtm.com/query/669220054/">See this in the query console on LGTM.com</a>. Of the demo projects on LGTM.com, only the <em>openstack/nova</em> project has examples of functions that appear to be Java-style getters.</p>
<div class="highlight-ql notranslate"><div class="highlight"><pre><span></span>ret = f.getStmt(0) and ret.getValue() = attr
</pre></div>
</div>
<p>This condition checks that the first line in the method is a return statement and that the expression returned (<code class="docutils literal notranslate"><span class="pre">ret.getValue()</span></code>) is an <code class="docutils literal notranslate"><span class="pre">Attribute</span></code> expression. Note that the equality <code class="docutils literal notranslate"><span class="pre">ret.getValue()</span> <span class="pre">=</span> <span class="pre">attr</span></code> means that <code class="docutils literal notranslate"><span class="pre">ret.getValue()</span></code> is restricted to <code class="docutils literal notranslate"><span class="pre">Attribute</span></code>s, since <code class="docutils literal notranslate"><span class="pre">attr</span></code> is an <code class="docutils literal notranslate"><span class="pre">Attribute</span></code>.</p>
<div class="highlight-ql notranslate"><div class="highlight"><pre><span></span>attr.getObject() = self and self.getId() = &quot;self&quot;
</pre></div>
</div>
<p>This condition checks that the value of the attribute (the expression to the left of the dot in <code class="docutils literal notranslate"><span class="pre">value.attr</span></code>) is an access to a variable called <code class="docutils literal notranslate"><span class="pre">&quot;self&quot;</span></code>.</p>
</section>
</section>
<section id="class-and-function-definitions">
<h2>Class and function definitions<a class="headerlink" href="#class-and-function-definitions" title="Link to this heading"></a></h2>
<p>As Python is a dynamically typed language, class, and function definitions are executable statements. This means that a class statement is both a statement and a scope containing statements. To represent this cleanly the class definition is broken into a number of parts. At runtime, when a class definition is executed a class object is created and then assigned to a variable of the same name in the scope enclosing the class. This class is created from a code-object representing the source code for the body of the class. To represent this the <code class="docutils literal notranslate"><span class="pre">ClassDef</span></code> class (which represents a <code class="docutils literal notranslate"><span class="pre">class</span></code> statement) subclasses <code class="docutils literal notranslate"><span class="pre">Assign</span></code>. The <code class="docutils literal notranslate"><span class="pre">Class</span></code> class, which represents the body of the class, can be accessed via the <code class="docutils literal notranslate"><span class="pre">ClassDef.getDefinedClass()</span></code>. <code class="docutils literal notranslate"><span class="pre">FunctionDef</span></code> and <code class="docutils literal notranslate"><span class="pre">Function</span></code> are handled similarly.</p>
<p>Here is the relevant part of the class hierarchy:</p>
<ul class="simple">
<li><p><code class="docutils literal notranslate"><span class="pre">Stmt</span></code></p>
<ul>
<li><p><code class="docutils literal notranslate"><span class="pre">Assign</span></code></p>
<ul>
<li><p><code class="docutils literal notranslate"><span class="pre">ClassDef</span></code></p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">FunctionDef</span></code></p></li>
</ul>
</li>
</ul>
</li>
<li><p><code class="docutils literal notranslate"><span class="pre">Scope</span></code></p>
<ul>
<li><p><code class="docutils literal notranslate"><span class="pre">Class</span></code></p></li>
<li><p><code class="docutils literal notranslate"><span class="pre">Function</span></code></p></li>
</ul>
</li>
</ul>
</section>
<section id="further-reading">
<h2>Further reading<a class="headerlink" href="#further-reading" title="Link to this heading"></a></h2>
<ul class="simple">
<li><p><a class="reference external" href="https://github.com/github/codeql/tree/main/python/ql/src">CodeQL queries for Python</a></p></li>
<li><p><a class="reference external" href="https://github.com/github/codeql/tree/main/python/ql/examples">Example queries for Python</a></p></li>
<li><p><a class="reference external" href="https://codeql.github.com/codeql-standard-libraries/python/">CodeQL library reference for Python</a></p></li>
</ul>
<ul class="simple">
<li><p><a class="reference internal" href="../ql-language-reference/index.html#ql-language-reference"><span class="std std-ref">QL language reference</span></a></p></li>
<li><p><a class="reference internal" href="../codeql-overview/codeql-tools.html#codeql-tools"><span class="std std-ref">CodeQL tools</span></a></p></li>
</ul>
</section>
</section>
</article>
<!-- GitHub footer, with links to terms and privacy statement -->
<div class="px-3 px-md-6 f6 py-4 d-sm-flex flex-justify-between flex-row-reverse flex-items-center border-top">
<ul class="list-style-none d-flex flex-items-center mb-3 mb-sm-0 lh-condensed-ultra">
<li class="mr-3">
<a href="https://twitter.com/github" title="GitHub on Twitter" style="color: #959da5;">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 273.5 222.3" class="d-block" height="18">
<path
d="M273.5 26.3a109.77 109.77 0 0 1-32.2 8.8 56.07 56.07 0 0 0 24.7-31 113.39 113.39 0 0 1-35.7 13.6 56.1 56.1 0 0 0-97 38.4 54 54 0 0 0 1.5 12.8A159.68 159.68 0 0 1 19.1 10.3a56.12 56.12 0 0 0 17.4 74.9 56.06 56.06 0 0 1-25.4-7v.7a56.11 56.11 0 0 0 45 55 55.65 55.65 0 0 1-14.8 2 62.39 62.39 0 0 1-10.6-1 56.24 56.24 0 0 0 52.4 39 112.87 112.87 0 0 1-69.7 24 119 119 0 0 1-13.4-.8 158.83 158.83 0 0 0 86 25.2c103.2 0 159.6-85.5 159.6-159.6 0-2.4-.1-4.9-.2-7.3a114.25 114.25 0 0 0 28.1-29.1"
fill="currentColor"></path>
</svg>
</a>
</li>
<li class="mr-3">
<a href="https://www.facebook.com/GitHub" title="GitHub on Facebook" style="color: #959da5;">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 15.3 15.4" class="d-block" height="18">
<path
d="M14.5 0H.8a.88.88 0 0 0-.8.9v13.6a.88.88 0 0 0 .8.9h7.3v-6h-2V7.1h2V5.4a2.87 2.87 0 0 1 2.5-3.1h.5a10.87 10.87 0 0 1 1.8.1v2.1h-1.3c-1 0-1.1.5-1.1 1.1v1.5h2.3l-.3 2.3h-2v5.9h3.9a.88.88 0 0 0 .9-.8V.8a.86.86 0 0 0-.8-.8z"
fill="currentColor"></path>
</svg>
</a>
</li>
<li class="mr-3">
<a href="https://www.youtube.com/github" title="GitHub on YouTube" style="color: #959da5;">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 19.17 13.6" class="d-block" height="16">
<path
d="M18.77 2.13A2.4 2.4 0 0 0 17.09.42C15.59 0 9.58 0 9.58 0a57.55 57.55 0 0 0-7.5.4A2.49 2.49 0 0 0 .39 2.13 26.27 26.27 0 0 0 0 6.8a26.15 26.15 0 0 0 .39 4.67 2.43 2.43 0 0 0 1.69 1.71c1.52.42 7.5.42 7.5.42a57.69 57.69 0 0 0 7.51-.4 2.4 2.4 0 0 0 1.68-1.71 25.63 25.63 0 0 0 .4-4.67 24 24 0 0 0-.4-4.69zM7.67 9.71V3.89l5 2.91z"
fill="currentColor"></path>
</svg>
</a>
</li>
<li class="mr-3 flex-self-start">
<a href="https://www.linkedin.com/company/github" title="GitHub on Linkedin" style="color: #959da5;">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 19 18" class="d-block" height="18">
<path
d="M3.94 2A2 2 0 1 1 2 0a2 2 0 0 1 1.94 2zM4 5.48H0V18h4zm6.32 0H6.34V18h3.94v-6.57c0-3.66 4.77-4 4.77 0V18H19v-7.93c0-6.17-7.06-5.94-8.72-2.91z"
fill="currentColor"></path>
</svg>
</a>
</li>
<li>
<a href="https://github.com/github" title="GitHub's organization" style="color: #959da5;">
<svg version="1.1" width="20" height="20" viewBox="0 0 16 16" class="octicon octicon-mark-github"
aria-hidden="true">
<path fill-rule="evenodd"
d="M8 0C3.58 0 0 3.58 0 8c0 3.54 2.29 6.53 5.47 7.59.4.07.55-.17.55-.38 0-.19-.01-.82-.01-1.49-2.01.37-2.53-.49-2.69-.94-.09-.23-.48-.94-.82-1.13-.28-.15-.68-.52-.01-.53.63-.01 1.08.58 1.23.82.72 1.21 1.87.87 2.33.66.07-.52.28-.87.51-1.07-1.78-.2-3.64-.89-3.64-3.95 0-.87.31-1.59.82-2.15-.08-.2-.36-1.02.08-2.12 0 0 .67-.21 2.2.82.64-.18 1.32-.27 2-.27.68 0 1.36.09 2 .27 1.53-1.04 2.2-.82 2.2-.82.44 1.1.16 1.92.08 2.12.51.56.82 1.27.82 2.15 0 3.07-1.87 3.75-3.65 3.95.29.25.54.73.54 1.48 0 1.07-.01 1.93-.01 2.2 0 .21.15.46.55.38A8.013 8.013 0 0016 8c0-4.42-3.58-8-8-8z">
</path>
</svg>
</a>
</li>
</ul>
<ul class="list-style-none d-flex text-gray">
<li class="mr-3">&copy;
<script type="text/javascript">document.write(new Date().getFullYear());</script> GitHub, Inc.</li>
<li class="mr-3"><a
href="https://docs.github.com/github/site-policy/github-terms-of-service"
class="link-gray">Terms </a></li>
<li><a href="https://docs.github.com/github/site-policy/github-privacy-statement"
class="link-gray">Privacy </a></li>
</ul>
</div>
</div>
</main>
<script type="text/javascript">
$(document).ready(function () {
$(".toggle > *").hide();
$(".toggle .name").show();
$(".toggle .name").click(function () {
$(this).parent().children().not(".name").toggle(400);
$(this).parent().children(".name").toggleClass("open");
})
});
</script>
</body>
</html>