Merge pull request #11140 from github/codeql-cli-2.11.2

Merge documentation changes of 2.11.2 into 2.11.3
This commit is contained in:
Arthur Baars
2022-11-07 16:07:20 +01:00
committed by GitHub
8 changed files with 1242 additions and 9 deletions

View File

@@ -0,0 +1,655 @@
.. _abstract-syntax-tree-classes-for-working-with-ruby-programs:
Abstract syntax tree classes for working with Ruby programs
===========================================================
CodeQL has a large selection of classes for representing the abstract syntax tree of Ruby programs.
.. include:: ../reusables/abstract-syntax-tree.rst
The descriptions below use the following conventions and placeholders.
* An ``IDENTIFIER`` denotes an arbitrary identifier.
* A ``CNAME`` denotes a class or module name.
* An ``FNAME`` denotes a method name.
* A ``TERM`` is either a semicolon or a newline used to terminate a statement.
* Elements enclosed in ``« »`` are grouped and may be suffixed by ``?``, ``*``, or ``+`` to denote 0 or 1 occurrences, 0 or more occurrences, and 1 or more occurrences respectively.
Statement classes
~~~~~~~~~~~~~~~~~
This table lists subclasses of Stmt_ that represent Ruby statements.
+---------------------------------+--------------+----------------+---------+
| Statement syntax | CodeQL class | Superclasses | Remarks |
+=================================+==============+================+=========+
| ``alias`` FNAME FNAME | AliasStmt_ | Stmt_ | |
+---------------------------------+--------------+----------------+---------+
| ``BEGIN {`` StmtSequence_ ``}`` | BeginBlock_ | StmtSequence_ | |
+---------------------------------+--------------+----------------+---------+
| ``begin`` StmtSequence_ ``end`` | BeginExpr_ | StmtSequence_ | |
+---------------------------------+--------------+----------------+---------+
| ``break`` «Expr_»? | BreakStmt_ | ReturningStmt_ | |
+---------------------------------+--------------+----------------+---------+
| ``;`` | EmptyStmt_ | Stmt_ | |
+---------------------------------+--------------+----------------+---------+
| ``END {`` StmtSequence_ ``}`` | EndBlock_ | StmtSequence_ | |
+---------------------------------+--------------+----------------+---------+
| ``next`` «Expr_»? | NextStmt_ | ReturningStmt_ | |
+---------------------------------+--------------+----------------+---------+
| ``redo`` | RedoStmt_ | Stmt_ | |
+---------------------------------+--------------+----------------+---------+
| ``retry`` | RetryStmt_ | Stmt_ | |
+---------------------------------+--------------+----------------+---------+
| ``return`` «Expr_»? | ReturnStmt_ | ReturningStmt_ | |
+---------------------------------+--------------+----------------+---------+
| ``undef`` «FNAME ``,``»+ | UndefStmt_ | Stmt_ | |
+---------------------------------+--------------+----------------+---------+
Calls
~~~~~
This table lists subclasses of Call_ as well as some expressions that appear as call arguments.
+----------------------------+---------------------+----------------+-------------------------------+
| Expression syntax | CodeQL class | Superclasses | Remarks |
+============================+=====================+================+===============================+
| Expr_ ``[`` Expr_ ``]`` | ElementReference_ | MethodCall_ | |
+----------------------------+---------------------+----------------+-------------------------------+
| MethodName_ «Expr_ ``,``»* | MethodCall_ | Call_ | |
+----------------------------+---------------------+----------------+-------------------------------+
| LhsExpr_ ``=`` Expr_ | SetterMethodCall_ | MethodCall_ | |
+----------------------------+---------------------+----------------+-------------------------------+
| ``super`` | SuperCall_ | MethodCall_ | |
+----------------------------+---------------------+----------------+-------------------------------+
| ``yield`` «Expr_ ``,``»* | YieldCall_ | Call_ | |
+----------------------------+---------------------+----------------+-------------------------------+
| ``&`` IDENTIFIER | BlockArgument_ | Expr_ | Used as an argument to a call |
+----------------------------+---------------------+----------------+-------------------------------+
| ``...`` | ForwardedArguments_ | Expr_ | Used as an argument to a call |
+----------------------------+---------------------+----------------+-------------------------------+
Constant accesses
~~~~~~~~~~~~~~~~~
All classes in this subsection are subclasses of ConstantAccess_.
+----------------------------------------+----------------------+----------------------+-------------------+
| Expression syntax | CodeQL class | Superclasses | Remarks |
+========================================+======================+======================+===================+
| CNAME | ConstantReadAccess_ | ConstantAccess_ | |
+----------------------------------------+----------------------+----------------------+-------------------+
| CNAME ``=`` Expr_ | ConstantAssignment_ | ConstantWriteAccess_ | |
+----------------------------------------+----------------------+----------------------+-------------------+
Control expressions
~~~~~~~~~~~~~~~~~~~
All classes in this subsection are subclasses of ControlExpr_.
+---------------------------------------------------------------------------------------------------------------------------------+---------------------+--------------------------------+---------+
| Expression syntax | CodeQL class | Superclasses | Remarks |
+=================================================================================================================================+=====================+================================+=========+
| ``if`` Expr_ ``then`` StmtSequence_ «``elsif`` Expr_ ``then`` StmtSequence_»* «``else`` StmtSequence_»? ``end`` | IfExpr_ | ConditionalExpr_, ControlExpr_ | |
+---------------------------------------------------------------------------------------------------------------------------------+---------------------+--------------------------------+---------+
| ``while`` Expr_ ``do`` StmtSequence_ ``end`` | WhileExpr_ | ConditionalLoop_ | |
+---------------------------------------------------------------------------------------------------------------------------------+---------------------+--------------------------------+---------+
| ``until`` Expr_ ``do`` StmtSequence_ ``end`` | UntilExpr_ | ConditionalLoop_ | |
+---------------------------------------------------------------------------------------------------------------------------------+---------------------+--------------------------------+---------+
| ``for`` LhsExpr_ ``in`` Expr_ ``do`` StmtSequence_ ``end`` | ForExpr_ | Loop_ | |
+---------------------------------------------------------------------------------------------------------------------------------+---------------------+--------------------------------+---------+
| Stmt_ ``while`` Expr_ | WhileModifierExpr_ | ConditionalLoop_ | |
+---------------------------------------------------------------------------------------------------------------------------------+---------------------+--------------------------------+---------+
| Stmt_ ``until`` Expr_ | UntilModifierExpr_ | ConditionalLoop_ | |
+---------------------------------------------------------------------------------------------------------------------------------+---------------------+--------------------------------+---------+
| Stmt_ ``if`` Expr_ | IfModifierExpr_ | ConditionalExpr_, ControlExpr_ | |
+---------------------------------------------------------------------------------------------------------------------------------+---------------------+--------------------------------+---------+
| Stmt_ ``unless`` Expr_ | UnlessModifierExpr_ | ConditionalExpr_, ControlExpr_ | |
+---------------------------------------------------------------------------------------------------------------------------------+---------------------+--------------------------------+---------+
| Expr_ ``?`` Stmt_ ``:`` Stmt_ | TernaryIfExpr_ | ConditionalExpr_, ControlExpr_ | |
+---------------------------------------------------------------------------------------------------------------------------------+---------------------+--------------------------------+---------+
| ``case`` Expr_ ``when`` Expr_ ``then`` StmtSequence_ «``when`` Expr_ ``then`` StmtSequence_»* «``else`` StmtSequence_»? ``end`` | CaseExpr_ | ControlExpr_ | |
+---------------------------------------------------------------------------------------------------------------------------------+---------------------+--------------------------------+---------+
| ``case when`` Expr_ ``then`` StmtSequence_ «``else`` StmtSequence_»? ``end`` | CaseExpr_ | ControlExpr_ | |
+---------------------------------------------------------------------------------------------------------------------------------+---------------------+--------------------------------+---------+
| ``case`` Expr_ ``in`` «TERM CaseExpr_»+ ``end`` f | CaseExpr_ | ControlExpr_ | |
+---------------------------------------------------------------------------------------------------------------------------------+---------------------+--------------------------------+---------+
Unary operations
~~~~~~~~~~~~~~~~
All classes in this subsection are subclasses of UnaryOperation_.
+--------------------+-----------------+---------------------------+-------------------+
| Expression syntax | CodeQL class | Superclasses | Remarks |
+====================+=================+===========================+===================+
| ``~`` Expr_ | ComplementExpr_ | UnaryBitwiseOperation_ | |
+--------------------+-----------------+---------------------------+-------------------+
| ``defined?`` Expr_ | DefinedExpr_ | UnaryOperation_ | |
+--------------------+-----------------+---------------------------+-------------------+
| ``**`` Expr_ | HashSplatExpr_ | UnaryOperation_ | |
+--------------------+-----------------+---------------------------+-------------------+
| ``!`` Expr_ | NotExpr_ | UnaryOperation_ | |
+--------------------+-----------------+---------------------------+-------------------+
| ``not`` Expr_ | NotExpr_ | UnaryOperation_ | |
+--------------------+-----------------+---------------------------+-------------------+
| ``*`` Expr_ | SplatExpr_ | UnaryOperation_ | |
+--------------------+-----------------+---------------------------+-------------------+
| ``-`` Expr_ | UnaryMinusExpr_ | UnaryArithmeticOperation_ | |
+--------------------+-----------------+---------------------------+-------------------+
| ``+`` Expr_ | UnaryPlusExpr_ | UnaryArithmeticOperation_ | |
+--------------------+-----------------+---------------------------+-------------------+
Binary operations
~~~~~~~~~~~~~~~~~
All classes in this subsection are subclasses of BinaryOperation_.
+------------------------+--------------------------+----------------------------+-------------------+
| Expression syntax | CodeQL class | Superclasses | Remarks |
+========================+==========================+============================+===================+
| Expr_ ``+`` Expr_ | AddExpr_ | BinaryArithmeticOperation_ | |
+------------------------+--------------------------+----------------------------+-------------------+
| LhsExpr_ ``+=`` Expr_ | AssignAddExpr_ | AssignArithmeticOperation_ | |
+------------------------+--------------------------+----------------------------+-------------------+
| LhsExpr_ ``&=`` Expr_ | AssignBitwiseAndExpr_ | AssignBitwiseOperation_ | |
+------------------------+--------------------------+----------------------------+-------------------+
| LhsExpr_ ``|=`` Expr_ | AssignBitwiseOrExpr_ | AssignBitwiseOperation_ | |
+------------------------+--------------------------+----------------------------+-------------------+
| LhsExpr_ ``^=`` Expr_ | AssignBitwiseXorExpr_ | AssignBitwiseOperation_ | |
+------------------------+--------------------------+----------------------------+-------------------+
| LhsExpr_ ``/=`` Expr_ | AssignDivExpr_ | AssignArithmeticOperation_ | |
+------------------------+--------------------------+----------------------------+-------------------+
| LhsExpr_ ``**=`` Expr_ | AssignExponentExpr_ | AssignArithmeticOperation_ | |
+------------------------+--------------------------+----------------------------+-------------------+
| LhsExpr_ ``<<=`` Expr_ | AssignLShiftExpr_ | AssignBitwiseOperation_ | |
+------------------------+--------------------------+----------------------------+-------------------+
| LhsExpr_ ``&&=`` Expr_ | AssignLogicalAndExpr_ | BinaryLogicalOperation_ | |
+------------------------+--------------------------+----------------------------+-------------------+
| LhsExpr_ ``||=`` Expr_ | AssignLogicalOrExpr_ | BinaryLogicalOperation_ | |
+------------------------+--------------------------+----------------------------+-------------------+
| LhsExpr_ ``%=`` Expr_ | AssignModuloExpr_ | AssignArithmeticOperation_ | |
+------------------------+--------------------------+----------------------------+-------------------+
| LhsExpr_ ``*=`` Expr_ | AssignMulExpr_ | AssignArithmeticOperation_ | |
+------------------------+--------------------------+----------------------------+-------------------+
| LhsExpr_ ``>>=`` Expr_ | AssignRShiftExpr_ | AssignBitwiseOperation_ | |
+------------------------+--------------------------+----------------------------+-------------------+
| LhsExpr_ ``-=`` Expr_ | AssignSubExpr_ | AssignArithmeticOperation_ | |
+------------------------+--------------------------+----------------------------+-------------------+
| Expr_ ``&`` Expr_ | BitwiseAndExpr_ | BinaryBitwiseOperation_ | |
+------------------------+--------------------------+----------------------------+-------------------+
| Expr_ ``|`` Expr_ | BitwiseOrExpr_ | BinaryBitwiseOperation_ | |
+------------------------+--------------------------+----------------------------+-------------------+
| Expr_ ``^`` Expr_ | BitwiseXorExpr_ | BinaryBitwiseOperation_ | |
+------------------------+--------------------------+----------------------------+-------------------+
| Expr_ ``===`` Expr_ | CaseEqExpr_ | EqualityOperation_ | |
+------------------------+--------------------------+----------------------------+-------------------+
| Expr_ ``/`` Expr_ | DivExpr_ | BinaryArithmeticOperation_ | |
+------------------------+--------------------------+----------------------------+-------------------+
| Expr_ ``===`` Expr_ | EqExpr_ | EqualityOperation_ | |
+------------------------+--------------------------+----------------------------+-------------------+
| Expr_ ``^`` Expr_ | ExponentExpr_ | BinaryArithmeticOperation_ | |
+------------------------+--------------------------+----------------------------+-------------------+
| Expr_ ``>=`` Expr_ | GEExpr_ | RelationalOperation_ | |
+------------------------+--------------------------+----------------------------+-------------------+
| Expr_ ``>`` Expr_ | GTExpr_ | RelationalOperation_ | |
+------------------------+--------------------------+----------------------------+-------------------+
| Expr_ ``<=`` Expr_ | LEExpr_ | RelationalOperation_ | |
+------------------------+--------------------------+----------------------------+-------------------+
| Expr_ ``<<`` Expr_ | LShiftExpr_ | BinaryBitwiseOperation_ | |
+------------------------+--------------------------+----------------------------+-------------------+
| Expr_ ``<`` Expr_ | LTExpr_ | RelationalOperation_ | |
+------------------------+--------------------------+----------------------------+-------------------+
| Expr_ ``&&`` Expr_ | LogicalAndExpr_ | BinaryLogicalOperation_ | |
+------------------------+--------------------------+----------------------------+-------------------+
| Expr_ ``and`` Expr_ | LogicalAndExpr_ | BinaryLogicalOperation_ | |
+------------------------+--------------------------+----------------------------+-------------------+
| Expr_ ``||`` Expr_ | LogicalOrExpr_ | BinaryLogicalOperation_ | |
+------------------------+--------------------------+----------------------------+-------------------+
| Expr_ ``or`` Expr_ | LogicalOrExpr_ | BinaryLogicalOperation_ | |
+------------------------+--------------------------+----------------------------+-------------------+
| Expr_ ``%`` Expr_ | ModuloExpr_ | BinaryArithmeticOperation_ | |
+------------------------+--------------------------+----------------------------+-------------------+
| Expr_ ``*`` Expr_ | MulExpr_ | BinaryArithmeticOperation_ | |
+------------------------+--------------------------+----------------------------+-------------------+
| Expr_ ``!=`` Expr_ | NEExpr_ | RelationalOperation_ | |
+------------------------+--------------------------+----------------------------+-------------------+
| Expr_ ``!~`` Expr_ | NoRegExpMatchExpr_ | BinaryOperation_ | |
+------------------------+--------------------------+----------------------------+-------------------+
| Expr_ ``>>`` Expr_ | RShiftExpr_ | BinaryBitwiseOperation_ | |
+------------------------+--------------------------+----------------------------+-------------------+
| Expr_ ``=~`` Expr_ | RegExpMatchExpr_ | BinaryOperation_ | |
+------------------------+--------------------------+----------------------------+-------------------+
| Expr_ ``<=>`` Expr_ | SpaceshipExpr_ | BinaryOperation_ | |
+------------------------+--------------------------+----------------------------+-------------------+
| Expr_ ``-`` Expr_ | SubExpr_ | BinaryArithmeticOperation_ | |
+------------------------+--------------------------+----------------------------+-------------------+
| LhsExpr_ ``=`` Expr_ | AssignExpr_ | Assignment_ | |
+------------------------+--------------------------+----------------------------+-------------------+
Literals
~~~~~~~~
All classes in this subsection are subclasses of Literal_.
+----------------------------+-------------------+----------------------------+-------------------+
| Example expression syntax | CodeQL class | Superclasses | Remarks |
+============================+===================+============================+===================+
| ``[1, 2]`` | ArrayLiteral_ | Literal_ | |
+----------------------------+-------------------+----------------------------+-------------------+
| ``true`` | BooleanLiteral_ | Literal_ | |
+----------------------------+-------------------+----------------------------+-------------------+
| ``?a`` | CharacterLiteral_ | Literal_ | |
+----------------------------+-------------------+----------------------------+-------------------+
| ``__ENCODING__`` | EncodingLiteral_ | Literal_ | |
+----------------------------+-------------------+----------------------------+-------------------+
| ``__FILE__`` | FileLiteral_ | Literal_ | |
+----------------------------+-------------------+----------------------------+-------------------+
| ``{ foo: 123, bar: 456 }`` | HashLiteral_ | Literal_ | |
+----------------------------+-------------------+----------------------------+-------------------+
| | ``<<FOO`` | HereDoc_ | StringlikeLiteral_ | |
| | ``hello world`` | | | |
| | ``FOO`` | | | |
+----------------------------+-------------------+----------------------------+-------------------+
| ``23`` | IntegerLiteral_ | NumericLiteral_ | |
+----------------------------+-------------------+----------------------------+-------------------+
| ``3.1`` | FloatLiteral_ | NumericLiteral_ | |
+----------------------------+-------------------+----------------------------+-------------------+
| ``3+2i`` | ComplexLiteral_ | NumericLiteral_ | |
+----------------------------+-------------------+----------------------------+-------------------+
| ``2/3r`` | RationalLiteral_ | NumericLiteral_ | |
+----------------------------+-------------------+----------------------------+-------------------+
| ``__LINE__`` | LineLiteral_ | Literal_ | |
+----------------------------+-------------------+----------------------------+-------------------+
| ``nil`` | NilLiteral_ | Literal_ | |
+----------------------------+-------------------+----------------------------+-------------------+
| ``(1..10)`` | RangeLiteral_ | Literal_ | |
+----------------------------+-------------------+----------------------------+-------------------+
| ``/[a-z]+/`` | RegExpLiteral_ | StringlikeLiteral_ | |
+----------------------------+-------------------+----------------------------+-------------------+
| ``"hello world"`` | StringLiteral_ | StringlikeLiteral_ | |
+----------------------------+-------------------+----------------------------+-------------------+
| ```ls -l``` | SubshellLiteral_ | StringlikeLiteral_ | |
+----------------------------+-------------------+----------------------------+-------------------+
| ``%x(/bin/sh foo.sh)`` | SubshellLiteral_ | StringlikeLiteral_ | |
+----------------------------+-------------------+----------------------------+-------------------+
| ``:foo`` | SymbolLiteral_ | StringlikeLiteral_ | |
+----------------------------+-------------------+----------------------------+-------------------+
Modules and Ruby classes
~~~~~~~~~~~~~~~~~~~~~~~~
All classes in this subsection are subclasses of BodyStmt_ and Scope_.
+----------------------------------------------------------------+--------------------+----------------------------------+-------------------+
| Expression syntax | CodeQL class | Superclasses | Remarks |
+================================================================+====================+==================================+===================+
| ``class`` CNAME «``<`` Expr_»? TERM StmtSequence_ TERM ``end`` | ClassDeclaration_ | Namespace_, ConstantWriteAccess_ | |
+----------------------------------------------------------------+--------------------+----------------------------------+-------------------+
| ``module`` CNAME TERM StmtSequence_ TERM ``end`` | ModuleDeclaration_ | Namespace_, ConstantWriteAccess_ | |
+----------------------------------------------------------------+--------------------+----------------------------------+-------------------+
| ``class <<`` Expr_ TERM StmtSequence_ TERM ``end`` | SingletonClass_ | ModuleBase_ | |
+----------------------------------------------------------------+--------------------+----------------------------------+-------------------+
Callable classes
~~~~~~~~~~~~~~~~
All classes in this subsection are subclasses of Callable_.
+----------------------------------------------------------------------+----------------------+----------------------+-------------------+
| Expression syntax | CodeQL class | Superclasses | Remarks |
+======================================================================+======================+======================+===================+
| ``{`` «``|`` «Parameter_ ``,``»* ``|``»? StmtSequence_ ``}`` | BraceBlock_ | Block_ | |
+----------------------------------------------------------------------+----------------------+----------------------+-------------------+
| ``do`` «``|`` «Parameter_ ``,``»* ``|``»? BodyStmt_ ``end`` | DoBlock_ | Block_, BodyStmt_ | |
+----------------------------------------------------------------------+----------------------+----------------------+-------------------+
| ``-> (`` «Parameter_ ``,``»* ``)`` ``{`` StmtSequence_ ``}`` | Lambda_ | Callable_, BodyStmt_ | |
+----------------------------------------------------------------------+----------------------+----------------------+-------------------+
| ``-> (`` «Parameter_ ``,``»* ``)`` ``do`` BodyStmt_ ``end`` | Lambda_ | Callable_, BodyStmt_ | |
+----------------------------------------------------------------------+----------------------+----------------------+-------------------+
| ``def`` FNAME «Parameter_ ``,``»* TERM BodyStmt_ TERM ``end`` | Method_ | MethodBase_ | |
+----------------------------------------------------------------------+----------------------+----------------------+-------------------+
| ``def self.`` FNAME «Parameter_ ``,``»* TERM BodyStmt_ TERM ``end`` | SingletonMethod_ | MethodBase_ | |
+----------------------------------------------------------------------+----------------------+----------------------+-------------------+
Parameter classes
~~~~~~~~~~~~~~~~~
All classes in this subsection are subclasses of Parameter_.
+------------------------------------------------------------+------------------------+----------------------+--------------------------------------------------------------------+
| Expression syntax | CodeQL class | Superclasses | Remarks |
+============================================================+========================+======================+====================================================================+
| ``&`` IDENTIFIER | BlockParameter_ | NamedParameter_ | |
+------------------------------------------------------------+------------------------+----------------------+--------------------------------------------------------------------+
| ``(`` «IDENTIFIER ``,``»+ ``)`` | DestructuredParameter_ | | |
+------------------------------------------------------------+------------------------+----------------------+--------------------------------------------------------------------+
| ``...`` | ForwardParameter_ | | |
+------------------------------------------------------------+------------------------+----------------------+--------------------------------------------------------------------+
| ``**nil`` | HashSplatNilParameter_ | | Indicates that there are no keyword parameters or keyword patterns |
+------------------------------------------------------------+------------------------+----------------------+--------------------------------------------------------------------+
| ``**`` IDENTIFIER | HashSplatParameter_ | NamedParameter_ | |
+------------------------------------------------------------+------------------------+----------------------+--------------------------------------------------------------------+
| IDENTIFIER ``:`` «Expr_»? | KeywordParameter_ | NamedParameter_ | |
+------------------------------------------------------------+------------------------+----------------------+--------------------------------------------------------------------+
| IDENTIFIER ``=`` Expr_ | OptionalParameter_ | NamedParameter_ | |
+------------------------------------------------------------+------------------------+----------------------+--------------------------------------------------------------------+
| IDENTIFIER | SimpleParameter_ | NamedParameter_ | |
+------------------------------------------------------------+------------------------+----------------------+--------------------------------------------------------------------+
| ``*`` IDENTIFIER | SplatParameter_ | NamedParameter_ | |
+------------------------------------------------------------+------------------------+----------------------+--------------------------------------------------------------------+
Pattern classes
~~~~~~~~~~~~~~~
All classes in this subsection are subclasses of CasePattern_. These expressions typically occur when a ``case`` uses pattern matching syntax.
+--------------------------------------------------------------------------------+-----------------------+--------------+-------------------+
| Expression syntax | CodeQL class | Superclasses | Remarks |
+================================================================================+=======================+==============+===================+
| CasePattern_ «``|`` CasePattern_»+ | AlternativePattern_ | CasePattern_ | |
+--------------------------------------------------------------------------------+-----------------------+--------------+-------------------+
| ``[`` «CasePattern ``,``»* «``*`` IDENTIFIER»? ``]`` | ArrayPattern_ | CasePattern_ | |
+--------------------------------------------------------------------------------+-----------------------+--------------+-------------------+
| CasePattern_ ``=>`` IDENTIFIER | AsPattern_ | CasePattern_ | |
+--------------------------------------------------------------------------------+-----------------------+--------------+-------------------+
| ``[`` ``*`` «IDENTIFIER»? (``,`` CasePattern)* ``,`` ``*`` «IDENTIFIER»? ``]`` | FindPattern_ | CasePattern_ | |
+--------------------------------------------------------------------------------+-----------------------+--------------+-------------------+
| ``{`` «StringlikeLiteral_ ``:`` CasePattern ``,``»* «``**`` IDENTIFIER»? ``}`` | HashPattern_ | CasePattern_ | |
+--------------------------------------------------------------------------------+-----------------------+--------------+-------------------+
| ``(`` CasePattern_ ``)`` | ParenthesizedPattern_ | CasePattern_ | |
+--------------------------------------------------------------------------------+-----------------------+--------------+-------------------+
| ``^`` Expr_ | ReferencePattern_ | CasePattern_ | |
+--------------------------------------------------------------------------------+-----------------------+--------------+-------------------+
Expression classes
~~~~~~~~~~~~~~~~~~
All classes in this subsection are subclasses of Expr_.
+--------------------------------------------------------------------------------------+----------------------+---------------+----------------------------------------------------------------------------------------+
| Expression syntax | CodeQL class | Superclasses | Remarks |
+======================================================================================+======================+===============+========================================================================================+
| «Expr_ ``,``»+ | ArgumentList_ | Expr_ | The right-hand side of an assignment or a ``return``, ``break``, or ``next`` statement |
+--------------------------------------------------------------------------------------+----------------------+---------------+----------------------------------------------------------------------------------------+
| StmtSequence_ «RescueClause_»? «``else`` StmtSequence_»? «``ensure`` StmtSequence_»? | BodyStmt_ | StmtSequence_ | |
+--------------------------------------------------------------------------------------+----------------------+---------------+----------------------------------------------------------------------------------------+
| Expr_ «``,`` Expr_»+ | DestructuredLhsExpr_ | LhsExpr_ | |
+--------------------------------------------------------------------------------------+----------------------+---------------+----------------------------------------------------------------------------------------+
| Expr_ | LhsExpr_ | Expr_ | An Expr_ appearing on the left-hand side of various operations. Can take many forms. |
+--------------------------------------------------------------------------------------+----------------------+---------------+----------------------------------------------------------------------------------------+
| Expr_ ``:`` Expr_ | Pair_ | Expr_ | Such as in a hash or as a keyword argument |
+--------------------------------------------------------------------------------------+----------------------+---------------+----------------------------------------------------------------------------------------+
| ``(`` StmtSequence_ ``)`` | ParenthesizedExpr_ | StmtSequence_ | |
+--------------------------------------------------------------------------------------+----------------------+---------------+----------------------------------------------------------------------------------------+
| ``rescue`` StmtSequence_ | RescueClause_ | Expr_ | |
+--------------------------------------------------------------------------------------+----------------------+---------------+----------------------------------------------------------------------------------------+
| Stmt_ ``rescue`` Stmt_ | RescueModifierExpr_ | Expr_ | |
+--------------------------------------------------------------------------------------+----------------------+---------------+----------------------------------------------------------------------------------------+
| StmtSequence_ TERM Stmt_ | StmtSequence_ | Expr_ | A sequence of 0 or more statements, separated by semicolons or newlines |
+--------------------------------------------------------------------------------------+----------------------+---------------+----------------------------------------------------------------------------------------+
| StringLiteral_ StringLiteral_ | StringConcatenation_ | Expr_ | Implicit concatenation of consecutive string literals |
+--------------------------------------------------------------------------------------+----------------------+---------------+----------------------------------------------------------------------------------------+
Variable classes
~~~~~~~~~~~~~~~~
All classes in this subsection are subclasses of VariableAccess_.
+----------------------------+------------------------------+-----------------------------------------------+------------------+
| Example expression syntax | CodeQL class | Superclasses | Remarks |
+============================+==============================+===============================================+==================+
| ``@@foo`` | ClassVariableReadAccess_ | VariableReadAccess_, ClassVariableAccess_ | |
+----------------------------+------------------------------+-----------------------------------------------+------------------+
| ``@@foo = 'str'`` | ClassVariableWriteAccess_ | VariableWriteAccess_, ClassVariableAccess_ | |
+----------------------------+------------------------------+-----------------------------------------------+------------------+
| ``$foo`` | GlobalVariableReadAccess_ | VariableReadAccess_, GlobalVariableAccess_ | |
+----------------------------+------------------------------+-----------------------------------------------+------------------+
| ``$foo = 'str'`` | GlobalVariableWriteAccess_ | VariableWriteAccess_, GlobalVariableAccess_ | |
+----------------------------+------------------------------+-----------------------------------------------+------------------+
| ``@foo`` | InstanceVariableReadAccess_ | VariableReadAccess_, InstanceVariableAccess_ | |
+----------------------------+------------------------------+-----------------------------------------------+------------------+
| ``@foo = 'str'`` | InstanceVariableWriteAccess_ | VariableWriteAccess_, InstanceVariableAccess_ | |
+----------------------------+------------------------------+-----------------------------------------------+------------------+
| ``foo`` | LocalVariableReadAccess_ | VariableReadAccess_, LocalVariableAccess_ | |
+----------------------------+------------------------------+-----------------------------------------------+------------------+
| ``foo = 'str'`` | LocalVariableWriteAccess_ | VariableWriteAccess_, LocalVariableAccess_ | |
+----------------------------+------------------------------+-----------------------------------------------+------------------+
| ``self`` | SelfVariableReadAccess_ | VariableReadAccess_, SelfVariableAccess_ | |
+----------------------------+------------------------------+-----------------------------------------------+------------------+
Syntactic sugar and desugaring
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Certain Ruby language features are shorthands for common operations that could also be expressed in other, more verbose, forms.
Such language features are typically referred to as "syntactic sugar", and make it easier for programmers to write and read code. This is
great for programmers. For source code analyzers, however, this leads to additional work as they need to understand the shorthand notation as well as the long form. To make analysis easier, CodeQL automatically "desugars" Ruby code, effectively rewriting
rich syntactic constructs into equivalent code that uses simpler syntactic constructs.
For example, supposing that ``x`` is an object with an attribute ``foo``, the assignment::
x.foo = y
is desugared to code similar to::
x.foo=(__synth_0 = y);
__synth_0;
In other words, there is effectively a call to the SetterMethodCall_ ``foo=`` on ``x`` with argument ``__synth_0 = y``, followed by a read of the ``__synth_0`` variable.
In CodeQL, this is implemented by synthesizing AstNode_ instances corresponding to this desugared version of the code.
Note that the original AssignExpr_ and the desugared SetterMethodCall_ versions are both available to use in CodeQL queries, and you do not usually need to be aware of any desugaring that may take place. However, if a codebase explicitly uses ``x.foo=(y)`` SetterMethodCall_ syntax, you cannot find this syntax by searching for instances of AssignExpr_ .
Other synthesized AstNode_ instances exist, see the isSynthesized_ and getDesugared_ predicates for details.
Further reading
---------------
.. include:: ../reusables/ruby-further-reading.rst
.. include:: ../reusables/codeql-ref-tools-further-reading.rst
.. _BlockArgument: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Call.qll/type.Call$BlockArgument.html
.. _Call: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Call.qll/type.Call$Call.html
.. _ElementReference: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Call.qll/type.Call$ElementReference.html
.. _ForwardedArguments: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Call.qll/type.Call$ForwardedArguments.html
.. _MethodCall: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Call.qll/type.Call$MethodCall.html
.. _SetterMethodCall: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Call.qll/type.Call$SetterMethodCall.html
.. _SuperCall: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Call.qll/type.Call$SuperCall.html
.. _UnknownMethodCall: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Call.qll/type.Call$UnknownMethodCall.html
.. _YieldCall: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Call.qll/type.Call$YieldCall.html
.. _ConstantAccess: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Constant.qll/type.Constant$ConstantAccess.html
.. _ConstantReadAccess: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Constant.qll/type.Constant$ConstantReadAccess.html
.. _ConstantWriteAccess: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Constant.qll/type.Constant$ConstantWriteAccess.html
.. _ConstantAssignment: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Constant.qll/type.Constant$ConstantAssignment.html
.. _ArgumentList: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Expr.qll/type.Expr$ArgumentList.html
.. _BodyStmt: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Expr.qll/type.Expr$BodyStmt.html
.. _DestructuredLhsExpr: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Expr.qll/type.Expr$DestructuredLhsExpr.html
.. _Expr: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Expr.qll/type.Expr$Expr.html
.. _LhsExpr: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Expr.qll/type.Expr$LhsExpr.html
.. _Pair: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Expr.qll/type.Expr$Pair.html
.. _ParenthesizedExpr: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Expr.qll/type.Expr$ParenthesizedExpr.html
.. _RescueClause: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Expr.qll/type.Expr$RescueClause.html
.. _RescueModifierExpr: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Expr.qll/type.Expr$RescueModifierExpr.html
.. _StmtSequence: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Expr.qll/type.Expr$StmtSequence.html
.. _StringConcatenation: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Expr.qll/type.Expr$StringConcatenation.html
.. _ControlExpr: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Control.qll/type.Control$ControlExpr.html
.. _ConditionalExpr: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Control.qll/type.Control$ConditionalExpr.html
.. _Loop: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Control.qll/type.Control$Loop.html
.. _ConditionalLoop: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Control.qll/type.Control$ConditionalLoop.html
.. _ForExpr: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Control.qll/type.Control$ForExpr.html
.. _IfExpr: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Control.qll/type.Control$IfExpr.html
.. _WhileExpr: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Control.qll/type.Control$WhileExpr.html
.. _UntilExpr: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Control.qll/type.Control$UntilExpr.html
.. _IfModifierExpr: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Control.qll/type.Control$IfModifierExpr.html
.. _UnlessModifierExpr: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Control.qll/type.Control$UnlessModifierExpr.html
.. _WhileModifierExpr: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Control.qll/type.Control$WhileModifierExpr.html
.. _UntilModifierExpr: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Control.qll/type.Control$UntilModifierExpr.html
.. _TernaryIfExpr: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Control.qll/type.Control$TernaryIfExpr.html
.. _CaseExpr: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Control.qll/type.Control$CaseExpr.html
.. _AstNode: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/AST.qll/type.AST$AstNode.html
.. _ArrayLiteral: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Literal.qll/type.Literal$ArrayLiteral.html
.. _BooleanLiteral: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Literal.qll/type.Literal$BooleanLiteral.html
.. _CharacterLiteral: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Literal.qll/type.Literal$CharacterLiteral.html
.. _ComplexLiteral: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Literal.qll/type.Literal$ComplexLiteral.html
.. _EncodingLiteral: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Literal.qll/type.Literal$EncodingLiteral.html
.. _FileLiteral: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Literal.qll/type.Literal$FileLiteral.html
.. _FloatLiteral: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Literal.qll/type.Literal$FloatLiteral.html
.. _HashLiteral: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Literal.qll/type.Literal$HashLiteral.html
.. _HereDoc: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Literal.qll/type.Literal$HereDoc.html
.. _IntegerLiteral: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Literal.qll/type.Literal$IntegerLiteral.html
.. _LineLiteral: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Literal.qll/type.Literal$LineLiteral.html
.. _Literal: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Literal.qll/type.Literal$Literal.html
.. _MethodName: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Literal.qll/type.Literal$MethodName.html
.. _NilLiteral: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Literal.qll/type.Literal$NilLiteral.html
.. _NumericLiteral: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Literal.qll/type.Literal$NumericLiteral.html
.. _RangeLiteral: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Literal.qll/type.Literal$RangeLiteral.html
.. _RationalLiteral: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Literal.qll/type.Literal$RationalLiteral.html
.. _RegExpComponent: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Literal.qll/type.Literal$RegExpComponent.html
.. _RegExpEscapeSequenceComponent: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Literal.qll/type.Literal$RegExpEscapeSequenceComponent.html
.. _RegExpInterpolationComponent: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Literal.qll/type.Literal$RegExpInterpolationComponent.html
.. _RegExpLiteral: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Literal.qll/type.Literal$RegExpLiteral.html
.. _RegExpTextComponent: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Literal.qll/type.Literal$RegExpTextComponent.html
.. _StringComponent: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Literal.qll/type.Literal$StringComponent.html
.. _StringEscapeSequenceComponent: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Literal.qll/type.Literal$StringEscapeSequenceComponent.html
.. _StringInterpolationComponent: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Literal.qll/type.Literal$StringInterpolationComponent.html
.. _StringLiteral: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Literal.qll/type.Literal$StringLiteral.html
.. _StringTextComponent: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Literal.qll/type.Literal$StringTextComponent.html
.. _StringlikeLiteral: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Literal.qll/type.Literal$StringlikeLiteral.html
.. _SubshellLiteral: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Literal.qll/type.Literal$SubshellLiteral.html
.. _SymbolLiteral: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Literal.qll/type.Literal$SymbolLiteral.html
.. _Block: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Method.qll/type.Method$Block.html
.. _BraceBlock: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Method.qll/type.Method$BraceBlock.html
.. _Callable: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Method.qll/type.Method$Callable.html
.. _DoBlock: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Method.qll/type.Method$DoBlock.html
.. _Lambda: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Method.qll/type.Method$Lambda.html
.. _Method: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Method.qll/type.Method$Method.html
.. _MethodBase: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Method.qll/type.Method$MethodBase.html
.. _SingletonMethod: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Method.qll/type.Method$SingletonMethod.html
.. _ClassDeclaration: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Module.qll/type.Module$ClassDeclaration.html
.. _Module: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Module.qll/type.Module$Module.html
.. _ModuleBase: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Module.qll/type.Module$ModuleBase.html
.. _ModuleDeclaration: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Module.qll/type.Module$ModuleDeclaration.html
.. _Namespace: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Module.qll/type.Module$Namespace.html
.. _SingletonClass: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Module.qll/type.Module$SingletonClass.html
.. _Toplevel: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Module.qll/type.Module$Toplevel.html
.. _AddExpr: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Operation.qll/type.Operation$AddExpr.html
.. _AssignAddExpr: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Operation.qll/type.Operation$AssignAddExpr.html
.. _AssignArithmeticOperation: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Operation.qll/type.Operation$AssignArithmeticOperation.html
.. _AssignBitwiseAndExpr: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Operation.qll/type.Operation$AssignBitwiseAndExpr.html
.. _AssignBitwiseOperation: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Operation.qll/type.Operation$AssignBitwiseOperation.html
.. _AssignBitwiseOrExpr: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Operation.qll/type.Operation$AssignBitwiseOrExpr.html
.. _AssignBitwiseXorExpr: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Operation.qll/type.Operation$AssignBitwiseXorExpr.html
.. _AssignDivExpr: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Operation.qll/type.Operation$AssignDivExpr.html
.. _AssignExponentExpr: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Operation.qll/type.Operation$AssignExponentExpr.html
.. _AssignExpr: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Operation.qll/type.Operation$AssignExpr.html
.. _AssignLShiftExpr: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Operation.qll/type.Operation$AssignLShiftExpr.html
.. _AssignLogicalAndExpr: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Operation.qll/type.Operation$AssignLogicalAndExpr.html
.. _AssignLogicalOperation: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Operation.qll/type.Operation$AssignLogicalOperation.html
.. _AssignLogicalOrExpr: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Operation.qll/type.Operation$AssignLogicalOrExpr.html
.. _AssignModuloExpr: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Operation.qll/type.Operation$AssignModuloExpr.html
.. _AssignMulExpr: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Operation.qll/type.Operation$AssignMulExpr.html
.. _AssignOperation: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Operation.qll/type.Operation$AssignOperation.html
.. _AssignRShiftExpr: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Operation.qll/type.Operation$AssignRShiftExpr.html
.. _AssignSubExpr: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Operation.qll/type.Operation$AssignSubExpr.html
.. _Assignment: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Operation.qll/type.Operation$Assignment.html
.. _BinaryArithmeticOperation: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Operation.qll/type.Operation$BinaryArithmeticOperation.html
.. _BinaryBitwiseOperation: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Operation.qll/type.Operation$BinaryBitwiseOperation.html
.. _BinaryLogicalOperation: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Operation.qll/type.Operation$BinaryLogicalOperation.html
.. _BinaryOperation: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Operation.qll/type.Operation$BinaryOperation.html
.. _BitwiseAndExpr: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Operation.qll/type.Operation$BitwiseAndExpr.html
.. _BitwiseOrExpr: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Operation.qll/type.Operation$BitwiseOrExpr.html
.. _BitwiseXorExpr: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Operation.qll/type.Operation$BitwiseXorExpr.html
.. _CaseEqExpr: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Operation.qll/type.Operation$CaseEqExpr.html
.. _ComparisonOperation: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Operation.qll/type.Operation$ComparisonOperation.html
.. _ComplementExpr: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Operation.qll/type.Operation$ComplementExpr.html
.. _DefinedExpr: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Operation.qll/type.Operation$DefinedExpr.html
.. _DivExpr: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Operation.qll/type.Operation$DivExpr.html
.. _EqExpr: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Operation.qll/type.Operation$EqExpr.html
.. _EqualityOperation: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Operation.qll/type.Operation$EqualityOperation.html
.. _ExponentExpr: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Operation.qll/type.Operation$ExponentExpr.html
.. _GEExpr: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Operation.qll/type.Operation$GEExpr.html
.. _GTExpr: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Operation.qll/type.Operation$GTExpr.html
.. _HashSplatExpr: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Operation.qll/type.Operation$HashSplatExpr.html
.. _LEExpr: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Operation.qll/type.Operation$LEExpr.html
.. _LShiftExpr: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Operation.qll/type.Operation$LShiftExpr.html
.. _LTExpr: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Operation.qll/type.Operation$LTExpr.html
.. _LogicalAndExpr: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Operation.qll/type.Operation$LogicalAndExpr.html
.. _LogicalOrExpr: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Operation.qll/type.Operation$LogicalOrExpr.html
.. _ModuloExpr: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Operation.qll/type.Operation$ModuloExpr.html
.. _MulExpr: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Operation.qll/type.Operation$MulExpr.html
.. _NEExpr: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Operation.qll/type.Operation$NEExpr.html
.. _NoRegExpMatchExpr: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Operation.qll/type.Operation$NoRegExpMatchExpr.html
.. _NotExpr: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Operation.qll/type.Operation$NotExpr.html
.. _Operation: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Operation.qll/type.Operation$Operation.html
.. _RShiftExpr: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Operation.qll/type.Operation$RShiftExpr.html
.. _RegExpMatchExpr: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Operation.qll/type.Operation$RegExpMatchExpr.html
.. _RelationalOperation: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Operation.qll/type.Operation$RelationalOperation.html
.. _SpaceshipExpr: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Operation.qll/type.Operation$SpaceshipExpr.html
.. _SplatExpr: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Operation.qll/type.Operation$SplatExpr.html
.. _SubExpr: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Operation.qll/type.Operation$SubExpr.html
.. _UnaryArithmeticOperation: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Operation.qll/type.Operation$UnaryArithmeticOperation.html
.. _UnaryBitwiseOperation: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Operation.qll/type.Operation$UnaryBitwiseOperation.html
.. _UnaryLogicalOperation: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Operation.qll/type.Operation$UnaryLogicalOperation.html
.. _UnaryMinusExpr: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Operation.qll/type.Operation$UnaryMinusExpr.html
.. _UnaryOperation: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Operation.qll/type.Operation$UnaryOperation.html
.. _UnaryPlusExpr: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Operation.qll/type.Operation$UnaryPlusExpr.html
.. _BlockParameter: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Parameter.qll/type.Parameter$BlockParameter.html
.. _DestructuredParameter: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Parameter.qll/type.Parameter$DestructuredParameter.html
.. _ForwardParameter: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Parameter.qll/type.Parameter$ForwardParameter.html
.. _HashSplatNilParameter: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Parameter.qll/type.Parameter$HashSplatNilParameter.html
.. _HashSplatParameter: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Parameter.qll/type.Parameter$HashSplatParameter.html
.. _KeywordParameter: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Parameter.qll/type.Parameter$KeywordParameter.html
.. _NamedParameter: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Parameter.qll/type.Parameter$NamedParameter.html
.. _OptionalParameter: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Parameter.qll/type.Parameter$OptionalParameter.html
.. _Parameter: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Parameter.qll/type.Parameter$Parameter.html
.. _SimpleParameter: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Parameter.qll/type.Parameter$SimpleParameter.html
.. _SplatParameter: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Parameter.qll/type.Parameter$SplatParameter.html
.. _AlternativePattern: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Pattern.qll/type.Pattern$AlternativePattern.html
.. _ArrayPattern: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Pattern.qll/type.Pattern$ArrayPattern.html
.. _AsPattern: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Pattern.qll/type.Pattern$AsPattern.html
.. _CasePattern: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Pattern.qll/type.Pattern$CasePattern.html
.. _FindPattern: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Pattern.qll/type.Pattern$FindPattern.html
.. _HashPattern: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Pattern.qll/type.Pattern$HashPattern.html
.. _ParenthesizedPattern: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Pattern.qll/type.Pattern$ParenthesizedPattern.html
.. _ReferencePattern: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Pattern.qll/type.Pattern$ReferencePattern.html
.. _Scope: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Scope.qll/type.Scope$Scope.html
.. _SelfScope: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Scope.qll/type.Scope$SelfScope.html
.. _AliasStmt: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Statement.qll/type.Statement$AliasStmt.html
.. _BeginBlock: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Statement.qll/type.Statement$BeginBlock.html
.. _BeginExpr: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Statement.qll/type.Statement$BeginExpr.html
.. _BreakStmt: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Statement.qll/type.Statement$BreakStmt.html
.. _EmptyStmt: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Statement.qll/type.Statement$EmptyStmt.html
.. _EndBlock: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Statement.qll/type.Statement$EndBlock.html
.. _NextStmt: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Statement.qll/type.Statement$NextStmt.html
.. _RedoStmt: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Statement.qll/type.Statement$RedoStmt.html
.. _RetryStmt: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Statement.qll/type.Statement$RetryStmt.html
.. _ReturnStmt: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Statement.qll/type.Statement$ReturnStmt.html
.. _ReturningStmt: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Statement.qll/type.Statement$ReturningStmt.html
.. _Stmt: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Statement.qll/type.Statement$Stmt.html
.. _UndefStmt: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Statement.qll/type.Statement$UndefStmt.html
.. _ClassVariable: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Variable.qll/type.Variable$ClassVariable.html
.. _ClassVariableAccess: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Variable.qll/type.Variable$ClassVariableAccess.html
.. _ClassVariableReadAccess: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Variable.qll/type.Variable$ClassVariableReadAccess.html
.. _ClassVariableWriteAccess: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Variable.qll/type.Variable$ClassVariableWriteAccess.html
.. _GlobalVariable: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Variable.qll/type.Variable$GlobalVariable.html
.. _GlobalVariableAccess: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Variable.qll/type.Variable$GlobalVariableAccess.html
.. _GlobalVariableReadAccess: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Variable.qll/type.Variable$GlobalVariableReadAccess.html
.. _GlobalVariableWriteAccess: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Variable.qll/type.Variable$GlobalVariableWriteAccess.html
.. _InstanceVariable: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Variable.qll/type.Variable$InstanceVariable.html
.. _InstanceVariableAccess: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Variable.qll/type.Variable$InstanceVariableAccess.html
.. _InstanceVariableReadAccess: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Variable.qll/type.Variable$InstanceVariableReadAccess.html
.. _InstanceVariableWriteAccess: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Variable.qll/type.Variable$InstanceVariableWriteAccess.html
.. _LocalVariable: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Variable.qll/type.Variable$LocalVariable.html
.. _LocalVariableAccess: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Variable.qll/type.Variable$LocalVariableAccess.html
.. _LocalVariableReadAccess: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Variable.qll/type.Variable$LocalVariableReadAccess.html
.. _LocalVariableWriteAccess: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Variable.qll/type.Variable$LocalVariableWriteAccess.html
.. _SelfVariable: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Variable.qll/type.Variable$SelfVariable.html
.. _SelfVariableAccess: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Variable.qll/type.Variable$SelfVariableAccess.html
.. _SelfVariableReadAccess: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Variable.qll/type.Variable$SelfVariableReadAccess.html
.. _Variable: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Variable.qll/type.Variable$Variable.html
.. _VariableAccess: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Variable.qll/type.Variable$VariableAccess.html
.. _VariableReadAccess: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Variable.qll/type.Variable$VariableReadAccess.html
.. _VariableWriteAccess: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/ast/Variable.qll/type.Variable$VariableWriteAccess.html
.. _isSynthesized: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/AST.qll/predicate.AST$AstNode$isSynthesized.0.html
.. _getDesugared: https://codeql.github.com/codeql-standard-libraries/ruby/codeql/ruby/AST.qll/predicate.AST$AstNode$getDesugared.0.html

