Update main C/C++ articles

This commit is contained in:
Felicity Chapman
2022-11-24 13:25:50 +00:00
committed by Arthur Baars
parent 8eeba92a47
commit a407f0a4ac
5 changed files with 5 additions and 29 deletions

View File

@@ -21,7 +21,7 @@ Experiment and learn how to write effective and efficient queries for CodeQL dat
hash-consing-and-value-numbering
- :doc:`Basic query for C and C++ code <basic-query-for-cpp-code>`: Learn to write and run a simple CodeQL query using LGTM.
- :doc:`Basic query for C and C++ code <basic-query-for-cpp-code>`: Learn to write and run a simple CodeQL query.
- :doc:`CodeQL library for C and C++ <codeql-library-for-cpp>`: When analyzing C or C++ code, you can use the large collection of classes in the CodeQL library for C and C++.

View File

@@ -165,8 +165,6 @@ Our starting point for the query is pairs of a base class and a derived class, c
where derived.getABaseClass+() = base
select base, derived, "The second class is derived from the first."
`See this in the query console on LGTM.com <https://lgtm.com/query/1505902347211/>`__
Note that the transitive closure symbol ``+`` indicates that ``Class.getABaseClass()`` may be followed one or more times, rather than only accepting a direct base class.
A lot of the results are uninteresting template parameters. You can remove those results by updating the ``where`` clause as follows:
@@ -177,8 +175,6 @@ A lot of the results are uninteresting template parameters. You can remove those
and not exists(base.getATemplateArgument())
and not exists(derived.getATemplateArgument())
`See this in the query console on LGTM.com <https://lgtm.com/query/1505907047251/>`__
Finding derived classes with destructors
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -196,8 +192,6 @@ Now we can extend the query to find derived classes with destructors, using the
and d2 = derived.getDestructor()
select base, derived, "The second class is derived from the first, and both have a destructor."
`See this in the query console on LGTM.com <https://lgtm.com/query/1505901767389/>`__
Notice that getting the destructor implicitly asserts that one exists. As a result, this version of the query returns fewer results than before.
Finding base classes where the destructor is not virtual
@@ -216,11 +210,9 @@ Our last change is to use ``Function.isVirtual()`` to find cases where the base
and not d1.isVirtual()
select d1, "This destructor should probably be virtual."
`See this in the query console on LGTM.com <https://lgtm.com/query/1505908156827/>`__
That completes the query.
There is a similar built-in `query <https://lgtm.com/rules/2158670642/>`__ on LGTM.com that finds classes in a C/C++ project with virtual functions but no virtual destructor. You can take a look at the code for this query by clicking **Open in query console** at the top of that page.
There is a similar standard query `Non-virtual destructor in base class <https://codeql.github.com/codeql-query-help/cpp/cpp-virtual-destructor/>`__ that finds classes in a C/C++ project with virtual functions but no virtual destructor.
Further reading
---------------

View File

@@ -23,8 +23,6 @@ In the following example we find instances of ``AssignExpr`` which assign the co
where e.getRValue().getValue().toInt() = 0
select e, "Assigning the value 0 to something."
`See this in the query console on LGTM.com <https://lgtm.com/query/1505908086530/>`__
The ``where`` clause in this example gets the expression on the right side of the assignment, ``getRValue()``, and compares it with zero. Notice that there are no checks to make sure that the right side of the assignment is an integer or that it has a value (that is, it is compile-time constant, rather than a variable). For expressions where either of these assumptions is wrong, the associated predicate simply does not return anything and the ``where`` clause will not produce a result. You could think of it as if there is an implicit ``exists(e.getRValue().getValue().toInt())`` at the beginning of this line.
It is also worth noting that the query above would find this C code:
@@ -33,7 +31,7 @@ It is also worth noting that the query above would find this C code:
yPtr = NULL;
This is because the database contains a representation of the code base after the preprocessor transforms have run. This means that any macro invocations, such as the ``NULL`` define used here, are expanded during the creation of the database. If you want to write queries about macros then there are some special library classes that have been designed specifically for this purpose (for example, the ``Macro``, ``MacroInvocation`` classes and predicates like ``Element.isInMacroExpansion()``). In this case, it is good that macros are expanded, but we do not want to find assignments to pointers. For more information, see `Database generation <https://lgtm.com/help/lgtm/generate-database>`__ on LGTM.com.
This is because the database contains a representation of the code base after the preprocessor transforms have run. This means that any macro invocations, such as the ``NULL`` define used here, are expanded during the creation of the database. If you want to write queries about macros then there are some special library classes that have been designed specifically for this purpose (for example, the ``Macro``, ``MacroInvocation`` classes and predicates like ``Element.isInMacroExpansion()``). In this case, it is good that macros are expanded, but we do not want to find assignments to pointers. For more information, see `Database creation <https://codeql.github.com/docs/codeql-overview/about-codeql/#database-creation>`__.
Finding assignments of 0 to an integer
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -49,8 +47,6 @@ We can make the query more specific by defining a condition for the left side of
and e.getLValue().getType().getUnspecifiedType() instanceof IntegralType
select e, "Assigning the value 0 to an integer."
`See this in the query console on LGTM.com <https://lgtm.com/query/1505906986578/>`__
This checks that the left side of the assignment has a type that is some kind of integer. Note the call to ``Type.getUnspecifiedType()``. This resolves ``typedef`` types to their underlying types so that the query finds assignments like this one:
.. code-block:: cpp
@@ -109,8 +105,6 @@ Unfortunately this would not quite work, because the loop initialization is actu
and e.getLValue().getType().getUnspecifiedType() instanceof IntegralType
select e, "Assigning the value 0 to an integer, inside a for loop initialization."
`See this in the query console on LGTM.com <https://lgtm.com/query/1505909016965/>`__
Finding assignments of 0 within the loop body
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -127,8 +121,6 @@ We can find assignments inside the loop body using similar code with the predica
and e.getLValue().getType().getUnderlyingType() instanceof IntegralType
select e, "Assigning the value 0 to an integer, inside a for loop body."
`See this in the query console on LGTM.com <https://lgtm.com/query/1505901437190/>`__
Note that we replaced ``e.getEnclosingStmt()`` with ``e.getEnclosingStmt().getParentStmt*()``, to find an assignment expression that is deeply nested inside the loop body. The transitive closure modifier ``*`` here indicates that ``Stmt.getParentStmt()`` may be followed zero or more times, rather than just once, giving us the statement, its parent statement, its parent's parent statement etc.
Further reading

