mirror of
https://github.com/github/codeql.git
synced 2025-12-16 16:53:25 +01:00
Rust: apply suggestions from code review
Co-authored-by: Sunbrye Ly <56200261+sunbrye@users.noreply.github.com>
This commit is contained in:
@@ -17,7 +17,7 @@ For a more general introduction to modeling data flow, see ":ref:`About data flo
|
||||
Local data flow
|
||||
---------------
|
||||
|
||||
Local data flow tracks the flow of data within a single method or callable. Local data flow is easier, faster, and more precise than global data flow. Before looking at more complex tracking, you should always consider local tracking because it is sufficient for many queries.
|
||||
Local data flow tracks the flow of data within a single method or callable. Local data flow is easier, faster, and more precise than global data flow. Before using more complex tracking, consider local tracking, as it is sufficient for many queries.
|
||||
|
||||
Using local data flow
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
@@ -43,13 +43,11 @@ Similarly, you can map a data flow ``ParameterNode`` to its corresponding ``Para
|
||||
...
|
||||
}
|
||||
|
||||
|
||||
Note that since ``asExpr`` maps from data-flow to control-flow nodes, you then need to call the ``getExpr`` member predicate on the control-flow node to map to the corresponding AST node,
|
||||
for example by writing ``node.asExpr().getExpr()``.
|
||||
Note that because ``asExpr`` maps from data-flow to control-flow nodes, you need to call the ``getExpr`` member predicate on the control-flow node to map to the corresponding AST node. For example, you can write ``node.asExpr().getExpr()``.
|
||||
A control-flow graph considers every way control can flow through code, consequently, there can be multiple data-flow and control-flow nodes associated with a single expression node in the AST.
|
||||
|
||||
The predicate ``localFlowStep(Node nodeFrom, Node nodeTo)`` holds if there is an immediate data flow edge from the node ``nodeFrom`` to the node ``nodeTo``.
|
||||
You can apply the predicate recursively, by using the ``+`` and ``*`` operators, or you can use the predefined recursive predicate ``localFlow``.
|
||||
You can apply the predicate recursively by using the ``+`` and ``*`` operators, or you can use the predefined recursive predicate ``localFlow``.
|
||||
|
||||
For example, you can find flow from an expression ``source`` to an expression ``sink`` in zero or more local steps:
|
||||
|
||||
@@ -71,7 +69,7 @@ If ``x`` is a tainted string then ``y`` is also tainted.
|
||||
|
||||
The local taint tracking library is in the module ``TaintTracking``.
|
||||
Like local data flow, a predicate ``localTaintStep(DataFlow::Node nodeFrom, DataFlow::Node nodeTo)`` holds if there is an immediate taint propagation edge from the node ``nodeFrom`` to the node ``nodeTo``.
|
||||
You can apply the predicate recursively, by using the ``+`` and ``*`` operators, or you can use the predefined recursive predicate ``localTaint``.
|
||||
You can apply the predicate recursively by using the ``+`` and ``*`` operators, or you can use the predefined recursive predicate ``localTaint``.
|
||||
|
||||
For example, you can find taint propagation from an expression ``source`` to an expression ``sink`` in zero or more local steps:
|
||||
|
||||
@@ -83,14 +81,14 @@ For example, you can find taint propagation from an expression ``source`` to an
|
||||
Using local sources
|
||||
~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
When exploring local data flow or taint propagation between two expressions as above, you would normally constrain the expressions to be relevant to your investigation.
|
||||
The next section gives some concrete examples, but first it's helpful to introduce the concept of a local source.
|
||||
When exploring local data flow or taint propagation between two expressions, such as in the previous example, you typically constrain the expressions to those relevant to your investigation.
|
||||
The next section provides concrete examples, but first introduces the concept of a local source.
|
||||
|
||||
A local source is a data-flow node with no local data flow into it.
|
||||
As such, it is a local origin of data flow, a place where a new value is created.
|
||||
It is a local origin of data flow, a place where a new value is created.
|
||||
This includes parameters (which only receive values from global data flow) and most expressions (because they are not value-preserving).
|
||||
The class ``LocalSourceNode`` represents data-flow nodes that are also local sources.
|
||||
It comes with a useful member predicate ``flowsTo(DataFlow::Node node)``, which holds if there is local data flow from the local source to ``node``.
|
||||
It includes a useful member predicate ``flowsTo(DataFlow::Node node)``, which holds if there is local data flow from the local source to ``node``.
|
||||
|
||||
Examples of local data flow
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
@@ -105,8 +103,7 @@ This query finds the argument passed in each call to ``File::create``:
|
||||
where call.getStaticTarget().(Function).getCanonicalPath() = "<std::fs::File>::create"
|
||||
select call.getArg(0)
|
||||
|
||||
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:
|
||||
Unfortunately, this only returns the expression used as the argument, not the possible values that could be passed to it. To address this, you can use local data flow to find all expressions that flow into the argument.
|
||||
|
||||
.. code-block:: ql
|
||||
|
||||
@@ -120,7 +117,7 @@ So we use local data flow to find all expressions that flow into the argument:
|
||||
DataFlow::localFlow(source, sink)
|
||||
select source, sink
|
||||
|
||||
We can vary the source, for example, making the source the parameter of a function rather than an expression. The following query finds where a parameter is used for the file creation:
|
||||
You can vary the source by making the source the parameter of a function instead of an expression. The following query finds where a parameter is used in file creation:
|
||||
|
||||
.. code-block:: ql
|
||||
|
||||
@@ -183,8 +180,8 @@ The last line (``module MyDataFlow = ...``) instantiates the parameterized modul
|
||||
Using global taint tracking
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Global taint tracking is to global data flow what local taint tracking is to local data flow.
|
||||
That is, global taint tracking extends global data flow with additional non-value-preserving steps.
|
||||
Global taint tracking relates to global data flow in the same way that local taint tracking relates to local data flow.
|
||||
In other words, global taint tracking extends global data flow with additional non-value-preserving steps.
|
||||
The global taint tracking library uses the same configuration module as the global data flow library. You can perform taint flow analysis using ``TaintTracking::Global``:
|
||||
|
||||
.. code-block:: ql
|
||||
@@ -207,7 +204,7 @@ The following global taint-tracking query finds places where a string literal is
|
||||
- Since this is a taint-tracking query, the ``TaintTracking::Global`` module is used.
|
||||
- The ``isSource`` predicate defines sources as any ``StringLiteralExpr``.
|
||||
- The ``isSink`` predicate defines sinks as arguments to a ``CallExpr`` called "password".
|
||||
- The sources and sinks may need tuning to a particular use, for example, if passwords are represented by a type other than ``String`` or passed in arguments of a different name than "password".
|
||||
- The sources and sinks may need to be adjusted for a particular use. For example, passwords might be represented by a type other than ``String`` or passed in arguments with a different name than "password".
|
||||
|
||||
.. code-block:: ql
|
||||
|
||||
|
||||
@@ -12,5 +12,5 @@ Experiment and learn how to write effective and efficient queries for CodeQL dat
|
||||
codeql-library-for-rust
|
||||
analyzing-data-flow-in-rust
|
||||
|
||||
- :doc:`CodeQL library for Rust <codeql-library-for-rust>`: When you're analyzing Rust code, you can make use of the large collection of classes in the CodeQL library for Rust.
|
||||
- :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.
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
CodeQL library for Rust
|
||||
=================================
|
||||
|
||||
When you're analyzing Rust code, you can make use of the large collection of classes in the CodeQL library for Rust.
|
||||
When analyzing Rust code, you can make use of the large collection of classes in the CodeQL library for Rust.
|
||||
|
||||
Overview
|
||||
--------
|
||||
@@ -11,7 +11,7 @@ Overview
|
||||
CodeQL ships with a library for analyzing Rust code. The classes in this library present the data from a CodeQL database in an object-oriented form and provide
|
||||
abstractions and predicates to help you with common analysis tasks.
|
||||
|
||||
The library is implemented as a set of CodeQL modules, that is, files with the extension ``.qll``. The
|
||||
The library is implemented as a set of CodeQL modules, which are files with the extension ``.qll``. The
|
||||
module `rust.qll <https://github.com/github/codeql/blob/main/rust/ql/lib/rust.qll>`__ imports most other standard library modules, so you can include them
|
||||
by beginning your query with:
|
||||
|
||||
@@ -20,27 +20,27 @@ by beginning your query with:
|
||||
import rust
|
||||
|
||||
The CodeQL libraries model various aspects of Rust code. The above import includes the abstract syntax tree (AST) library, which is used for locating program elements
|
||||
to match syntactic elements in the source code. This can be used for example to find values, patterns and structures.
|
||||
to match syntactic elements in the source code. This can be used to find values, patterns, and structures.
|
||||
|
||||
The control flow graph (CFG) is imported using
|
||||
The control flow graph (CFG) is imported using:
|
||||
|
||||
.. code-block:: ql
|
||||
|
||||
import codeql.rust.controlflow.ControlFlowGraph
|
||||
|
||||
The CFG models the control flow between statements and expressions, for example whether one expression can
|
||||
The CFG models the control flow between statements and expressions. For example, it can determine whether one expression can
|
||||
be evaluated before another expression, or whether an expression "dominates" another one, meaning that all paths to an
|
||||
expression must flow through another expression first.
|
||||
|
||||
The data flow library is imported using
|
||||
The data flow library is imported using:
|
||||
|
||||
.. code-block:: ql
|
||||
|
||||
import codeql.rust.dataflow.DataFlow
|
||||
|
||||
Data flow tracks the flow of data through the program, including through function calls (interprocedural data flow) and between steps in a job or workflow.
|
||||
Data flow is particularly useful for security queries, where untrusted data flows to vulnerable parts of the program. Related to data flow is the taint-tracking library,
|
||||
which finds how data can *influence* other values in a program, even when it is not copied exactly.
|
||||
Data flow tracks the flow of data through the program, including across function calls (interprocedural data flow) and between steps in a job or workflow.
|
||||
Data flow is particularly useful for security queries, where untrusted data flows to vulnerable parts of the program. The taint-tracking library is related to data flow,
|
||||
and helps you find how data can *influence* other values in a program, even when it is not copied exactly.
|
||||
|
||||
To summarize, the main Rust library modules are:
|
||||
|
||||
|
||||
Reference in New Issue
Block a user