Apply suggestions from code review

Co-authored-by: Felicity Chapman <felicitymay@github.com>
This commit is contained in:
Arthur Baars
2022-11-01 11:35:26 +01:00
committed by GitHub
parent 6f646be733
commit ab963fef82

View File

@@ -9,16 +9,15 @@ external libraries.
About this article
------------------
This article describes how to use API graphs to reference classes and functions defined in library
code. You can use API graphs to conveniently refer to external library functions when defining things like
remote flow sources.
This article describes how you can use API graphs to reference classes and functions defined in library
code. API graphs are particularly useful when you want to model the remote flow sources available from external library functions.
Module and class references
---------------------------
The most common entry point into the API graph will be the point where a toplevel module or class is
accessed. For example, you can access the API graph node corresponding to the ``::Regexp`` class
The most common entry point into the API graph is when a top-level module or class is accessed.
For example, you can access the API graph node corresponding to the ``::Regexp`` class
by using the ``API::getTopLevelMember`` method defined in the ``codeql.ruby.ApiGraphs`` module, as the
following snippet demonstrates.
@@ -29,7 +28,7 @@ following snippet demonstrates.
select API::getTopLevelMember("Regexp")
This query selects the API graph nodes corresponding to references to the ``Regexp`` class. For nested
modules and classes, you can use the ``getMember` method. For example the following query selects
modules and classes, you can use the ``getMember`` method. For example the following query selects
references to the ``Net::HTTP`` class.
.. code-block:: ql
@@ -38,9 +37,8 @@ references to the ``Net::HTTP`` class.
select API::getTopLevelMember("Net").getMember("HTTP")
Note that the given module name *must not* contain any ```::`` symbols. Thus, something like
`API::getTopLevelMember("Net::HTTP")`` will not do what you expect. Instead, this should be decomposed
into an access of the ``HTTP`` member of the API graph node for ``Net``, as in the example above.
Note that you should specify module names without ``::`` symbols. If you write ``API::getTopLevelMember("Net::HTTP")``, it will not do what you expect. Instead, you need to decompose this name
into an access of the ``HTTP`` member of the API graph node for ``Net``, as shown in the example above.
Calls and class instantiations
------------------------------
@@ -78,13 +76,13 @@ The following snippet builds on the above to find calls of the ``Regexp#match?``
Subclasses
----------
For many libraries, the main mode of usage is to extend one or more library classes. To track this
Many libraries are used by extending one or more library classes. To track this
in the API graph, you can use the ``getASubclass`` method to get the API graph node corresponding to
all the immediate subclasses of this node. To find *all* subclasses, use ``*`` or ``+`` to apply the
method repeatedly, as in ``getASubclass*``.
the immediate subclasses of a node. To find *all* subclasses, use ``*`` or ``+`` to apply the
method repeatedly. You can see an example where all subclasses are identified using ``getASubclass*`` below.
Note that ``getASubclass`` does not account for any subclassing that takes place in library code
that has not been extracted. Thus, it may be necessary to account for this in the models you write.
Note that ``getASubclass`` can only return subclasses that are extracted as part of the CodeQL database
that you are analyzing. When libraries have predefined subclasses, you will need to explicitly include them in your model.
For example, the ``ActionController::Base`` class has a predefined subclass ``Rails::ApplicationController``. To find
all subclasses of ``ActionController::Base``, you must explicitly include the subclasses of ``Rails::ApplicationController`` as well.
@@ -109,10 +107,14 @@ Using the API graph in dataflow queries
Dataflow queries often search for points where data from external sources enters the code base
as well as places where data leaves the code base. API graphs provide a convenient way to refer
to external API components such as library functions and their inputs and outputs. API graph nodes
cannot be used directly in dataflow queries they model entities that are defined externally,
while dataflow nodes correspond to entities defined in the current code base. To brigde this gap
the API node classes provide the ``asSource()`` and ``asSink()`` methods.
to external API components such as library functions and their inputs and outputs.
However, you do not use API graph nodes directly in dataflow queries.
- API graph nodes model entities that are defined outside your code base.
- Dataflow nodes model entities defined within the current code base.
You bridge the gap between the entities outside and inside your code base using
the API node class methods: ``asSource()`` and ``asSink()``.
The ``asSource()`` method is used to select dataflow nodes where a value from an external source
enters the current code base. A typical example is the return value of a library function such as
@@ -135,15 +137,15 @@ of the ``File.write(path, value)`` method.
select API::getTopLevelMember("File").getMethod("write").getParameter(1).asSink()
A more complex example is a call to ``File.open`` with a block argument. This function creates a ```File`` instance
and passes it to the supplied block. In this case the first parameter of the block is the place where an
externally created value enters the code base, i.e. the ``|file|`` in the example below:
A more complex example is a call to ``File.open`` with a block argument. This function creates a ``File`` instance
and passes it to the supplied block. In this case, we are interested in the first parameter of the block because this is where an
externally created value enters the code base, that is, the ``|file|`` in the Ruby example below:
.. code-block:: ruby
File.open("/my/file.txt", "w") { |file| file << "Hello world" }
The following snippet finds parameters of blocks of ``File.open`` method calls:
The following snippet of CodeQL finds parameters of blocks of ``File.open`` method calls:
.. code-block:: ql
@@ -152,7 +154,7 @@ The following snippet finds parameters of blocks of ``File.open`` method calls:
select API::getTopLevelMember("File").getMethod("open").getBlock().getParameter(0).asSource()
The following example is a dataflow query that that uses API graphs to find cases where data that
is read flows into a call to ```File.write``.
is read flows into a call to ``File.write``.
.. code-block:: ql