View File

@@ -40,8 +40,6 @@ It might be more interesting to find functions that are not called, using the st
where not exists(FunctionCall fc | fc.getTarget() = f)
select f, "This function is never called."
`See this in the query console on LGTM.com <https://lgtm.com/query/1505891246456/>`__
The new query finds functions that are not the target of any ``FunctionCall``—in other words, functions that are never called. You may be surprised by how many results the query finds. However, if you examine the results, you can see that many of the functions it finds are used indirectly. To create a query that finds only unused functions, we need to refine the query and exclude other ways of using a function.
Excluding functions that are referenced with a function pointer
@@ -58,11 +56,9 @@ You can modify the query to remove functions where a function pointer is used to
and not exists(FunctionAccess fa | fa.getTarget() = f)
select f, "This function is never called, or referenced with a function pointer."
`See this in the query console on LGTM.com <https://lgtm.com/query/1505890446605/>`__
This query returns fewer results. However, if you examine the results then you can probably still find potential refinements.
For example, there is a more complicated LGTM `query <https://lgtm.com/rules/2152580467/>`__ that finds unused static functions. To see the code for this query, click **Open in query console** at the top of the page.
For example, there is a more complicated standard query, `Unused static function <https://codeql.github.com/codeql-query-help/cpp/cpp-unused-static-function/>`__, that finds unused static functions.
You can explore the definition of an element in the standard libraries and see what predicates are available. Use the keyboard **F3** button to open the definition of any element. Alternatively, hover over the element and click **Jump to definition** in the tooltip displayed. The library file is opened in a new tab with the definition highlighted.
@@ -80,8 +76,6 @@ This query uses ``Function`` and ``FunctionCall`` to find calls to the function
and not fc.getArgument(1) instanceof StringLiteral
select fc, "sprintf called with variable format string."
`See this in the query console on LGTM.com <https://lgtm.com/query/1505889506751/>`__
This uses:
- ``Declaration.getQualifiedName()`` to identify calls to the specific function ``sprintf``.
@@ -89,7 +83,7 @@ This uses:
Note that we could have used ``Declaration.getName()``, but ``Declaration.getQualifiedName()`` is a better choice because it includes the namespace. For example: ``getName()`` would return ``vector`` where ``getQualifiedName`` would return ``std::vector``.
The LGTM version of this query is considerably more complicated, but if you look carefully you will find that its structure is the same. See `Non-constant format string <https://lgtm.com/rules/2152810612/>`__ and click **Open in query console** at the top of the page.
The published version of this query is considerably more complicated, but if you look carefully you will find that its structure is the same. See `Non-constant format string <https://codeql.github.com/codeql-query-help/cpp/cpp-non-constant-format/>`__.
Further reading
---------------

View File

@@ -146,8 +146,6 @@ Finally we can simplify the query by using the transitive closure operator. In t
and exists(c.getBlock())
select c, "Constructor does not initialize fields $@.", f, f.getName()
`See this in the query console on LGTM.com <https://lgtm.com/query/1505896968215/>`__
Further reading
---------------