Fix code block in other CodeQL docs

This commit is contained in:
Shati Patel
2020-12-23 12:41:46 +00:00
parent f1d8d9414f
commit ff8e9e6adf
5 changed files with 58 additions and 18 deletions

View File

@@ -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
{

View File

@@ -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
/**
*

View File

@@ -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)

View File

@@ -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>` (``_``),

View File

@@ -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