Merge pull request #13901 from hvitved/dataflow/refactor

Data flow: Refactor shared library
This commit is contained in:
Tom Hvitved 2023-08-07 13:22:53 +02:00 коммит произвёл GitHub
Родитель 0d97c1c54a 34864e1077
Коммит 2126ab0dde
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
28 изменённых файлов: 264 добавлений и 265 удалений

Просмотреть файл

@ -1,3 +1,3 @@
private import DataFlowImplSpecific
private import codeql.dataflow.DataFlowImpl
private import codeql.dataflow.internal.DataFlowImpl
import MakeImpl<CppOldDataFlow>

Просмотреть файл

@ -1,3 +1,3 @@
private import DataFlowImplSpecific
private import codeql.dataflow.DataFlowImplCommon
private import codeql.dataflow.internal.DataFlowImplCommon
import MakeImplCommon<CppOldDataFlow>

Просмотреть файл

@ -2,7 +2,7 @@
* Provides C++-specific definitions for use in the data flow library.
*/
private import codeql.dataflow.DataFlowParameter
private import codeql.dataflow.DataFlow
module Private {
import DataFlowPrivate
@ -13,7 +13,7 @@ module Public {
import DataFlowUtil
}
module CppOldDataFlow implements DataFlowParameter {
module CppOldDataFlow implements InputSig {
import Private
import Public

Просмотреть файл

@ -1,3 +1,3 @@
private import DataFlowImplSpecific
private import codeql.dataflow.DataFlowImpl
private import codeql.dataflow.internal.DataFlowImpl
import MakeImpl<CppDataFlow>

Просмотреть файл

@ -1,3 +1,3 @@
private import DataFlowImplSpecific
private import codeql.dataflow.DataFlowImplCommon
private import codeql.dataflow.internal.DataFlowImplCommon
import MakeImplCommon<CppDataFlow>

Просмотреть файл

@ -2,7 +2,7 @@
* Provides IR-specific definitions for use in the data flow library.
*/
private import codeql.dataflow.DataFlowParameter
private import codeql.dataflow.DataFlow
module Private {
import DataFlowPrivate
@ -13,7 +13,7 @@ module Public {
import DataFlowUtil
}
module CppDataFlow implements DataFlowParameter {
module CppDataFlow implements InputSig {
import Private
import Public

Просмотреть файл

@ -1,3 +1,3 @@
private import DataFlowImplSpecific
private import codeql.dataflow.DataFlowImpl
private import codeql.dataflow.internal.DataFlowImpl
import MakeImpl<CsharpDataFlow>

Просмотреть файл

@ -1,3 +1,3 @@
private import DataFlowImplSpecific
private import codeql.dataflow.DataFlowImplCommon
private import codeql.dataflow.internal.DataFlowImplCommon
import MakeImplCommon<CsharpDataFlow>

Просмотреть файл

@ -2,7 +2,7 @@
* Provides C#-specific definitions for use in the data flow library.
*/
private import codeql.dataflow.DataFlowParameter
private import codeql.dataflow.DataFlow
module Private {
import DataFlowPrivate
@ -13,7 +13,7 @@ module Public {
import DataFlowPublic
}
module CsharpDataFlow implements DataFlowParameter {
module CsharpDataFlow implements InputSig {
import Private
import Public

Просмотреть файл

@ -1,3 +1,3 @@
private import DataFlowImplSpecific
private import codeql.dataflow.DataFlowImpl
private import codeql.dataflow.internal.DataFlowImpl
import MakeImpl<GoDataFlow>

Просмотреть файл

@ -1,3 +1,3 @@
private import DataFlowImplSpecific
private import codeql.dataflow.DataFlowImplCommon
private import codeql.dataflow.internal.DataFlowImplCommon
import MakeImplCommon<GoDataFlow>

Просмотреть файл

@ -2,7 +2,7 @@
* Provides Go-specific definitions for use in the data flow library.
*/
private import codeql.dataflow.DataFlowParameter
private import codeql.dataflow.DataFlow
module Private {
import DataFlowPrivate
@ -13,7 +13,7 @@ module Public {
import DataFlowUtil
}
module GoDataFlow implements DataFlowParameter {
module GoDataFlow implements InputSig {
import Private
import Public

Просмотреть файл

@ -1,3 +1,3 @@
private import DataFlowImplSpecific
private import codeql.dataflow.DataFlowImpl
private import codeql.dataflow.internal.DataFlowImpl
import MakeImpl<JavaDataFlow>

Просмотреть файл

@ -1,3 +1,3 @@
private import DataFlowImplSpecific
private import codeql.dataflow.DataFlowImplCommon
private import codeql.dataflow.internal.DataFlowImplCommon
import MakeImplCommon<JavaDataFlow>

Просмотреть файл

@ -2,7 +2,7 @@
* Provides Java-specific definitions for use in the data flow library.
*/
private import codeql.dataflow.DataFlowParameter
private import codeql.dataflow.DataFlow
module Private {
import DataFlowPrivate
@ -13,7 +13,7 @@ module Public {
import DataFlowUtil
}
module JavaDataFlow implements DataFlowParameter {
module JavaDataFlow implements InputSig {
import Private
import Public

Просмотреть файл

@ -1,3 +1,3 @@
private import DataFlowImplSpecific
private import codeql.dataflow.DataFlowImpl
private import codeql.dataflow.internal.DataFlowImpl
import MakeImpl<PythonDataFlow>

Просмотреть файл

@ -1,3 +1,3 @@
private import DataFlowImplSpecific
private import codeql.dataflow.DataFlowImplCommon
private import codeql.dataflow.internal.DataFlowImplCommon
import MakeImplCommon<PythonDataFlow>

Просмотреть файл

@ -2,7 +2,7 @@
* Provides Python-specific definitions for use in the data flow library.
*/
private import codeql.dataflow.DataFlowParameter
private import codeql.dataflow.DataFlow
// we need to export `Unit` for the DataFlowImpl* files
private import python as Python
@ -15,7 +15,7 @@ module Public {
import DataFlowUtil
}
module PythonDataFlow implements DataFlowParameter {
module PythonDataFlow implements InputSig {
import Private
import Public

Просмотреть файл

@ -1,3 +1,3 @@
private import DataFlowImplSpecific
private import codeql.dataflow.DataFlowImpl
private import codeql.dataflow.internal.DataFlowImpl
import MakeImpl<RubyDataFlow>

Просмотреть файл

@ -1,3 +1,3 @@
private import DataFlowImplSpecific
private import codeql.dataflow.DataFlowImplCommon
private import codeql.dataflow.internal.DataFlowImplCommon
import MakeImplCommon<RubyDataFlow>

Просмотреть файл

@ -2,7 +2,7 @@
* Provides Ruby-specific definitions for use in the data flow library.
*/
private import codeql.dataflow.DataFlowParameter
private import codeql.dataflow.DataFlow
module Private {
import DataFlowPrivate
@ -13,7 +13,7 @@ module Public {
import DataFlowPublic
}
module RubyDataFlow implements DataFlowParameter {
module RubyDataFlow implements InputSig {
import Private
import Public

Просмотреть файл

@ -1,15 +1,234 @@
/**
* Provides an implementation of global (interprocedural) data flow. This file
* re-exports the local (intraprocedural) data flow analysis from
* `DataFlowImplSpecific::Public` and adds a global analysis, mainly exposed
* through the `Global` and `GlobalWithState` modules.
* adds a global analysis, mainly exposed through the `Global` and `GlobalWithState`
* modules.
*/
import DataFlowParameter
/** Provides language-specific data flow parameters. */
signature module InputSig {
class Node {
/** Gets a textual representation of this element. */
string toString();
module Configs<DataFlowParameter Lang> {
/**
* Holds if this element is at the specified location.
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
);
}
class ParameterNode extends Node;
class ArgumentNode extends Node;
class ReturnNode extends Node {
ReturnKind getKind();
}
class OutNode extends Node;
class PostUpdateNode extends Node {
Node getPreUpdateNode();
}
class CastNode extends Node;
predicate isParameterNode(ParameterNode p, DataFlowCallable c, ParameterPosition pos);
predicate isArgumentNode(ArgumentNode n, DataFlowCall call, ArgumentPosition pos);
DataFlowCallable nodeGetEnclosingCallable(Node node);
DataFlowType getNodeType(Node node);
predicate nodeIsHidden(Node node);
class DataFlowExpr;
/** Gets the node corresponding to `e`. */
Node exprNode(DataFlowExpr e);
class DataFlowCall {
/** Gets a textual representation of this element. */
string toString();
DataFlowCallable getEnclosingCallable();
}
class DataFlowCallable {
/** Gets a textual representation of this element. */
string toString();
}
class ReturnKind {
/** Gets a textual representation of this element. */
string toString();
}
/** Gets a viable implementation of the target of the given `Call`. */
DataFlowCallable viableCallable(DataFlowCall c);
/**
* Holds if the set of viable implementations that can be called by `call`
* might be improved by knowing the call context.
*/
predicate mayBenefitFromCallContext(DataFlowCall call, DataFlowCallable c);
/**
* Gets a viable dispatch target of `call` in the context `ctx`. This is
* restricted to those `call`s for which a context might make a difference.
*/
DataFlowCallable viableImplInCallContext(DataFlowCall call, DataFlowCall ctx);
/**
* Gets a node that can read the value returned from `call` with return kind
* `kind`.
*/
OutNode getAnOutNode(DataFlowCall call, ReturnKind kind);
class DataFlowType {
/** Gets a textual representation of this element. */
string toString();
}
string ppReprType(DataFlowType t);
bindingset[t1, t2]
predicate compatibleTypes(DataFlowType t1, DataFlowType t2);
predicate typeStrongerThan(DataFlowType t1, DataFlowType t2);
class Content {
/** Gets a textual representation of this element. */
string toString();
}
predicate forceHighPrecision(Content c);
/**
* An entity that represents a set of `Content`s.
*
* The set may be interpreted differently depending on whether it is
* stored into (`getAStoreContent`) or read from (`getAReadContent`).
*/
class ContentSet {
/** Gets a content that may be stored into when storing into this set. */
Content getAStoreContent();
/** Gets a content that may be read from when reading from this set. */
Content getAReadContent();
}
class ContentApprox {
/** Gets a textual representation of this element. */
string toString();
}
ContentApprox getContentApprox(Content c);
class ParameterPosition {
/** Gets a textual representation of this element. */
bindingset[this]
string toString();
}
class ArgumentPosition {
/** Gets a textual representation of this element. */
bindingset[this]
string toString();
}
predicate parameterMatch(ParameterPosition ppos, ArgumentPosition apos);
predicate simpleLocalFlowStep(Node node1, Node node2);
/**
* Holds if data can flow from `node1` to `node2` through a non-local step
* that does not follow a call edge. For example, a step through a global
* variable.
*/
predicate jumpStep(Node node1, Node node2);
/**
* Holds if data can flow from `node1` to `node2` via a read of `c`. Thus,
* `node1` references an object with a content `c.getAReadContent()` whose
* value ends up in `node2`.
*/
predicate readStep(Node node1, ContentSet c, Node node2);
/**
* Holds if data can flow from `node1` to `node2` via a store into `c`. Thus,
* `node2` references an object with a content `c.getAStoreContent()` that
* contains the value of `node1`.
*/
predicate storeStep(Node node1, ContentSet c, Node node2);
/**
* Holds if values stored inside content `c` are cleared at node `n`. For example,
* any value stored inside `f` is cleared at the pre-update node associated with `x`
* in `x.f = newValue`.
*/
predicate clearsContent(Node n, ContentSet c);
/**
* Holds if the value that is being tracked is expected to be stored inside content `c`
* at node `n`.
*/
predicate expectsContent(Node n, ContentSet c);
/**
* Holds if the node `n` is unreachable when the call context is `call`.
*/
predicate isUnreachableInCall(Node n, DataFlowCall call);
default int accessPathLimit() { result = 5 }
/**
* Holds if flow is allowed to pass from parameter `p` and back to itself as a
* side-effect, resulting in a summary from `p` to itself.
*
* One example would be to allow flow like `p.foo = p.bar;`, which is disallowed
* by default as a heuristic.
*/
predicate allowParameterReturnInSelf(ParameterNode p);
class LambdaCallKind;
/** Holds if `creation` is an expression that creates a lambda of kind `kind` for `c`. */
predicate lambdaCreation(Node creation, LambdaCallKind kind, DataFlowCallable c);
/** Holds if `call` is a lambda call of kind `kind` where `receiver` is the lambda expression. */
predicate lambdaCall(DataFlowCall call, LambdaCallKind kind, Node receiver);
/** Extra data-flow steps needed for lambda flow analysis. */
predicate additionalLambdaFlowStep(Node nodeFrom, Node nodeTo, boolean preservesValue);
/**
* Holds if `n` should never be skipped over in the `PathGraph` and in path
* explanations.
*/
default predicate neverSkipInPathGraph(Node n) { none() }
/**
* Gets an additional term that is added to the `join` and `branch` computations to reflect
* an additional forward or backwards branching factor that is not taken into account
* when calculating the (virtual) dispatch cost.
*
* Argument `arg` is part of a path from a source to a sink, and `p` is the target parameter.
*/
int getAdditionalFlowIntoCallNodeTerm(ArgumentNode arg, ParameterNode p);
predicate golangSpecificParamArgFilter(DataFlowCall call, ParameterNode p, ArgumentNode arg);
}
module Configs<InputSig Lang> {
private import Lang
private import DataFlowImplCommon::MakeImplCommon<Lang>
private import internal.DataFlowImplCommon::MakeImplCommon<Lang>
import DataFlowImplCommonPublic
/** An input configuration for data flow. */
@ -211,9 +430,9 @@ module Configs<DataFlowParameter Lang> {
}
}
module DataFlowMake<DataFlowParameter Lang> {
module DataFlowMake<InputSig Lang> {
private import Lang
private import DataFlowImpl::MakeImpl<Lang>
private import internal.DataFlowImpl::MakeImpl<Lang>
import Configs<Lang>
/**

Просмотреть файл

@ -1,220 +0,0 @@
signature module DataFlowParameter {
class Node {
/** Gets a textual representation of this element. */
string toString();
/**
* Holds if this element is at the specified location.
* The location spans column `startcolumn` of line `startline` to
* column `endcolumn` of line `endline` in file `filepath`.
* For more information, see
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
*/
predicate hasLocationInfo(
string filepath, int startline, int startcolumn, int endline, int endcolumn
);
}
class ParameterNode extends Node;
class ArgumentNode extends Node;
class ReturnNode extends Node {
ReturnKind getKind();
}
class OutNode extends Node;
class PostUpdateNode extends Node {
Node getPreUpdateNode();
}
class CastNode extends Node;
predicate isParameterNode(ParameterNode p, DataFlowCallable c, ParameterPosition pos);
predicate isArgumentNode(ArgumentNode n, DataFlowCall call, ArgumentPosition pos);
DataFlowCallable nodeGetEnclosingCallable(Node node);
DataFlowType getNodeType(Node node);
predicate nodeIsHidden(Node node);
class DataFlowExpr;
/** Gets the node corresponding to `e`. */
Node exprNode(DataFlowExpr e);
class DataFlowCall {
/** Gets a textual representation of this element. */
string toString();
DataFlowCallable getEnclosingCallable();
}
class DataFlowCallable {
/** Gets a textual representation of this element. */
string toString();
}
class ReturnKind {
/** Gets a textual representation of this element. */
string toString();
}
/** Gets a viable implementation of the target of the given `Call`. */
DataFlowCallable viableCallable(DataFlowCall c);
/**
* Holds if the set of viable implementations that can be called by `call`
* might be improved by knowing the call context.
*/
predicate mayBenefitFromCallContext(DataFlowCall call, DataFlowCallable c);
/**
* Gets a viable dispatch target of `call` in the context `ctx`. This is
* restricted to those `call`s for which a context might make a difference.
*/
DataFlowCallable viableImplInCallContext(DataFlowCall call, DataFlowCall ctx);
/**
* Gets a node that can read the value returned from `call` with return kind
* `kind`.
*/
OutNode getAnOutNode(DataFlowCall call, ReturnKind kind);
class DataFlowType {
/** Gets a textual representation of this element. */
string toString();
}
string ppReprType(DataFlowType t);
bindingset[t1, t2]
predicate compatibleTypes(DataFlowType t1, DataFlowType t2);
predicate typeStrongerThan(DataFlowType t1, DataFlowType t2);
class Content {
/** Gets a textual representation of this element. */
string toString();
}
predicate forceHighPrecision(Content c);
/**
* An entity that represents a set of `Content`s.
*
* The set may be interpreted differently depending on whether it is
* stored into (`getAStoreContent`) or read from (`getAReadContent`).
*/
class ContentSet {
/** Gets a content that may be stored into when storing into this set. */
Content getAStoreContent();
/** Gets a content that may be read from when reading from this set. */
Content getAReadContent();
}
class ContentApprox {
/** Gets a textual representation of this element. */
string toString();
}
ContentApprox getContentApprox(Content c);
class ParameterPosition {
/** Gets a textual representation of this element. */
bindingset[this]
string toString();
}
class ArgumentPosition {
/** Gets a textual representation of this element. */
bindingset[this]
string toString();
}
predicate parameterMatch(ParameterPosition ppos, ArgumentPosition apos);
predicate simpleLocalFlowStep(Node node1, Node node2);
/**
* Holds if data can flow from `node1` to `node2` through a non-local step
* that does not follow a call edge. For example, a step through a global
* variable.
*/
predicate jumpStep(Node node1, Node node2);
/**
* Holds if data can flow from `node1` to `node2` via a read of `c`. Thus,
* `node1` references an object with a content `c.getAReadContent()` whose
* value ends up in `node2`.
*/
predicate readStep(Node node1, ContentSet c, Node node2);
/**
* Holds if data can flow from `node1` to `node2` via a store into `c`. Thus,
* `node2` references an object with a content `c.getAStoreContent()` that
* contains the value of `node1`.
*/
predicate storeStep(Node node1, ContentSet c, Node node2);
/**
* Holds if values stored inside content `c` are cleared at node `n`. For example,
* any value stored inside `f` is cleared at the pre-update node associated with `x`
* in `x.f = newValue`.
*/
predicate clearsContent(Node n, ContentSet c);
/**
* Holds if the value that is being tracked is expected to be stored inside content `c`
* at node `n`.
*/
predicate expectsContent(Node n, ContentSet c);
/**
* Holds if the node `n` is unreachable when the call context is `call`.
*/
predicate isUnreachableInCall(Node n, DataFlowCall call);
default int accessPathLimit() { result = 5 }
/**
* Holds if flow is allowed to pass from parameter `p` and back to itself as a
* side-effect, resulting in a summary from `p` to itself.
*
* One example would be to allow flow like `p.foo = p.bar;`, which is disallowed
* by default as a heuristic.
*/
predicate allowParameterReturnInSelf(ParameterNode p);
class LambdaCallKind;
/** Holds if `creation` is an expression that creates a lambda of kind `kind` for `c`. */
predicate lambdaCreation(Node creation, LambdaCallKind kind, DataFlowCallable c);
/** Holds if `call` is a lambda call of kind `kind` where `receiver` is the lambda expression. */
predicate lambdaCall(DataFlowCall call, LambdaCallKind kind, Node receiver);
/** Extra data-flow steps needed for lambda flow analysis. */
predicate additionalLambdaFlowStep(Node nodeFrom, Node nodeTo, boolean preservesValue);
/**
* Holds if `n` should never be skipped over in the `PathGraph` and in path
* explanations.
*/
default predicate neverSkipInPathGraph(Node n) { none() }
/**
* Gets an additional term that is added to the `join` and `branch` computations to reflect
* an additional forward or backwards branching factor that is not taken into account
* when calculating the (virtual) dispatch cost.
*
* Argument `arg` is part of a path from a source to a sink, and `p` is the target parameter.
*/
int getAdditionalFlowIntoCallNodeTerm(ArgumentNode arg, ParameterNode p);
predicate golangSpecificParamArgFilter(DataFlowCall call, ParameterNode p, ArgumentNode arg);
}

Просмотреть файл

@ -6,11 +6,11 @@
private import codeql.util.Unit
private import codeql.util.Option
import DataFlowParameter
private import codeql.dataflow.DataFlow
module MakeImpl<DataFlowParameter Lang> {
module MakeImpl<InputSig Lang> {
private import Lang
private import DataFlow::DataFlowMake<Lang>
private import DataFlowMake<Lang>
private import DataFlowImplCommon::MakeImplCommon<Lang>
private import DataFlowImplCommonPublic

Просмотреть файл

@ -1,6 +1,6 @@
import DataFlowParameter
private import codeql.dataflow.DataFlow
module MakeImplCommon<DataFlowParameter Lang> {
module MakeImplCommon<InputSig Lang> {
private import Lang
import Cached

Просмотреть файл

@ -1,3 +1,3 @@
private import DataFlowImplSpecific
private import codeql.dataflow.DataFlowImpl
private import codeql.dataflow.internal.DataFlowImpl
import MakeImpl<SwiftDataFlow>

Просмотреть файл

@ -1,3 +1,3 @@
private import DataFlowImplSpecific
private import codeql.dataflow.DataFlowImplCommon
private import codeql.dataflow.internal.DataFlowImplCommon
import MakeImplCommon<SwiftDataFlow>

Просмотреть файл

@ -2,7 +2,7 @@
* Provides Swift-specific definitions for use in the data flow library.
*/
private import codeql.dataflow.DataFlowParameter
private import codeql.dataflow.DataFlow
// we need to export `Unit` for the DataFlowImpl* files
private import swift as Swift
@ -15,7 +15,7 @@ module Public {
import DataFlowPublic
}
module SwiftDataFlow implements DataFlowParameter {
module SwiftDataFlow implements InputSig {
import Private
import Public