View File

@@ -0,0 +1,393 @@
.. _analyzing-data-flow-in-ruby:
Analyzing data flow in Ruby
=============================
You can use CodeQL to track the flow of data through a Ruby program to places where the data is used.
About this article
------------------
This article describes how data flow analysis is implemented in the CodeQL libraries for Ruby 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 ":ref:`About data flow analysis <about-data-flow-analysis>`."
Local data flow
---------------
Local data flow tracks the flow of data within a single method or callable. Local data flow is easier, faster, and more precise than global data flow. Before looking at more complex tracking, you should always consider local tracking because it is sufficient for many queries.
Using local data flow
~~~~~~~~~~~~~~~~~~~~~
You can use the local data flow library by importing the ``DataFlow`` module. The library uses the class ``Node`` to represent any element through which data can flow.
``Node``\ s are divided into expression nodes (``ExprNode``) and parameter nodes (``ParameterNode``).
You can map a data flow ``ParameterNode`` to its corresponding ``Parameter`` AST node using the ``asParameter`` member predicate.
Similarly, you can use the ``asExpr`` member predicate to map a data flow ``ExprNode`` to its corresponding ``ExprCfgNode`` in the control-flow library.
.. code-block:: ql
class Node {
/** Gets the expression corresponding to this node, if any. */
CfgNodes::ExprCfgNode asExpr() { ... }
/** Gets the parameter corresponding to this node, if any. */
Parameter asParameter() { ... }
...
}
You can use the predicates ``exprNode`` and ``parameterNode`` to map from expressions and parameters to their data-flow node:
.. code-block:: ql
/**
* Gets a node corresponding to expression `e`.
*/
ExprNode exprNode(CfgNodes::ExprCfgNode e) { ... }
/**
* Gets the node corresponding to the value of parameter `p` at function entry.
*/
ParameterNode parameterNode(Parameter p) { ... }
Note that since ``asExpr`` and ``exprNode`` map between data-flow and control-flow nodes, you then need to call the ``getExpr`` member predicate on the control-flow node to map to the corresponding AST node,
for example, by writing ``node.asExpr().getExpr()``.
A control-flow graph considers every way control can flow through code, consequently, there can be multiple data-flow and control-flow nodes associated with a single expression node in the AST.
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, you can find flow from an expression ``source`` to an expression ``sink`` in zero or more local steps:
.. code-block:: ql
DataFlow::localFlow(source, sink)
Using local taint tracking
~~~~~~~~~~~~~~~~~~~~~~~~~~
Local taint tracking extends local data flow to include flow steps where values are not preserved, for example, string manipulation.
For example:
.. code-block:: ruby
temp = x
y = temp + ", " + temp
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``.
You can apply the predicate recursively, by using the ``+`` and ``*`` operators, or you can use the predefined recursive predicate ``localTaint``.
For example, you can find taint propagation from an expression ``source`` to an expression ``sink`` in zero or more local steps:
.. code-block:: ql
TaintTracking::localTaint(source, sink)
Using local sources
~~~~~~~~~~~~~~~~~~~
When exploring local data flow or taint propagation between two expressions as above, you would normally constrain the expressions to be relevant to your investigation.
The next section gives some concrete examples, but first it's helpful to introduce the concept of a local source.
A local source is a data-flow node with no local data flow into it.
As such, it is a local origin of data flow, a place where a new value is created.
This includes parameters (which only receive values from global data flow) and most expressions (because they are not value-preserving).
The class ``LocalSourceNode`` represents data-flow nodes that are also local sources.
It comes with a useful member predicate ``flowsTo(DataFlow::Node node)``, which holds if there is local data flow from the local source to ``node``.
Examples of local data flow
~~~~~~~~~~~~~~~~~~~~~~~~~~~
This query finds the filename argument passed in each call to ``File.open``:
.. code-block:: ql
import codeql.ruby.DataFlow
import codeql.ruby.ApiGraphs
from DataFlow::CallNode call
where call = API::getTopLevelMember("File").getAMethodCall("open")
select call.getArgument(0)
Notice the use of the ``API`` module for referring to library methods.
For more information, see ":doc:`Using API graphs in Ruby <using-api-graphs-in-ruby>`."
Unfortunately this will only give the expression in the argument, not the values which could be passed to it.
So we use local data flow to find all expressions that flow into the argument:
.. code-block:: ql
import codeql.ruby.DataFlow
import codeql.ruby.ApiGraphs
from DataFlow::CallNode call, DataFlow::ExprNode expr
where
call = API::getTopLevelMember("File").getAMethodCall("open") and
DataFlow::localFlow(expr, call.getArgument(0))
select call, expr
Many expressions flow to the same call.
If you run this query, you may notice that you get several data-flow nodes for an expression as it flows towards a call (notice repeated locations in the ``call`` column).
We are mostly interested in the "first" of these, what might be called the local source for the file name.
To restrict the results to local sources for the file name, and to simultaneously make the analysis more efficient, we can use the CodeQL class ``LocalSourceNode``.
We can update the query to specify that ``expr`` is an instance of a ``LocalSourceNode``.
.. code-block:: ql
import codeql.ruby.DataFlow
import codeql.ruby.ApiGraphs
from DataFlow::CallNode call, DataFlow::ExprNode expr
where
call = API::getTopLevelMember("File").getAMethodCall("open") and
DataFlow::localFlow(expr, call.getArgument(0)) and
expr instanceof DataFlow::LocalSourceNode
select call, expr
An alternative approach to limit the results to local sources for the file name is to enforce this by casting.
That would allow us to use the member predicate ``flowsTo`` on ``LocalSourceNode`` like so:
.. code-block:: ql
import codeql.ruby.DataFlow
import codeql.ruby.ApiGraphs
from DataFlow::CallNode call, DataFlow::ExprNode expr
where
call = API::getTopLevelMember("File").getAMethodCall("open") and
expr.(DataFlow::LocalSourceNode).flowsTo(call.getArgument(0))
select call, expr
As an alternative, we can ask more directly that ``expr`` is a local source of the first argument, via the predicate ``getALocalSource``:
.. code-block:: ql
import codeql.ruby.DataFlow
import codeql.ruby.ApiGraphs
from DataFlow::CallNode call, DataFlow::ExprNode expr
where
call = API::getTopLevelMember("File").getAMethodCall("open") and
expr = call.getArgument(0).getALocalSource()
select call, expr
All these three queries give identical results.
We now mostly have one expression per call.
We may still have cases of more than one expression flowing to a call, but then they flow through different code paths (possibly due to control-flow splitting).
We might want to make the source more specific, for example, a parameter to a method or block.
This query finds instances where a parameter is used as the name when opening a file:
.. code-block:: ql
import codeql.ruby.DataFlow
import codeql.ruby.ApiGraphs
from DataFlow::CallNode call, DataFlow::ParameterNode p
where
call = API::getTopLevelMember("File").getAMethodCall("open") and
DataFlow::localFlow(p, call.getArgument(0))
select call, p
Using the exact name supplied via the parameter may be too strict.
If we want to know if the parameter influences the file name, we can use taint tracking instead of data flow.
This query finds calls to ``File.open`` where the file name is derived from a parameter:
.. code-block:: ql
import codeql.ruby.DataFlow
import codeql.ruby.TaintTracking
import codeql.ruby.ApiGraphs
from DataFlow::CallNode call, DataFlow::ParameterNode p
where
call = API::getTopLevelMember("File").getAMethodCall("open") and
TaintTracking::localTaint(p, call.getArgument(0))
select call, p
Global data flow
----------------
Global data flow tracks data flow throughout the entire program, and is therefore more powerful than local data flow.
However, global data flow is less precise than local data flow, and the analysis typically requires significantly more time and memory to perform.
.. pull-quote:: Note
.. include:: ../reusables/path-problem.rst
Using global data flow
~~~~~~~~~~~~~~~~~~~~~~
You can use the global data flow library by extending the class ``DataFlow::Configuration``:
.. code-block:: ql
import codeql.ruby.DataFlow
class MyDataFlowConfiguration extends DataFlow::Configuration {
MyDataFlowConfiguration() { this = "..." }
override predicate isSource(DataFlow::Node source) {
...
}
override predicate isSink(DataFlow::Node sink) {
...
}
}
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.
The characteristic predicate (``MyDataFlowConfiguration()``) defines the name of the configuration, so ``"..."`` must be replaced with a unique name (for instance the class name).
The data flow analysis is performed using the predicate ``hasFlow(DataFlow::Node source, DataFlow::Node sink)``:
.. code-block:: ql
from MyDataFlowConfiguation dataflow, DataFlow::Node source, DataFlow::Node sink
where dataflow.hasFlow(source, sink)
select source, "Dataflow to $@.", sink, sink.toString()
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``:
.. code-block:: ql
import codeql.ruby.DataFlow
import codeql.ruby.TaintTracking
class MyTaintTrackingConfiguration extends TaintTracking::Configuration {
MyTaintTrackingConfiguration() { this = "..." }
override predicate isSource(DataFlow::Node source) {
...
}
override predicate isSink(DataFlow::Node sink) {
...
}
}
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.
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)``.
Predefined sources and sinks
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The data flow library contains a number of predefined sources and sinks, providing a good starting point for defining data flow based security queries.
- The class ``RemoteFlowSource`` (defined in module ``codeql.ruby.dataflow.RemoteFlowSources``) represents data flow from remote network inputs. This is useful for finding security problems in networked services.
- The library ``Concepts`` (defined in module ``codeql.ruby.Concepts``) contains several subclasses of ``DataFlow::Node`` that are security relevant, such as ``FileSystemAccess`` and ``SqlExecution``.
For global flow, it is also useful to restrict sources to instances of ``LocalSourceNode``.
The predefined sources generally do that.
Class hierarchy
~~~~~~~~~~~~~~~
- ``DataFlow::Configuration`` - base class for custom global data flow analysis.
- ``DataFlow::Node`` - an element behaving as a data-flow node.
- ``DataFlow::LocalSourceNode`` - a local origin of data, 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 method/block entry.
- ``RemoteFlowSource`` - data flow from network/remote input.
- ``Concepts::SystemCommandExecution`` - a data-flow node that executes an operating system command, for instance by spawning a new process.
- ``Concepts::FileSystemAccess`` - a data-flow node that performs a file system access, including reading and writing data, creating and deleting files and folders, checking and updating permissions, and so on.
- ``Concepts::Path::PathNormalization`` - a data-flow node that performs path normalization. This is often needed in order to safely access paths.
- ``Concepts::CodeExecution`` - a data-flow node that dynamically executes Ruby code.
- ``Concepts::SqlExecution`` - a data-flow node that executes SQL statements.
- ``Concepts::HTTP::Server::RouteSetup`` - a data-flow node that sets up a route on a server.
- ``Concepts::HTTP::Server::HttpResponse`` - a data-flow node that creates an HTTP response on a server.
- ``TaintTracking::Configuration`` - base class for custom global taint tracking analysis.
Examples of global data flow
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The following global taint-tracking query finds path arguments in filesystem accesses that can be controlled by a remote user.
- Since this is a taint-tracking query, the configuration class extends ``TaintTracking::Configuration``.
- The ``isSource`` predicate defines sources as any data-flow nodes that are instances of ``RemoteFlowSource``.
- The ``isSink`` predicate defines sinks as path arguments in any filesystem access, using ``FileSystemAccess`` from the ``Concepts`` library.
.. code-block:: ql
import codeql.ruby.DataFlow
import codeql.ruby.TaintTracking
import codeql.ruby.Concepts
import codeql.ruby.dataflow.RemoteFlowSources
class RemoteToFileConfiguration extends TaintTracking::Configuration {
RemoteToFileConfiguration() { this = "RemoteToFileConfiguration" }
override predicate isSource(DataFlow::Node source) { source instanceof RemoteFlowSource }
override predicate isSink(DataFlow::Node sink) {
sink = any(FileSystemAccess fa).getAPathArgument()
}
}
from DataFlow::Node input, DataFlow::Node fileAccess, RemoteToFileConfiguration config
where config.hasFlow(input, fileAccess)
select fileAccess, "This file access uses data from $@.", input, "user-controllable input."
The following global data-flow query finds calls to ``File.open`` where the filename argument comes from an environment variable.
- Since this is a data-flow query, the configuration class extends ``DataFlow::Configuration``.
- The ``isSource`` predicate defines sources as expression nodes representing lookups on the ``ENV`` hash.
- The ``isSink`` predicate defines sinks as the first argument in any call to ``File.open``.
.. code-block:: ql
import codeql.ruby.DataFlow
import codeql.ruby.controlflow.CfgNodes
import codeql.ruby.ApiGraphs
class EnvironmentToFileConfiguration extends DataFlow::Configuration {
EnvironmentToFileConfiguration() { this = "EnvironmentToFileConfiguration" }
override predicate isSource(DataFlow::Node source) {
exists(ExprNodes::ConstantReadAccessCfgNode env |
env.getExpr().getName() = "ENV" and
env = source.asExpr().(ExprNodes::ElementReferenceCfgNode).getReceiver()
)
}
override predicate isSink(DataFlow::Node sink) {
sink = API::getTopLevelMember("File").getAMethodCall("open").getArgument(0)
}
}
from EnvironmentToFileConfiguration config, DataFlow::Node environment, DataFlow::Node fileOpen
where config.hasFlow(environment, fileOpen)
select fileOpen, "This call to 'File.open' uses data from $@.", environment,
"an environment variable"
Further reading
---------------
- ":ref:`Exploring data flow with path queries <exploring-data-flow-with-path-queries>`"
.. include:: ../reusables/ruby-further-reading.rst
.. include:: ../reusables/codeql-ref-tools-further-reading.rst

