Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
131 changes: 131 additions & 0 deletions docs/codeql/codeql-language-guides/basic-query-for-rust-code.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
.. _basic-query-for-rust-code:

Basic query for Rust code
==========================

Learn to write and run a simple CodeQL query using Visual Studio Code with the CodeQL extension.

.. include:: ../reusables/vs-code-basic-instructions/setup-to-run-queries.rst

About the query
---------------

The query we're going to run performs a basic search of the code for ``if`` expressions that are redundant, in the sense that they have an empty ``then`` branch. For example, code such as:

.. code-block:: rust

if error {
// we should handle the error
}

.. include:: ../reusables/vs-code-basic-instructions/find-database.rst

Running a quick query
---------------------

.. include:: ../reusables/vs-code-basic-instructions/run-quick-query-1.rst

#. In the quick query tab, delete the content and paste in the following query.

.. code-block:: ql

import rust

from IfExpr ifExpr
where ifExpr.getThen().(BlockExpr).getStmtList().getNumberOfStmtOrExpr() = 0
select ifExpr, "This 'if' expression is redundant."

.. include:: ../reusables/vs-code-basic-instructions/run-quick-query-2.rst

.. image:: ../images/codeql-for-visual-studio-code/basic-rust-query-results-1.png
:align: center

If any matching code is found, click a link in the ``ifExpr`` column to open the file and highlight the matching ``if`` expression.

.. image:: ../images/codeql-for-visual-studio-code/basic-rust-query-results-2.png
:align: center

.. include:: ../reusables/vs-code-basic-instructions/note-store-quick-query.rst

About the query structure
~~~~~~~~~~~~~~~~~~~~~~~~~

After the initial ``import`` statement, this simple query comprises three parts that serve similar purposes to the FROM, WHERE, and SELECT parts of an SQL query.

+----------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------+
| Query part | Purpose | Details |
+==================================================================================+===================================================================================================================+======================================================================================================+
| ``import rust`` | Imports the standard CodeQL AST libraries for Rust. | Every query begins with one or more ``import`` statements. |
+----------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------+
| ``from IfExpr ifExpr`` | Defines the variables for the query. | We use: an ``IfExpr`` variable for ``if`` expressions. |
| | Declarations are of the form: | |
| | ``<type> <variable name>`` | |
+----------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------+
| ``where ifExpr.getThen().(BlockExpr).getStmtList().getNumberOfStmtOrExpr() = 0`` | Defines a condition on the variables. | ``ifExpr.getThen()``: gets the ``then`` branch of the ``if`` expression. |
| | | ``.(BlockExpr)``: requires that the ``then`` branch is a block expression (``{ }``). |
| | | ``.getStmtList()``: gets the list of things in the block. |
| | | ``.getNumberOfStmtOrExpr() = 0``: requires that there are no statements or expressions in the block. |
+----------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------+
| ``select ifExpr, "This 'if' expression is redundant."`` | Defines what to report for each match. | Reports the resulting ``if`` expression with a string that explains the problem. |
Copy link
Preview

Copilot AI Sep 30, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The error message refers to 'if' expression, but line 36 uses 'if' statement. The terminology should be consistent - use 'if' expression in both places since Rust treats if as an expression.

Copilot uses AI. Check for mistakes.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right, though it's line 36 that should be updated - they're if "expressions" in Rust.

Updated the doc.

I'll need to re-create the screenshots as well, but lets wait and see if any other changes are suggested first...

| | | |
| | ``select`` statements for queries that are used to find instances of poor coding practice are always in the form: | |
| | ``select <program element>, "<alert message>"`` | |
+----------------------------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------+

Extend the query
----------------

Query writing is an inherently iterative process. You write a simple query and then, when you run it, you discover examples that you had not previously considered, or opportunities for improvement.

Remove false positive results
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Browsing the results of our basic query shows that it could be improved. Among the results you are likely to find examples of ``if`` expressions with an ``else`` branch, where an empty ``then`` branch does serve a purpose. For example:

.. code-block:: rust

if (option == "-verbose") {
// nothing to do - handled earlier
} else {
handleError("unrecognized option")
}

In this case, identifying the ``if`` expression with the empty ``then`` branch as redundant is a false positive. One solution to this is to modify the query to select ``if`` expressions where both the ``then`` and ``else`` branches are missing.

To exclude ``if`` expressions that have an ``else`` branch:

#. Add the following to the where clause:

.. code-block:: ql

and not exists(ifExpr.getElse())

The ``where`` clause is now:

.. code-block:: ql

where
ifExpr.getThen().(BlockExpr).getStmtList().getNumberOfStmtOrExpr() = 0 and
not exists(ifExpr.getElse())

#. Re-run the query.

There are now fewer results because ``if`` expressions with an ``else`` branch are no longer included.

Further reading
---------------

.. include:: ../reusables/rust-further-reading.rst
.. include:: ../reusables/codeql-ref-tools-further-reading.rst

.. Article-specific substitutions for the reusables used in docs/codeql/reusables/vs-code-basic-instructions

.. |language-text| replace:: Rust

.. |language-code| replace:: ``rust``

.. |example-url| replace:: https://github.com/rust-lang/rustlings

.. |image-quick-query| image:: ../images/codeql-for-visual-studio-code/quick-query-tab-rust.png

.. |result-col-1| replace:: The first column corresponds to the expression ``ifExpr`` and is linked to the location in the source code of the project where ``ifExpr`` occurs.
4 changes: 4 additions & 0 deletions docs/codeql/codeql-language-guides/codeql-for-rust.rst
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,12 @@ Experiment and learn how to write effective and efficient queries for CodeQL dat
.. toctree::
:hidden:

basic-query-for-rust-code
codeql-library-for-rust
analyzing-data-flow-in-rust

- :doc:`Basic query for Rust code <basic-query-for-rust-code>`: Learn to write and run a simple CodeQL query.

- :doc:`CodeQL library for Rust <codeql-library-for-rust>`: When analyzing Rust code, you can make use of the large collection of classes in the CodeQL library for Rust.

- :doc:`Analyzing data flow in Rust <analyzing-data-flow-in-rust>`: You can use CodeQL to track the flow of data through a Rust program to places where the data is used.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.