mirror of
https://github.com/github/codeql.git
synced 2026-01-07 19:50:22 +01:00
Fix code block in other CodeQL docs
This commit is contained in:
@@ -108,8 +108,8 @@ Count the number of lines of code, excluding the directory ``external``:
|
||||
.. code-block:: ql
|
||||
|
||||
select sum(SourceFile f |
|
||||
not exists(Folder external | external.getShortName() = "external" |
|
||||
external.getAFolder*().getAFile() = f) |
|
||||
not exists(Folder ext | ext.getShortName() = "external" |
|
||||
ext.getAFolder*().getAFile() = f) |
|
||||
f.getNumberOfLines())
|
||||
|
||||
Exercises
|
||||
@@ -961,7 +961,7 @@ Find all obsolete elements:
|
||||
|
||||
Model NUnit test fixtures:
|
||||
|
||||
.. code-block:: csharp
|
||||
.. code-block:: ql
|
||||
|
||||
class TestFixture extends Class
|
||||
{
|
||||
|
||||
@@ -21,7 +21,9 @@ For more information on how to format your code when contributing queries to the
|
||||
Basic query structure
|
||||
*********************
|
||||
|
||||
:ref:`Queries <queries>` written with CodeQL have the file extension ``.ql``, and contain a ``select`` clause. Many of the existing queries include additional optional information, and have the following structure::
|
||||
:ref:`Queries <queries>` written with CodeQL have the file extension ``.ql``, and contain a ``select`` clause. Many of the existing queries include additional optional information, and have the following structure:
|
||||
|
||||
.. code-block:: ql
|
||||
|
||||
/**
|
||||
*
|
||||
|
||||
@@ -44,7 +44,9 @@ Constructing a path query
|
||||
Path queries require certain metadata, query predicates, and ``select`` statement structures.
|
||||
Many of the built-in path queries included in CodeQL follow a simple structure, which depends on how the language you are analyzing is modeled with CodeQL.
|
||||
|
||||
For C/C++, C#, Java, and JavaScript you should use the following template::
|
||||
For C/C++, C#, Java, and JavaScript you should use the following template:
|
||||
|
||||
.. code-block:: ql
|
||||
|
||||
/**
|
||||
* ...
|
||||
@@ -66,7 +68,9 @@ Where:
|
||||
- ``source`` and ``sink`` are nodes on the `path graph <https://en.wikipedia.org/wiki/Path_graph>`__, and ``DataFlow::PathNode`` is their type.
|
||||
- ``Configuration`` is a class containing the predicates which define how data may flow between the ``source`` and the ``sink``.
|
||||
|
||||
For Python you should use a slightly different template::
|
||||
For Python you should use a slightly different template:
|
||||
|
||||
.. code-block:: ql
|
||||
|
||||
/**
|
||||
* ...
|
||||
@@ -104,13 +108,17 @@ To do this you need to define a :ref:`query predicate <query-predicates>` called
|
||||
This predicate defines the edge relations of the graph you are computing, and it is used to compute the paths related to each result that your query generates.
|
||||
You can import a predefined ``edges`` predicate from a path graph module in one of the standard data flow libraries. In addition to the path graph module, the data flow libraries contain the other ``classes``, ``predicates``, and ``modules`` that are commonly used in data flow analysis. The import statement to use depends on the language that you are analyzing.
|
||||
|
||||
For C/C++, C#, Java, and JavaScript you would use::
|
||||
For C/C++, C#, Java, and JavaScript you would use:
|
||||
|
||||
.. code-block:: ql
|
||||
|
||||
import DataFlow::PathGraph
|
||||
|
||||
This statement imports the ``PathGraph`` module from the data flow library (``DataFlow.qll``), in which ``edges`` is defined.
|
||||
|
||||
For Python, the ``Paths`` module contains the ``edges`` predicate::
|
||||
For Python, the ``Paths`` module contains the ``edges`` predicate:
|
||||
|
||||
.. code-block:: ql
|
||||
|
||||
import semmle.python.security.Paths
|
||||
|
||||
@@ -121,7 +129,9 @@ For all languages, you can also optionally define a ``nodes`` query predicate, w
|
||||
Defining your own ``edges`` predicate
|
||||
-------------------------------------
|
||||
|
||||
You can also define your own ``edges`` predicate in the body of your query. It should take the following form::
|
||||
You can also define your own ``edges`` predicate in the body of your query. It should take the following form:
|
||||
|
||||
.. code-block:: ql
|
||||
|
||||
query predicate edges(PathNode a, PathNode b) {
|
||||
/** Logical conditions which hold if `(a,b)` is an edge in the data flow graph */
|
||||
@@ -136,7 +146,9 @@ You must provide information about the ``source`` and ``sink`` in your path quer
|
||||
The name and the type of the ``source`` and the ``sink`` must be declared in the ``from`` statement of the query, and the types must be compatible with the nodes of the graph computed by the ``edges`` predicate.
|
||||
|
||||
If you are querying C/C++, C#, Java, or JavaScript code (and you have used ``import DataFlow::PathGraph`` in your query), the definitions of the ``source`` and ``sink`` are accessed via the ``Configuration`` class in the data flow library. You should declare all three of these objects in the ``from`` statement.
|
||||
For example::
|
||||
For example:
|
||||
|
||||
.. code-block:: ql
|
||||
|
||||
from Configuration config, DataFlow::PathNode source, DataFlow::PathNode sink
|
||||
|
||||
@@ -149,7 +161,9 @@ For more information on using the configuration class in your analysis see the s
|
||||
|
||||
You can also create a configuration for different frameworks and environments by extending the ``Configuration`` class. For more information, see ":ref:`Types <defining-a-class>`" in the QL language reference.
|
||||
|
||||
If you are querying Python code (and you have used ``import semmle.python.security.Paths`` in your query) you should declare ``TaintedPathSource source, TaintedPathSink sink`` in your ``from`` statement. You do not need to declare a ``Configuration`` class as the definitions of the ``TaintedPathSource`` and ``TaintedPathSink`` contain all of the type information that is required::
|
||||
If you are querying Python code (and you have used ``import semmle.python.security.Paths`` in your query) you should declare ``TaintedPathSource source, TaintedPathSink sink`` in your ``from`` statement. You do not need to declare a ``Configuration`` class as the definitions of the ``TaintedPathSource`` and ``TaintedPathSink`` contain all of the type information that is required:
|
||||
|
||||
.. code-block:: ql
|
||||
|
||||
from TaintedPathSource source, TaintedPathSink sink
|
||||
|
||||
@@ -163,11 +177,15 @@ This clause can use :ref:`aggregations <aggregations>`, :ref:`predicates <predic
|
||||
|
||||
When writing a path queries, you would typically include a predicate that holds only if data flows from the ``source`` to the ``sink``.
|
||||
|
||||
For C/C++, C#, Java or JavaScript, you would use the ``hasFlowPath`` predicate to define flow from the ``source`` to the ``sink`` for a given ``Configuration``::
|
||||
For C/C++, C#, Java or JavaScript, you would use the ``hasFlowPath`` predicate to define flow from the ``source`` to the ``sink`` for a given ``Configuration``:
|
||||
|
||||
.. code-block:: ql
|
||||
|
||||
where config.hasFlowPath(source, sink)
|
||||
|
||||
For Python, you would simply use the ``flowsTo`` predicate to define flow from the ``source`` to the ``sink``::
|
||||
For Python, you would simply use the ``flowsTo`` predicate to define flow from the ``source`` to the ``sink``:
|
||||
|
||||
.. code-block:: ql
|
||||
|
||||
where source.flowsTo(sink)
|
||||
|
||||
|
||||
@@ -47,6 +47,7 @@ a piece of cargo.
|
||||
*Show/hide code*
|
||||
|
||||
.. literalinclude:: river-crossing.ql
|
||||
:language: ql
|
||||
:lines: 15-23
|
||||
|
||||
Second, any item can be on one of two shores. Let's call these the "left shore" and the "right shore".
|
||||
@@ -63,6 +64,7 @@ You can do this by defining a member predicate
|
||||
*Show/hide code*
|
||||
|
||||
.. literalinclude:: river-crossing.ql
|
||||
:language: ql
|
||||
:lines: 25-38
|
||||
|
||||
We also want a way to keep track of where the man, the goat, the cabbage, and the wolf are at any point. We can call this combined
|
||||
@@ -80,6 +82,7 @@ temporary variables in the body of a class are called :ref:`fields <fields>`.
|
||||
*Show/hide code*
|
||||
|
||||
.. literalinclude:: river-crossing-1.ql
|
||||
:language: ql
|
||||
:lines: 33-40,87
|
||||
|
||||
We are interested in two particular states, namely the initial state and the goal state,
|
||||
@@ -94,6 +97,7 @@ Assuming that all items start on the left shore and end up on the right shore, d
|
||||
*Show/hide code*
|
||||
|
||||
.. literalinclude:: river-crossing-1.ql
|
||||
:language: ql
|
||||
:lines: 89-97
|
||||
|
||||
.. pull-quote::
|
||||
@@ -112,6 +116,7 @@ Using the above note, the QL code so far looks like this:
|
||||
*Show/hide code*
|
||||
|
||||
.. literalinclude:: river-crossing.ql
|
||||
:language: ql
|
||||
:lines: 15-52,103-113
|
||||
|
||||
Model the action of "ferrying"
|
||||
@@ -130,6 +135,7 @@ after ferrying a particular cargo. (Hint: Use the predicate ``other``.)
|
||||
*Show/hide code*
|
||||
|
||||
.. literalinclude:: river-crossing.ql
|
||||
:language: ql
|
||||
:lines: 54-67
|
||||
|
||||
Of course, not all ferrying actions are possible. Add some extra conditions to describe when a ferrying
|
||||
@@ -147,6 +153,7 @@ For example, follow these steps:
|
||||
*Show/hide code*
|
||||
|
||||
.. literalinclude:: river-crossing.ql
|
||||
:language: ql
|
||||
:lines: 69-81
|
||||
|
||||
Find paths from one state to another
|
||||
@@ -185,6 +192,7 @@ for example ``steps <= 7``.
|
||||
*Show/hide code*
|
||||
|
||||
.. literalinclude:: river-crossing-1.ql
|
||||
:language: ql
|
||||
:lines: 70-86
|
||||
|
||||
However, although this ensures that the solution is finite, it can still contain loops if the upper bound
|
||||
@@ -215,6 +223,7 @@ the given path without revisiting any previously visited states.
|
||||
*Show/hide code*
|
||||
|
||||
.. literalinclude:: river-crossing.ql
|
||||
:language: ql
|
||||
:lines: 83-102
|
||||
|
||||
Display the results
|
||||
@@ -230,6 +239,7 @@ that returns the resulting path.
|
||||
*Show/hide code*
|
||||
|
||||
.. literalinclude:: river-crossing.ql
|
||||
:language: ql
|
||||
:lines: 115-117
|
||||
|
||||
The :ref:`don't-care expression <don-t-care-expressions>` (``_``),
|
||||
|
||||
@@ -27,7 +27,9 @@ The performance of a predicate can often be judged by considering roughly how ma
|
||||
One way of creating badly performing predicates is by using two variables without relating them in any way, or only relating them using a negation.
|
||||
This leads to computing the `Cartesian product <https://en.wikipedia.org/wiki/Cartesian_product>`__ between the sets of possible values for each variable, potentially generating a huge table of results.
|
||||
This can occur if you don't specify restrictions on your variables.
|
||||
For instance, consider the following predicate that checks whether a Java method ``m`` may access a field ``f``::
|
||||
For instance, consider the following predicate that checks whether a Java method ``m`` may access a field ``f``:
|
||||
|
||||
.. code-block:: ql
|
||||
|
||||
predicate mayAccess(Method m, Field f) {
|
||||
f.getAnAccess().getEnclosingCallable() = m
|
||||
@@ -39,7 +41,9 @@ The predicate holds if ``m`` contains an access to ``f``, but also conservativel
|
||||
|
||||
However, if ``m`` is a native method, the table computed by ``mayAccess`` will contain a row ``m, f`` for *all* fields ``f`` in the codebase, making it potentially very large.
|
||||
|
||||
This example shows a similar mistake in a member predicate::
|
||||
This example shows a similar mistake in a member predicate:
|
||||
|
||||
.. code-block:: ql
|
||||
|
||||
class Foo extends Class {
|
||||
...
|
||||
@@ -57,11 +61,15 @@ Use specific types
|
||||
~~~~~~~~~~~~~~~~~~
|
||||
|
||||
":ref:`Types <types>`" provide an upper bound on the size of a relation.
|
||||
This helps the query optimizer be more effective, so it's generally good to use the most specific types possible. For example::
|
||||
This helps the query optimizer be more effective, so it's generally good to use the most specific types possible. For example:
|
||||
|
||||
.. code-block:: ql
|
||||
|
||||
predicate foo(LoggingCall e)
|
||||
|
||||
is preferred over::
|
||||
is preferred over:
|
||||
|
||||
.. code-block:: ql
|
||||
|
||||
predicate foo(Expr e)
|
||||
|
||||
@@ -95,7 +103,9 @@ Avoid complex recursion
|
||||
":ref:`Recursion <recursion>`" is about self-referencing definitions.
|
||||
It can be extremely powerful as long as it is used appropriately.
|
||||
On the whole, you should try to make recursive predicates as simple as possible.
|
||||
That is, you should define a *base case* that allows the predicate to *bottom out*, along with a single *recursive call*::
|
||||
That is, you should define a *base case* that allows the predicate to *bottom out*, along with a single *recursive call*:
|
||||
|
||||
.. code-block:: ql
|
||||
|
||||
int depth(Stmt s) {
|
||||
exists(Callable c | c.getBody() = s | result = 0) // base case
|
||||
|
||||
Reference in New Issue
Block a user