View File

@@ -80,7 +80,7 @@ After the initial ``import`` statement, this simple query comprises three parts
+---------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------+
| Query part | Purpose | Details |
+===============================================================+===================================================================================================================+========================================================================================================================+
| ``import codeql.ruby.AST`` | Imports the standard CodeQL AST libraries for Ruby. | Every query begins with one or more ``import`` statements. |
| ``import codeql.ruby.AST`` | Imports the standard CodeQL AST libraries for Ruby. | Every query begins with one or more ``import`` statements. |
+---------------------------------------------------------------+-------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------------------------------+
| ``from IfExpr ifexpr`` | Defines the variables for the query. | We use: an ``IfExpr`` variable for ``if`` expressions. |
| | Declarations are of the form: | |

View File

@@ -10,9 +10,16 @@ Experiment and learn how to write effective and efficient queries for CodeQL dat
basic-query-for-ruby-code
codeql-library-for-ruby
abstract-syntax-tree-classes-for-working-with-ruby-programs
analyzing-data-flow-in-ruby
using-api-graphs-in-ruby
- :doc:`Basic query for Ruby code <basic-query-for-ruby-code>`: Learn to write and run a simple CodeQL query using LGTM.
- :doc:`CodeQL library for Ruby <codeql-library-for-ruby>`: When you're analyzing a Ruby program, you can make use of the large collection of classes in the CodeQL library for Ruby.
.. include:: ../reusables/ruby-beta-note.rst
- :doc:`Analyzing data flow in Ruby <analyzing-data-flow-in-ruby>`: You can use CodeQL to track the flow of data through a Ruby program to places where the data is used.
- :doc:`Using API graphs in Ruby <using-api-graphs-in-ruby>`: API graphs are a uniform interface for referring to functions, classes, and methods defined in external libraries.
- :doc:`Abstract syntax tree classes for working with Ruby programs <abstract-syntax-tree-classes-for-working-with-ruby-programs>`: CodeQL has a large selection of classes for representing the abstract syntax tree of Ruby programs.

