mirror of
https://github.com/github/codeql.git
synced 2026-04-26 01:05:15 +02:00
C# pre-migration changes: titles & intros
This commit is contained in:
@@ -1,11 +1,13 @@
|
||||
Analyzing data flow in C#
|
||||
=========================
|
||||
|
||||
Overview
|
||||
--------
|
||||
You can use CodeQL to track the flow of data through a C# program to its use.
|
||||
|
||||
This topic describes how data flow analysis is implemented in the CodeQL libraries for C# and includes examples to help you write your own data flow queries.
|
||||
The following sections describe how to utilize the libraries for local data flow, global data flow, and taint tracking.
|
||||
About this article
|
||||
------------------
|
||||
|
||||
This article describes how data flow analysis is implemented in the CodeQL libraries for C# and includes examples to help you write your own data flow queries.
|
||||
The following sections describe how to use the libraries for local data flow, global data flow, and taint tracking.
|
||||
|
||||
For a more general introduction to modeling data flow, see :doc:`Introduction to data flow analysis with CodeQL <../intro-to-data-flow>`.
|
||||
|
||||
@@ -17,7 +19,7 @@ Local data flow is data flow within a single method or callable. Local data flow
|
||||
Using local data flow
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The local data flow library is in the module ``DataFlow``, which defines the class ``Node`` denoting any element that data can flow through. ``Node``\ s are divided into expression nodes (``ExprNode``) and parameter nodes (``ParameterNode``). It is possible to map between data flow nodes and expressions/parameters using the member predicates ``asExpr`` and ``asParameter``:
|
||||
The local data flow library is in the module ``DataFlow``, which defines the class ``Node`` denoting any element that data can flow through. ``Node``\ s are divided into expression nodes (``ExprNode``) and parameter nodes (``ParameterNode``). You can map between data flow nodes and expressions/parameters using the member predicates ``asExpr`` and ``asParameter``:
|
||||
|
||||
.. code-block:: ql
|
||||
|
||||
@@ -45,9 +47,9 @@ or using the predicates ``exprNode`` and ``parameterNode``:
|
||||
*/
|
||||
ParameterNode parameterNode(Parameter p) { ... }
|
||||
|
||||
The predicate ``localFlowStep(Node nodeFrom, Node nodeTo)`` holds if there is an immediate data flow edge from the node ``nodeFrom`` to the node ``nodeTo``. The predicate can be applied recursively (using the ``+`` and ``*`` operators), or it is possible to use the predefined recursive predicate ``localFlow``.
|
||||
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``.
|
||||
|
||||
For example, finding flow from a parameter ``source`` to an expression ``sink`` in zero or more local steps can be achieved as follows:
|
||||
For example, you can find flow from a parameter ``source`` to an expression ``sink`` in zero or more local steps:
|
||||
|
||||
.. code-block:: ql
|
||||
|
||||
@@ -65,9 +67,9 @@ Local taint tracking extends local data flow by including non-value-preserving f
|
||||
|
||||
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``. The predicate can be applied recursively (using the ``+`` and ``*`` operators), or it is possible to use the predefined recursive predicate ``localTaint``.
|
||||
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``.
|
||||
|
||||
For example, finding taint propagation from a parameter ``source`` to an expression ``sink`` in zero or more local steps can be achieved as follows:
|
||||
For example, you can find taint propagation from a parameter ``source`` to an expression ``sink`` in zero or more local steps:
|
||||
|
||||
.. code-block:: ql
|
||||
|
||||
@@ -76,7 +78,7 @@ For example, finding taint propagation from a parameter ``source`` to an express
|
||||
Examples
|
||||
~~~~~~~~
|
||||
|
||||
The following query finds the filename passed to ``System.IO.File.Open``:
|
||||
This query finds the filename passed to ``System.IO.File.Open``:
|
||||
|
||||
.. code-block:: ql
|
||||
|
||||
@@ -99,7 +101,7 @@ Unfortunately this will only give the expression in the argument, not the values
|
||||
and DataFlow::localFlow(DataFlow::exprNode(src), DataFlow::exprNode(call.getArgument(0)))
|
||||
select src
|
||||
|
||||
Then we can make the source more specific, for example an access to a public parameter. The following query finds where a public parameter is used to open a file:
|
||||
Then we can make the source more specific, for example an access to a public parameter. This query finds instances of a public parameter being used to open a file:
|
||||
|
||||
.. code-block:: ql
|
||||
|
||||
@@ -112,7 +114,7 @@ Then we can make the source more specific, for example an access to a public par
|
||||
and call.getEnclosingCallable().(Member).isPublic()
|
||||
select p, "Opening a file from a public method."
|
||||
|
||||
The following example finds calls to ``String.Format`` where the format string isn't hard-coded:
|
||||
This query finds calls to ``String.Format`` where the format string isn't hard-coded:
|
||||
|
||||
.. code-block:: ql
|
||||
|
||||
@@ -139,7 +141,7 @@ Global data flow tracks data flow throughout the entire program, and is therefor
|
||||
Using global data flow
|
||||
~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The global data flow library is used by extending the class ``DataFlow::Configuration`` as follows:
|
||||
The global data flow library is used by extending the class ``DataFlow::Configuration``:
|
||||
|
||||
.. code-block:: ql
|
||||
|
||||
@@ -157,12 +159,12 @@ The global data flow library is used by extending the class ``DataFlow::Configur
|
||||
}
|
||||
}
|
||||
|
||||
The following predicates are defined in the configuration:
|
||||
These predicates are defined in the configuration:
|
||||
|
||||
- ``isSource`` - defines where data may flow from
|
||||
- ``isSink`` - defines where data may flow to
|
||||
- ``isBarrier`` - optionally, restricts the data flow
|
||||
- ``isAdditionalFlowStep`` - optionally, adds additional flow steps
|
||||
- ``isSource`` - defines where data may flow from.
|
||||
- ``isSink`` - defines where data may flow to.
|
||||
- ``isBarrier`` - optionally, restricts the data flow.
|
||||
- ``isAdditionalFlowStep`` - optionally, adds additional flow steps.
|
||||
|
||||
The characteristic predicate (``MyDataFlowConfiguration()``) defines the name of the configuration, so ``"..."`` must be replaced with a unique name.
|
||||
|
||||
@@ -177,7 +179,7 @@ The data flow analysis is performed using the predicate ``hasFlow(DataFlow::Node
|
||||
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. The global taint tracking library is used by extending the class ``TaintTracking::Configuration`` as follows:
|
||||
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. The global taint tracking library is used by extending the class ``TaintTracking::Configuration``:
|
||||
|
||||
.. code-block:: ql
|
||||
|
||||
@@ -195,12 +197,12 @@ Global taint tracking is to global data flow what local taint tracking is to loc
|
||||
}
|
||||
}
|
||||
|
||||
The following predicates are defined in the configuration:
|
||||
These predicates are defined in the configuration:
|
||||
|
||||
- ``isSource`` - defines where taint may flow from
|
||||
- ``isSink`` - defines where taint may flow to
|
||||
- ``isSanitizer`` - optionally, restricts the taint flow
|
||||
- ``isAdditionalTaintStep`` - optionally, adds additional taint steps
|
||||
- ``isSource`` - defines where taint may flow from.
|
||||
- ``isSink`` - defines where taint may flow to.
|
||||
- ``isSanitizer`` - optionally, restricts the taint flow.
|
||||
- ``isAdditionalTaintStep`` - optionally, adds additional taint steps.
|
||||
|
||||
Similar to global data flow, the characteristic predicate (``MyTaintTrackingConfiguration()``) defines the unique name of the configuration and the taint analysis is performed using the predicate ``hasFlow(DataFlow::Node source, DataFlow::Node sink)``.
|
||||
|
||||
@@ -214,7 +216,7 @@ The class ``RemoteSourceFlow`` (defined in module ``semmle.code.csharp.dataflow.
|
||||
Example
|
||||
~~~~~~~
|
||||
|
||||
The following example shows a data flow configuration that uses all public API parameters as data sources.
|
||||
This query shows a data flow configuration that uses all public API parameters as data sources:
|
||||
|
||||
.. code-block:: ql
|
||||
|
||||
@@ -236,30 +238,30 @@ The following example shows a data flow configuration that uses all public API p
|
||||
Class hierarchy
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
- ``DataFlow::Configuration`` - base class for custom global data flow analysis
|
||||
- ``DataFlow::Node`` - an element behaving as a data flow node
|
||||
- ``DataFlow::Configuration`` - base class for custom global data flow analysis.
|
||||
- ``DataFlow::Node`` - an element behaving as a data flow node.
|
||||
|
||||
- ``DataFlow::ExprNode`` - an expression behaving as a data flow node
|
||||
- ``DataFlow::ParameterNode`` - a parameter data flow node representing the value of a parameter at function entry
|
||||
- ``DataFlow::ExprNode`` - an expression behaving as a data flow node.
|
||||
- ``DataFlow::ParameterNode`` - a parameter data flow node representing the value of a parameter at function entry.
|
||||
|
||||
- ``PublicCallableParameter`` - a parameter to a public method/callable in a public class
|
||||
- ``PublicCallableParameter`` - a parameter to a public method/callable in a public class.
|
||||
|
||||
- ``RemoteSourceFlow`` - data flow from network/remote input
|
||||
- ``RemoteSourceFlow`` - data flow from network/remote input.
|
||||
|
||||
- ``AspNetRemoteFlowSource`` - data flow from remote ASP.NET user input
|
||||
- ``AspNetRemoteFlowSource`` - data flow from remote ASP.NET user input.
|
||||
|
||||
- ``AspNetQueryStringRemoteFlowSource`` - data flow from ``System.Web.HttpRequest``
|
||||
- ``AspNetUserInputRemoveFlowSource`` - data flow from ``System.Web.IO.WebControls.TextBox``
|
||||
- ``AspNetQueryStringRemoteFlowSource`` - data flow from ``System.Web.HttpRequest``.
|
||||
- ``AspNetUserInputRemoveFlowSource`` - data flow from ``System.Web.IO.WebControls.TextBox``.
|
||||
|
||||
- ``WcfRemoteFlowSource`` - data flow from a WCF web service
|
||||
- ``AspNetServiceRemoteFlowSource`` - data flow from an ASP.NET web service
|
||||
- ``WcfRemoteFlowSource`` - data flow from a WCF web service.
|
||||
- ``AspNetServiceRemoteFlowSource`` - data flow from an ASP.NET web service.
|
||||
|
||||
- ``TaintTracking::Configuration`` - base class for custom global taint tracking analysis
|
||||
- ``TaintTracking::Configuration`` - base class for custom global taint tracking analysis.
|
||||
|
||||
Examples
|
||||
~~~~~~~~
|
||||
|
||||
The following data flow configuration tracks data flow from environment variables to opening files:
|
||||
This data flow configuration tracks data flow from environment variables to opening files:
|
||||
|
||||
.. code-block:: ql
|
||||
|
||||
@@ -300,7 +302,7 @@ Exercise 4: Using the answers from 2 and 3, write a query to find all global dat
|
||||
Extending library data flow
|
||||
---------------------------
|
||||
|
||||
*Library* data flow defines how data flows through libraries where the source code is not available, such as the .NET Framework, third-party libraries or proprietary libraries.
|
||||
Library data flow defines how data flows through libraries where the source code is not available, such as the .NET Framework, third-party libraries or proprietary libraries.
|
||||
|
||||
To define new library data flow, extend the class ``LibraryTypeDataFlow`` from the module ``semmle.code.csharp.dataflow.LibraryTypeDataFlow``. Override the predicate ``callableFlow`` to define how data flows through the methods in the class. ``callableFlow`` has the signature
|
||||
|
||||
@@ -308,9 +310,9 @@ To define new library data flow, extend the class ``LibraryTypeDataFlow`` from t
|
||||
|
||||
predicate callableFlow(CallableFlowSource source, CallableFlowSink sink, SourceDeclarationCallable callable, boolean preservesValue)
|
||||
|
||||
- ``callable`` - the ``Callable`` (such as a method, constructor, property getter or setter) performing the data flow
|
||||
- ``source`` - the data flow input
|
||||
- ``sink`` - the data flow output
|
||||
- ``callable`` - the ``Callable`` (such as a method, constructor, property getter or setter) performing the data flow.
|
||||
- ``source`` - the data flow input.
|
||||
- ``sink`` - the data flow output.
|
||||
- ``preservesValue`` - whether the flow step preserves the value, for example if ``x`` is a string then ``x.ToString()`` preserves the value where as ``x.ToLower()`` does not.
|
||||
|
||||
Class hierarchy
|
||||
@@ -318,24 +320,24 @@ Class hierarchy
|
||||
|
||||
- ``Callable`` - a callable (methods, accessors, constructors etc.)
|
||||
|
||||
- ``SourceDeclarationCallable`` - an unconstructed callable
|
||||
- ``SourceDeclarationCallable`` - an unconstructed callable.
|
||||
|
||||
- ``CallableFlowSource`` - the input of data flow into the callable
|
||||
- ``CallableFlowSource`` - the input of data flow into the callable.
|
||||
|
||||
- ``CallableFlowSourceQualifier`` - the data flow comes from the object itself
|
||||
- ``CallableFlowSourceArg`` - the data flow comes from an argument to the call
|
||||
- ``CallableFlowSourceQualifier`` - the data flow comes from the object itself.
|
||||
- ``CallableFlowSourceArg`` - the data flow comes from an argument to the call.
|
||||
|
||||
- ``CallableFlowSink`` - the output of data flow from the callable
|
||||
- ``CallableFlowSink`` - the output of data flow from the callable.
|
||||
|
||||
- ``CallableFlowSinkQualifier`` - the output is to the object itself
|
||||
- ``CallableFlowSinkReturn`` - the output is returned from the call
|
||||
- ``CallableFlowSinkArg`` - the output is an argument
|
||||
- ``CallableFlowSinkDelegateArg`` - the output flows through a delegate argument (for example, LINQ)
|
||||
- ``CallableFlowSinkQualifier`` - the output is to the object itself.
|
||||
- ``CallableFlowSinkReturn`` - the output is returned from the call.
|
||||
- ``CallableFlowSinkArg`` - the output is an argument.
|
||||
- ``CallableFlowSinkDelegateArg`` - the output flows through a delegate argument (for example, LINQ).
|
||||
|
||||
Example
|
||||
~~~~~~~
|
||||
|
||||
The following example is adapted from ``LibraryTypeDataFlow.qll``. It declares data flow through the class ``System.Uri``, including the constructor, the ``ToString`` method, and the properties ``Query``, ``OriginalString``, and ``PathAndQuery``.
|
||||
This example is adapted from ``LibraryTypeDataFlow.qll``. It declares data flow through the class ``System.Uri``, including the constructor, the ``ToString`` method, and the properties ``Query``, ``OriginalString``, and ``PathAndQuery``.
|
||||
|
||||
.. code-block:: ql
|
||||
|
||||
@@ -489,7 +491,7 @@ Exercise 4
|
||||
Exercise 5
|
||||
~~~~~~~~~~
|
||||
|
||||
All properties can flow data. We can declare this as follows:
|
||||
All properties can flow data:
|
||||
|
||||
.. code-block:: ql
|
||||
|
||||
@@ -545,8 +547,8 @@ This can be adapted from the ``SystemUriFlow`` class:
|
||||
}
|
||||
}
|
||||
|
||||
What next?
|
||||
----------
|
||||
Further reading
|
||||
---------------
|
||||
|
||||
- Learn about the standard libraries used to write queries for C# in :doc:`Introducing the C# libraries <introduce-libraries-csharp>`.
|
||||
- Find out more about QL in the `QL language handbook <https://help.semmle.com/QL/ql-handbook/index.html>`__ and `QL language specification <https://help.semmle.com/QL/ql-spec/language.html>`__.
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
Introducing the CodeQL libraries for C#
|
||||
=======================================
|
||||
CodeQL library for C#
|
||||
=====================
|
||||
|
||||
Overview
|
||||
--------
|
||||
When you need to analyze a C# program, you can make use of the large collection of classes in the C# library for CodeQL.
|
||||
|
||||
About the C# library
|
||||
--------------------
|
||||
|
||||
There is an extensive library for analyzing CodeQL databases extracted from C# projects. The classes in this library present the data from a 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 QL modules, that is, files with the extension ``.qll``. The module ``csharp.qll`` imports all the core C# library modules, so you can include the complete library by beginning your query with:
|
||||
|
||||
@@ -10,9 +12,9 @@ There is an extensive library for analyzing CodeQL databases extracted from C# p
|
||||
|
||||
import csharp
|
||||
|
||||
Since this is required for all C# queries, it is omitted from code snippets below.
|
||||
Since this is required for all C# queries, it's omitted from code snippets below.
|
||||
|
||||
The core library contains all the program elements, including `files <#files>`__, `types <#types>`__, methods, `variables <#variables>`__, `statements <#statements>`__, and `expressions <#expressions>`__. This is sufficient for most queries, however additional libraries can be imported for bespoke functionality such as control flow and data flow. See :doc:`CodeQL for C# <ql-for-csharp>` for information about these additional libraries.
|
||||
The core library contains all the program elements, including `files <#files>`__, `types <#types>`__, methods, `variables <#variables>`__, `statements <#statements>`__, and `expressions <#expressions>`__. This is sufficient for most queries, however additional libraries can be imported for bespoke functionality such as control flow and data flow. For information about these additional libraries, see :doc:`CodeQL for C# <ql-for-csharp>`.
|
||||
|
||||
Class hierarchies
|
||||
~~~~~~~~~~~~~~~~~
|
||||
@@ -42,7 +44,7 @@ Each section contains a class hierarchy, showing the inheritance structure betwe
|
||||
|
||||
- ``AddExpr``, ``SubExpr``, ``MulExpr``, ``DivExpr``, ``RemExpr``
|
||||
|
||||
This means that the class ``AddExpr`` extends class ``BinaryArithmeticOperation``, which in turn extends class ``ArithmeticOperation`` and so on. If you want to query any arithmetic operation, then use the class ``ArithmeticOperation``, but if you specifically want to limit the query to addition operations, then use the class ``AddExpr``.
|
||||
This means that the class ``AddExpr`` extends class ``BinaryArithmeticOperation``, which in turn extends class ``ArithmeticOperation`` and so on. If you want to query any arithmetic operation, use the class ``ArithmeticOperation``, but if you specifically want to limit the query to addition operations, use the class ``AddExpr``.
|
||||
|
||||
Classes can also be considered to be *sets*, and the ``extends`` relation between classes defines a subset. Every member of class ``AddExpr`` is also in the class ``BinaryArithmeticOperation``. In general, classes overlap and an entity can be a member of several classes.
|
||||
|
||||
@@ -50,14 +52,14 @@ This overview omits some of the less important or intermediate classes from the
|
||||
|
||||
Each class has predicates, which are logical propositions about that class. They also define navigable relationships between classes. Predicates are inherited, so for example the ``AddExpr`` class inherits the predicates ``getLeftOperand()`` and ``getRightOperand()`` from ``BinaryArithmeticOperation``, and ``getType()`` from class ``Expr``. This is similar to how methods are inherited in object-oriented programming languages.
|
||||
|
||||
In this overview, we present the most common and useful predicates. Consult the `reference <https://help.semmle.com/qldoc/csharp>`__, the CodeQL source code, and autocomplete in the editor for the complete list of predicates available on each class.
|
||||
In this overview, we present the most common and useful predicates. For the complete list of predicates available on each class, you can look in the CodeQL source code, use autocomplete in the editor, or see the `C# reference <https://help.semmle.com/qldoc/csharp>`__.
|
||||
|
||||
Exercises
|
||||
~~~~~~~~~
|
||||
|
||||
Each section in this topic contains exercises to check your understanding.
|
||||
|
||||
Exercise 1: Simplify the following query:
|
||||
Exercise 1: Simplify this query:
|
||||
|
||||
.. code-block:: ql
|
||||
|
||||
@@ -84,11 +86,11 @@ Class hierarchy
|
||||
Predicates
|
||||
~~~~~~~~~~
|
||||
|
||||
- ``getName()`` - gets the full path of the file (for example, ``C:\Temp\test.cs``)
|
||||
- ``getNumberOfLines()`` - gets the number of lines (for source files only)
|
||||
- ``getShortName()`` - gets the name of the file without the extension (for example, ``test``)
|
||||
- ``getBaseName()`` - gets the name and extension of the file (for example, ``test.cs``)
|
||||
- ``getParent()`` - gets the parent directory
|
||||
- ``getName()`` - gets the full path of the file (for example, ``C:\Temp\test.cs``).
|
||||
- ``getNumberOfLines()`` - gets the number of lines (for source files only).
|
||||
- ``getShortName()`` - gets the name of the file without the extension (for example, ``test``).
|
||||
- ``getBaseName()`` - gets the name and extension of the file (for example, ``test.cs``).
|
||||
- ``getParent()`` - gets the parent directory.
|
||||
|
||||
Examples
|
||||
~~~~~~~~
|
||||
@@ -116,7 +118,7 @@ Exercise 2: Write a query to find the source file with the largest number of lin
|
||||
Elements
|
||||
--------
|
||||
|
||||
The class `Element <https://help.semmle.com/qldoc/csharp/semmle/code/cil/Element.qll/type.Element$Element.html>`__ is the base class for all parts of a C# program, and it is the root of the element class hierarchy. All program elements (such as types, methods, statements, and expressions) ultimately derive from this common base class.
|
||||
The class `Element <https://help.semmle.com/qldoc/csharp/semmle/code/cil/Element.qll/type.Element$Element.html>`__ is the base class for all parts of a C# program, and it's the root of the element class hierarchy. All program elements (such as types, methods, statements, and expressions) ultimately derive from this common base class.
|
||||
|
||||
``Element`` forms a hierarchical structure of the program, which can be navigated using the ``getParent()`` and ``getChild()`` predicates. This is much like an abstract syntax tree, and also applies to elements in assemblies.
|
||||
|
||||
@@ -125,10 +127,10 @@ Predicates
|
||||
|
||||
The ``Element`` class provides common functionality for all program elements, including:
|
||||
|
||||
- ``getLocation()`` - gets the text span in the source code
|
||||
- ``getFile()`` - gets the ``File`` containing the ``Element``
|
||||
- ``getParent()`` - gets the parent ``Element``, if any
|
||||
- ``getAChild()`` - gets a child ``Element`` of this element, if any
|
||||
- ``getLocation()`` - gets the text span in the source code.
|
||||
- ``getFile()`` - gets the ``File`` containing the ``Element``.
|
||||
- ``getParent()`` - gets the parent ``Element``, if any.
|
||||
- ``getAChild()`` - gets a child ``Element`` of this element, if any.
|
||||
|
||||
Examples
|
||||
~~~~~~~~
|
||||
@@ -163,11 +165,11 @@ Predicates
|
||||
|
||||
Some predicates of ``Location`` include:
|
||||
|
||||
- ``getFile()`` - gets the ``File``
|
||||
- ``getStartLine()`` - gets the first line of the text
|
||||
- ``getEndLine()`` - gets the last line of the text
|
||||
- ``getStartColumn()`` - gets the column of the start of the text
|
||||
- ``getEndColumn()`` - gets the column of the end of the text
|
||||
- ``getFile()`` - gets the ``File``.
|
||||
- ``getStartLine()`` - gets the first line of the text.
|
||||
- ``getEndLine()`` - gets the last line of the text.
|
||||
- ``getStartColumn()`` - gets the column of the start of the text.
|
||||
- ``getEndColumn()`` - gets the column of the end of the text.
|
||||
|
||||
Examples
|
||||
~~~~~~~~
|
||||
@@ -213,10 +215,10 @@ Predicates
|
||||
|
||||
Useful member predicates on ``Declaration`` include:
|
||||
|
||||
- ``getDeclaringType()`` - gets the type containing the declaration, if any
|
||||
- ``getName()``/``hasName(string)`` - gets the name of the declared entity
|
||||
- ``isSourceDeclaration()`` - whether the declaration is source code and is not a constructed type/method
|
||||
- ``getSourceDeclaration()`` - gets the original (unconstructed) declaration
|
||||
- ``getDeclaringType()`` - gets the type containing the declaration, if any.
|
||||
- ``getName()``/``hasName(string)`` - gets the name of the declared entity.
|
||||
- ``isSourceDeclaration()`` - whether the declaration is source code and is not a constructed type/method.
|
||||
- ``getSourceDeclaration()`` - gets the original (unconstructed) declaration.
|
||||
|
||||
Examples
|
||||
~~~~~~~~
|
||||
@@ -262,10 +264,10 @@ Predicates
|
||||
|
||||
Some common predicates on ``Variable`` are:
|
||||
|
||||
- ``getType()`` - gets the ``Type`` of this variable
|
||||
- ``getAnAccess()`` - gets an expression that accesses (reads or writes) this variable, if any
|
||||
- ``getAnAssignedValue()`` - gets an expression that is assigned to this variable, if any
|
||||
- ``getInitializer()`` - gets the expression used to initialize the variable, if any
|
||||
- ``getType()`` - gets the ``Type`` of this variable.
|
||||
- ``getAnAccess()`` - gets an expression that accesses (reads or writes) this variable, if any.
|
||||
- ``getAnAssignedValue()`` - gets an expression that is assigned to this variable, if any.
|
||||
- ``getInitializer()`` - gets the expression used to initialize the variable, if any.
|
||||
|
||||
Examples
|
||||
~~~~~~~~
|
||||
@@ -309,7 +311,7 @@ Class hierarchy
|
||||
- ``VoidType`` - ``void``
|
||||
- ``PointerType`` - a pointer type
|
||||
|
||||
The ``ValueType`` class extends further as follows:
|
||||
The ``ValueType`` class extends further:
|
||||
|
||||
- ``ValueType`` - a value type
|
||||
|
||||
@@ -345,7 +347,7 @@ The ``ValueType`` class extends further as follows:
|
||||
- ``NullableType``
|
||||
- ``ArrayType``
|
||||
|
||||
The ``RefType`` class extends further as follows:
|
||||
The ``RefType`` class extends further:
|
||||
|
||||
- ``RefType``
|
||||
|
||||
@@ -369,19 +371,19 @@ Predicates
|
||||
|
||||
Useful members of ``ValueOrRefType`` include:
|
||||
|
||||
- ``getQualifiedName()/hasQualifiedName(string)`` - gets the qualified name of the type (for example, ``"System.String"``)
|
||||
- ``getABaseInterface()`` - gets an immediate interface of this type, if any
|
||||
- ``getABaseType()`` - gets an immediate base class or interface of this type, if any
|
||||
- ``getBaseClass()`` - gets the immediate base class of this type, if any
|
||||
- ``getASubType()`` - gets an immediate subtype, a type which directly inherits from this type, if any
|
||||
- ``getAMember()`` - gets any member (field/method/property etc), if any
|
||||
- ``getAMethod()`` - gets a method, if any
|
||||
- ``getAProperty()`` - gets a property, if any
|
||||
- ``getAnIndexer()`` - gets an indexer, if any
|
||||
- ``getAnEvent()`` - gets an event, if any
|
||||
- ``getAnOperator()`` - gets an operator, if any
|
||||
- ``getANestedType()`` - gets a nested type
|
||||
- ``getNamespace()`` - gets the enclosing namespace
|
||||
- ``getQualifiedName()/hasQualifiedName(string)`` - gets the qualified name of the type (for example, ``"System.String"``).
|
||||
- ``getABaseInterface()`` - gets an immediate interface of this type, if any.
|
||||
- ``getABaseType()`` - gets an immediate base class or interface of this type, if any.
|
||||
- ``getBaseClass()`` - gets the immediate base class of this type, if any.
|
||||
- ``getASubType()`` - gets an immediate subtype, a type which directly inherits from this type, if any.
|
||||
- ``getAMember()`` - gets any member (field/method/property etc), if any.
|
||||
- ``getAMethod()`` - gets a method, if any.
|
||||
- ``getAProperty()`` - gets a property, if any.
|
||||
- ``getAnIndexer()`` - gets an indexer, if any.
|
||||
- ``getAnEvent()`` - gets an event, if any.
|
||||
- ``getAnOperator()`` - gets an operator, if any.
|
||||
- ``getANestedType()`` - gets a nested type.
|
||||
- ``getNamespace()`` - gets the enclosing namespace.
|
||||
|
||||
Examples
|
||||
~~~~~~~~
|
||||
@@ -492,12 +494,12 @@ Predicates
|
||||
|
||||
Here are a few useful predicates on the ``Callable`` class:
|
||||
|
||||
- ``getParameter(int)``/``getAParameter()`` - gets a parameter
|
||||
- ``calls(Callable)`` - whether there's a direct call from one callable to another
|
||||
- ``getReturnType()`` - gets the return type
|
||||
- ``getBody()``/``getExpressionBody()`` - gets the body of the callable
|
||||
- ``getParameter(int)``/``getAParameter()`` - gets a parameter.
|
||||
- ``calls(Callable)`` - whether there's a direct call from one callable to another.
|
||||
- ``getReturnType()`` - gets the return type.
|
||||
- ``getBody()``/``getExpressionBody()`` - gets the body of the callable.
|
||||
|
||||
Since ``Callable`` extends ``Declaration``, it also has predicates from ``Declaration``, such as
|
||||
Since ``Callable`` extends ``Declaration``, it also has predicates from ``Declaration``, such as:
|
||||
|
||||
- ``getName()``/``hasName(string)``
|
||||
- ``getSourceDeclaration()``
|
||||
@@ -506,10 +508,10 @@ Since ``Callable`` extends ``Declaration``, it also has predicates from ``Declar
|
||||
|
||||
Methods have additional predicates, including:
|
||||
|
||||
- ``getAnOverridee()`` - gets a method that is immediately overridden by this method
|
||||
- ``getAnOverrider()`` - gets a method that immediately overrides this method
|
||||
- ``getAnImplementee()`` - gets an interface method that is immediately implemented by this method
|
||||
- ``getAnImplementor()`` - gets a method that immediately implements this interface method
|
||||
- ``getAnOverridee()`` - gets a method that is immediately overridden by this method.
|
||||
- ``getAnOverrider()`` - gets a method that immediately overrides this method.
|
||||
- ``getAnImplementee()`` - gets an interface method that is immediately implemented by this method.
|
||||
- ``getAnImplementor()`` - gets a method that immediately implements this interface method.
|
||||
|
||||
Examples
|
||||
~~~~~~~~
|
||||
@@ -665,7 +667,7 @@ Find an ``if`` statement with a constant condition:
|
||||
where ifStmt.getCondition().hasValue()
|
||||
select ifStmt, "This 'if' statement is constant."
|
||||
|
||||
Find an ``if`` statement with an empty "then" clause:
|
||||
Find an ``if`` statement with an empty "then" block:
|
||||
|
||||
.. code-block:: ql
|
||||
|
||||
@@ -680,7 +682,7 @@ Exercises
|
||||
|
||||
Exercise 6: Write a query to list all empty methods. (`Answer <#exercise-6>`__)
|
||||
|
||||
Exercise 7: Modify the last example to also detect empty statements (``;``) in the then block. (`Answer <#exercise-7>`__)
|
||||
Exercise 7: Modify the last example to also detect empty statements (``;``) in the "then" block. (`Answer <#exercise-7>`__)
|
||||
|
||||
Exercise 8: Modify the last example to exclude chains of ``if`` statements, where the ``else`` part is another ``if`` statement. (`Answer <#exercise-8>`__)
|
||||
|
||||
@@ -874,13 +876,13 @@ Predicates
|
||||
|
||||
Useful predicates on ``Expr`` include:
|
||||
|
||||
- ``getType()`` - gets the ``Type`` of the expression
|
||||
- ``getValue()`` - gets the compile-time constant, if any
|
||||
- ``hasValue()`` - whether the expression has a compile-time constant
|
||||
- ``getEnclosingStmt()`` - gets the statement containing the expression, if any
|
||||
- ``getEnclosingCallable()`` - gets the callable containing the expression, if any
|
||||
- ``stripCasts()`` - remove all explicit or implicit casts
|
||||
- ``isImplicit()`` - whether the expression was implicit, such as an implicit ``this`` qualifier (``ThisAccess``)
|
||||
- ``getType()`` - gets the ``Type`` of the expression.
|
||||
- ``getValue()`` - gets the compile-time constant, if any.
|
||||
- ``hasValue()`` - whether the expression has a compile-time constant.
|
||||
- ``getEnclosingStmt()`` - gets the statement containing the expression, if any.
|
||||
- ``getEnclosingCallable()`` - gets the callable containing the expression, if any.
|
||||
- ``stripCasts()`` - remove all explicit or implicit casts.
|
||||
- ``isImplicit()`` - whether the expression was implicit, such as an implicit ``this`` qualifier (``ThisAccess``).
|
||||
|
||||
Examples
|
||||
~~~~~~~~
|
||||
@@ -922,7 +924,7 @@ Attributes
|
||||
|
||||
C# attributes are represented by the class `Attribute <https://help.semmle.com/qldoc/csharp/semmle/code/cil/Attribute.qll/type.Attribute$Attribute.html>`__. They can be present on many C# elements, such as classes, methods, fields, and parameters. The database contains attributes from the source code and all assembly references.
|
||||
|
||||
The attribute of any ``Element`` can be obtained via ``getAnAttribute()``, whereas if you have an attribute, you can find its element via ``getTarget()``. The following two query fragments are identical:
|
||||
The attribute of any ``Element`` can be obtained via ``getAnAttribute()``, whereas if you have an attribute, you can find its element via ``getTarget()``. These two query fragments are identical:
|
||||
|
||||
.. code-block:: ql
|
||||
|
||||
@@ -939,8 +941,8 @@ Class hierarchy
|
||||
Predicates
|
||||
~~~~~~~~~~
|
||||
|
||||
- ``getTarget()`` - gets the ``Element`` to which this attribute applies
|
||||
- ``getArgument(int)`` - gets the given argument of the attribute
|
||||
- ``getTarget()`` - gets the ``Element`` to which this attribute applies.
|
||||
- ``getArgument(int)`` - gets the given argument of the attribute.
|
||||
- ``getType()`` - gets the type of this attribute. Note that the class name must end in ``"Attribute"``.
|
||||
|
||||
Examples
|
||||
@@ -1117,8 +1119,8 @@ Here is the fixed version:
|
||||
else reason = "(not given)"
|
||||
select e, "This is obsolete because " + reason
|
||||
|
||||
What next?
|
||||
----------
|
||||
Further reading
|
||||
---------------
|
||||
|
||||
- Visit :doc:`Tutorial: Analyzing data flow in C# <dataflow>` to learn more about writing queries using the standard data flow and taint tracking libraries.
|
||||
- Find out more about QL in the `QL language handbook <https://help.semmle.com/QL/ql-handbook/index.html>`__ and `QL language specification <https://help.semmle.com/QL/ql-spec/language.html>`__.
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
CodeQL for C#
|
||||
=============
|
||||
|
||||
You can use CodeQL to explore C# programs and quickly find variants of security vulnerabilities and bugs.
|
||||
|
||||
.. toctree::
|
||||
:glob:
|
||||
:hidden:
|
||||
|
||||
Reference in New Issue
Block a user