View File

@@ -0,0 +1,185 @@
.. _using-api-graphs-in-ruby:
Using API graphs in Ruby
==========================
API graphs are a uniform interface for referring to functions, classes, and methods defined in
external libraries.
About this article
------------------
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 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.
.. code-block:: ql
import codeql.ruby.ApiGraphs
select API::getTopLevelMember("Regexp")
The example above finds references to a top-level class. For nested
modules and classes, you can use the ``getMember`` method. For example the following query selects
references to the ``Net::HTTP`` class.
.. code-block:: ql
import codeql.ruby.ApiGraphs
select API::getTopLevelMember("Net").getMember("HTTP")
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
------------------------------
To track the calls of externally defined functions, you can use the ``getMethod`` method. The
following snippet finds all calls of ``Regexp.compile``:
.. code-block:: ql
import codeql.ruby.ApiGraphs
select API::getTopLevelMember("Regexp").getMethod("compile")
The example above is for a call to a class method. Tracking calls to instance methods, is a two-step
process, first you need to find instances of the class before you can find the calls
to methods on those instances. The following snippet finds instantiations of the ``Regexp`` class:
.. code-block:: ql
import codeql.ruby.ApiGraphs
select API::getTopLevelMember("Regexp").getInstance()
Note that the ``getInstance`` method also includes subclasses. For example if there is a
``class SpecialRegexp < Regexp`` then ``getInstance`` also finds ``SpecialRegexp.new``.
The following snippet builds on the above to find calls of the ``Regexp#match?`` instance method:
.. code-block:: ql
import codeql.ruby.ApiGraphs
select API::getTopLevelMember("Regexp").getInstance().getMethod("match?")
Subclasses
----------
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
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`` 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.
.. code-block:: ql
import codeql.ruby.ApiGraphs
API::Node actionController() {
result =
[
API::getTopLevelMember("ActionController").getMember("Base"),
API::getTopLevelMember("Rails").getMember("ApplicationController")
].getASubclass*()
}
select actionController()
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.
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
``File.read(path)``:
.. code-block:: ql
import codeql.ruby.ApiGraphs
select API::getTopLevelMember("File").getMethod("read").getReturn().asSource()
The ``asSink()`` method is used to select dataflow nodes where a value leaves the
current code base and flows into an external library. For example the second parameter
of the ``File.write(path, value)`` method.
.. code-block:: ql
import codeql.ruby.ApiGraphs
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, 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 of CodeQL finds parameters of blocks of ``File.open`` method calls:
.. code-block:: ql
import codeql.ruby.ApiGraphs
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``.
.. code-block:: ql
import codeql.ruby.DataFlow
import codeql.ruby.ApiGraphs
class Configuration extends DataFlow::Configuration {
Configuration() { this = "File read/write Configuration" }
override predicate isSource(DataFlow::Node source) {
source = API::getTopLevelMember("File").getMethod("read").getReturn().asSource()
}
override predicate isSink(DataFlow::Node sink) {
sink = API::getTopLevelMember("File").getMethod("write").getParameter(1).asSink()
}
}
from DataFlow::Node src, DataFlow::Node sink, Configuration config
where config.hasFlow(src, sink)
select src, "The data read here flows into a $@ call.", sink, "File.write"
Further reading
---------------
.. include:: ../reusables/ruby-further-reading.rst
.. include:: ../reusables/codeql-ref-tools-further-reading.rst

View File

@@ -35,4 +35,3 @@ Note that the CWE coverage includes both "`supported queries <https://github.com
python-cwe
ruby-cwe
.. include:: ../reusables/ruby-beta-note.rst

View File

@@ -23,8 +23,6 @@ View the query help for the queries included in the ``code-scanning``, ``securit
For a full list of the CWEs covered by these queries, see ":doc:`CodeQL CWE coverage <codeql-cwe-coverage>`."
.. include:: ../reusables/ruby-beta-note.rst
.. toctree::
:hidden:
:titlesonly:

View File

@@ -1,4 +0,0 @@
.. pull-quote:: Note
CodeQL analysis for Ruby is currently in beta. During the beta, analysis of Ruby code,
and the accompanying documentation, will not be as comprehensive as for other languages.