mirror of
https://github.com/github/codeql.git
synced 2026-04-27 17:55:19 +02:00
Merge branch 'main' into actiondispatch-response
This commit is contained in:
@@ -241,7 +241,7 @@ private Instruction getANonConversionUse(Operand operand) {
|
||||
|
||||
/**
|
||||
* Gets the operand that represents the first use of the value of `call` following
|
||||
* a sequnce of conversion-like instructions.
|
||||
* a sequence of conversion-like instructions.
|
||||
*/
|
||||
predicate operandForfullyConvertedCall(Operand operand, CallInstruction call) {
|
||||
exists(getANonConversionUse(operand)) and
|
||||
@@ -254,7 +254,7 @@ predicate operandForfullyConvertedCall(Operand operand, CallInstruction call) {
|
||||
|
||||
/**
|
||||
* Gets the instruction that represents the first use of the value of `call` following
|
||||
* a sequnce of conversion-like instructions.
|
||||
* a sequence of conversion-like instructions.
|
||||
*
|
||||
* This predicate only holds if there is no suitable operand (i.e., no operand of a non-
|
||||
* conversion instruction) to use to represent the value of `call` after conversions.
|
||||
|
||||
@@ -746,7 +746,7 @@ predicate exprNodeShouldBeOperand(Node node, Expr e) {
|
||||
|
||||
/**
|
||||
* Holds if `load` is a `LoadInstruction` that is the result of evaluating `e`
|
||||
* and `node` is an `IndirctOperandNode` that should map `node.asExpr()` to `e`.
|
||||
* and `node` is an `IndirectOperandNode` that should map `node.asExpr()` to `e`.
|
||||
*
|
||||
* We map `e` to `node.asExpr()` when `node` semantically represents the
|
||||
* same value as `load`. A subsequent flow step will flow `node` to
|
||||
|
||||
@@ -100,7 +100,7 @@ private string getNodeProperty(DataFlow::Node node, string key) {
|
||||
or
|
||||
// Is there partial flow from a source to this node?
|
||||
// This property will only be emitted if partial flow is enabled by overriding
|
||||
// `DataFlow::Configration::explorationLimit()`.
|
||||
// `DataFlow::Configuration::explorationLimit()`.
|
||||
key = "pflow" and
|
||||
result =
|
||||
strictconcat(DataFlow::PartialPathNode sourceNode, DataFlow::PartialPathNode destNode, int dist,
|
||||
|
||||
@@ -71,7 +71,7 @@ abstract class CustomSignDef extends SignDef {
|
||||
* Concrete implementations extend one of the following subclasses:
|
||||
* - `ConstantSignExpr`, for expressions with a compile-time constant value.
|
||||
* - `FlowSignExpr`, for expressions whose sign can be computed from the signs of their operands.
|
||||
* - `CustomsignExpr`, for expressions shose sign can be computed by a language-specific
|
||||
* - `CustomsignExpr`, for expressions whose sign can be computed by a language-specific
|
||||
* implementation.
|
||||
*
|
||||
* If the same expression matches more than one of the above subclasses, the sign is computed as
|
||||
|
||||
@@ -11,7 +11,7 @@ private import experimental.semmle.code.cpp.semantic.Semantic
|
||||
predicate ignoreTypeRestrictions(SemExpr e) { none() }
|
||||
|
||||
/**
|
||||
* Workaround to track the sign of cetain expressions even if the type of the expression is not
|
||||
* Workaround to track the sign of certain expressions even if the type of the expression is not
|
||||
* numeric.
|
||||
*/
|
||||
predicate trackUnknownNonNumericExpr(SemExpr e) { none() }
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Proivdes the `LinkTarget` class representing linker invocations during the build process.
|
||||
* Provides the `LinkTarget` class representing linker invocations during the build process.
|
||||
*/
|
||||
|
||||
import semmle.code.cpp.Class
|
||||
|
||||
@@ -144,7 +144,7 @@ class Variable extends Declaration, @variable {
|
||||
* `Variable.getInitializer()` to get the variable's initializer,
|
||||
* or use `Variable.getAnAssignedValue()` to get an expression that
|
||||
* is the right-hand side of an assignment or an initialization of
|
||||
* the varible.
|
||||
* the variable.
|
||||
*/
|
||||
Assignment getAnAssignment() { result.getLValue() = this.getAnAccess() }
|
||||
|
||||
@@ -173,7 +173,7 @@ class Variable extends Declaration, @variable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this variable is declated as part of a structured binding
|
||||
* Holds if this variable is declared as part of a structured binding
|
||||
* declaration. For example, `x` in `auto [x, y] = ...`.
|
||||
*/
|
||||
predicate isStructuredBinding() { is_structured_binding(underlyingElement(this)) }
|
||||
|
||||
@@ -76,7 +76,7 @@ class TypeBoundsAnalysis extends BufferWriteEstimationReason, TTypeBoundsAnalysi
|
||||
|
||||
/**
|
||||
* The estimation comes from non trivial bounds found via actual flow analysis,
|
||||
* but a widening aproximation might have been used for variables in loops.
|
||||
* but a widening approximation might have been used for variables in loops.
|
||||
* For example
|
||||
* ```
|
||||
* for (int i = 0; i < 10; ++i) {
|
||||
@@ -141,7 +141,7 @@ class AttributeFormattingFunction extends FormattingFunction {
|
||||
* - `""` is a `vprintf` variant, `outputParamIndex` is `-1`.
|
||||
* - `"f"` is a `vfprintf` variant, `outputParamIndex` indicates the output stream parameter.
|
||||
* - `"s"` is a `vsprintf` variant, `outputParamIndex` indicates the output buffer parameter.
|
||||
* - `"?"` if the type cannot be deteremined. `outputParamIndex` is `-1`.
|
||||
* - `"?"` if the type cannot be determined. `outputParamIndex` is `-1`.
|
||||
*/
|
||||
predicate primitiveVariadicFormatter(
|
||||
TopLevelFunction f, string type, int formatParamIndex, int outputParamIndex
|
||||
@@ -198,7 +198,7 @@ private predicate callsVariadicFormatter(
|
||||
* - `""` is a `vprintf` variant, `outputParamIndex` is `-1`.
|
||||
* - `"f"` is a `vfprintf` variant, `outputParamIndex` indicates the output stream parameter.
|
||||
* - `"s"` is a `vsprintf` variant, `outputParamIndex` indicates the output buffer parameter.
|
||||
* - `"?"` if the type cannot be deteremined. `outputParamIndex` is `-1`.
|
||||
* - `"?"` if the type cannot be determined. `outputParamIndex` is `-1`.
|
||||
*/
|
||||
predicate variadicFormatter(Function f, string type, int formatParamIndex, int outputParamIndex) {
|
||||
primitiveVariadicFormatter(f, type, formatParamIndex, outputParamIndex)
|
||||
|
||||
@@ -12,7 +12,7 @@ private import internal.ConstantExprs
|
||||
* relation). The refinement manifests itself in two changes:
|
||||
*
|
||||
* - The successor relation on `BasicBlock`s uses `successors_adapted`
|
||||
* (instead of `successors_extended` used by `PrimtiveBasicBlock`s). Consequently,
|
||||
* (instead of `successors_extended` used by `PrimitiveBasicBlock`s). Consequently,
|
||||
* some edges between `BasicBlock`s may be removed. Example:
|
||||
* ```
|
||||
* x = 1; // s1
|
||||
|
||||
@@ -149,7 +149,7 @@ private predicate bbLoopEntryConditionAlwaysTrueAt(BasicBlock bb, int i, Control
|
||||
/**
|
||||
* Basic block `pred` contains all or part of the condition belonging to a loop,
|
||||
* and there is an edge from `pred` to `succ` that concludes the condition.
|
||||
* If the edge corrseponds with the loop condition being found to be `true`, then
|
||||
* If the edge corresponds with the loop condition being found to be `true`, then
|
||||
* `skipsLoop` is `false`. Otherwise the edge corresponds with the loop condition
|
||||
* being found to be `false` and `skipsLoop` is `true`. Non-concluding edges
|
||||
* within a complex loop condition are not matched by this predicate.
|
||||
|
||||
@@ -1137,7 +1137,7 @@ class BuiltInOperationIsArray extends BuiltInOperation, @isarray {
|
||||
* A C++ `__array_rank` built-in operation (used by some implementations of the
|
||||
* `<type_traits>` header).
|
||||
*
|
||||
* If known, returns the number of dimentsions of an arrary type.
|
||||
* If known, returns the number of dimensions of an arrary type.
|
||||
* ```
|
||||
* template<typename _Tp>
|
||||
* struct rank
|
||||
|
||||
@@ -494,7 +494,7 @@ class VacuousDestructorCall extends Expr, @vacuous_destructor_call {
|
||||
* An initialization of a base class or member variable performed as part
|
||||
* of a constructor's explicit initializer list or implicit actions.
|
||||
*
|
||||
* This is a QL root class for reprenting various types of constructor
|
||||
* This is a QL root class for representing various types of constructor
|
||||
* initializations.
|
||||
*/
|
||||
class ConstructorInit extends Expr, @ctorinit {
|
||||
|
||||
@@ -779,7 +779,7 @@ class AlignofExprOperator extends AlignofOperator {
|
||||
/**
|
||||
* A C++11 `alignof` expression whose operand is a type name.
|
||||
* ```
|
||||
* bool proper_alignment = (alingof(T) == alignof(T[0]);
|
||||
* bool proper_alignment = (alignof(T) == alignof(T[0]);
|
||||
* ```
|
||||
*/
|
||||
class AlignofTypeOperator extends AlignofOperator {
|
||||
|
||||
@@ -451,7 +451,7 @@ class Expr extends StmtParent, @expr {
|
||||
// For performance, we avoid a full transitive closure over `getConversion`.
|
||||
// Since there can be several implicit conversions before and after an
|
||||
// explicit conversion, use `getImplicitlyConverted` to step over them
|
||||
// cheaply. Then, if there is an explicit conversion following the implict
|
||||
// cheaply. Then, if there is an explicit conversion following the implicit
|
||||
// conversion sequence, recurse to handle multiple explicit conversions.
|
||||
if this.getImplicitlyConverted().hasExplicitConversion()
|
||||
then result = this.getImplicitlyConverted().getConversion().getExplicitlyConverted()
|
||||
|
||||
@@ -100,7 +100,7 @@ private string getNodeProperty(DataFlow::Node node, string key) {
|
||||
or
|
||||
// Is there partial flow from a source to this node?
|
||||
// This property will only be emitted if partial flow is enabled by overriding
|
||||
// `DataFlow::Configration::explorationLimit()`.
|
||||
// `DataFlow::Configuration::explorationLimit()`.
|
||||
key = "pflow" and
|
||||
result =
|
||||
strictconcat(DataFlow::PartialPathNode sourceNode, DataFlow::PartialPathNode destNode, int dist,
|
||||
|
||||
@@ -742,7 +742,7 @@ class NoOpInstruction extends Instruction {
|
||||
* The `ReturnInstruction` for a function will have a control-flow successor edge to a block
|
||||
* containing the `ExitFunction` instruction for that function.
|
||||
*
|
||||
* There are two differet return instructions: `ReturnValueInstruction`, for returning a value from
|
||||
* There are two different return instructions: `ReturnValueInstruction`, for returning a value from
|
||||
* a non-`void`-returning function, and `ReturnVoidInstruction`, for returning from a
|
||||
* `void`-returning function.
|
||||
*/
|
||||
@@ -1331,7 +1331,7 @@ class CheckedConvertOrThrowInstruction extends UnaryInstruction {
|
||||
*
|
||||
* If the operand holds a null address, the result is a null address.
|
||||
*
|
||||
* This instruction is used to represent `dyanmic_cast<void*>` in C++, which returns the pointer to
|
||||
* This instruction is used to represent `dynamic_cast<void*>` in C++, which returns the pointer to
|
||||
* the most-derived object.
|
||||
*/
|
||||
class CompleteObjectAddressInstruction extends UnaryInstruction {
|
||||
|
||||
@@ -64,7 +64,7 @@ private module Cached {
|
||||
or
|
||||
instr = reusedPhiInstruction(_) and
|
||||
// Check that the phi instruction is *not* degenerate, but we can't use
|
||||
// getDegeneratePhiOperand in the first stage with phi instyructions
|
||||
// getDegeneratePhiOperand in the first stage with phi instructions
|
||||
not exists(
|
||||
unique(OldIR::PhiInputOperand operand |
|
||||
operand = instr.(OldIR::PhiInstruction).getAnInputOperand() and
|
||||
@@ -718,7 +718,7 @@ module DefUse {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the rank index of a hyphothetical use one instruction past the end of
|
||||
* Gets the rank index of a hypothetical use one instruction past the end of
|
||||
* the block. This index can be used to determine if a definition reaches the
|
||||
* end of the block, even if the definition is the last instruction in the
|
||||
* block.
|
||||
|
||||
@@ -172,7 +172,7 @@ deprecated module UnaliasedSSAOperands = UnaliasedSsaOperands;
|
||||
|
||||
/**
|
||||
* Provides wrappers for the constructors of each branch of `TOperand` that is used by the
|
||||
* asliased SSA stage.
|
||||
* aliased SSA stage.
|
||||
* These wrappers are not parameterized because it is not possible to invoke an IPA constructor via
|
||||
* a class alias.
|
||||
*/
|
||||
|
||||
@@ -742,7 +742,7 @@ class NoOpInstruction extends Instruction {
|
||||
* The `ReturnInstruction` for a function will have a control-flow successor edge to a block
|
||||
* containing the `ExitFunction` instruction for that function.
|
||||
*
|
||||
* There are two differet return instructions: `ReturnValueInstruction`, for returning a value from
|
||||
* There are two different return instructions: `ReturnValueInstruction`, for returning a value from
|
||||
* a non-`void`-returning function, and `ReturnVoidInstruction`, for returning from a
|
||||
* `void`-returning function.
|
||||
*/
|
||||
@@ -1331,7 +1331,7 @@ class CheckedConvertOrThrowInstruction extends UnaryInstruction {
|
||||
*
|
||||
* If the operand holds a null address, the result is a null address.
|
||||
*
|
||||
* This instruction is used to represent `dyanmic_cast<void*>` in C++, which returns the pointer to
|
||||
* This instruction is used to represent `dynamic_cast<void*>` in C++, which returns the pointer to
|
||||
* the most-derived object.
|
||||
*/
|
||||
class CompleteObjectAddressInstruction extends UnaryInstruction {
|
||||
|
||||
@@ -542,7 +542,7 @@ class TranslatedArgumentExprSideEffect extends TranslatedArgumentSideEffect,
|
||||
* The IR translation of an argument side effect for `*this` on a call, where there is no `Expr`
|
||||
* object that represents the `this` argument.
|
||||
*
|
||||
* The applies only to constructor calls, as the AST has explioit qualifier `Expr`s for all other
|
||||
* The applies only to constructor calls, as the AST has exploit qualifier `Expr`s for all other
|
||||
* calls to non-static member functions.
|
||||
*/
|
||||
class TranslatedStructorQualifierSideEffect extends TranslatedArgumentSideEffect,
|
||||
|
||||
@@ -2177,7 +2177,7 @@ abstract class TranslatedConditionalExpr extends TranslatedNonConstantExpr {
|
||||
/**
|
||||
* The IR translation of the ternary conditional operator (`a ? b : c`).
|
||||
* For this version, we expand the condition as a `TranslatedCondition`, rather than a
|
||||
* `TranslatedExpr`, to simplify the control flow in the presence of short-ciruit logical operators.
|
||||
* `TranslatedExpr`, to simplify the control flow in the presence of short-circuit logical operators.
|
||||
*/
|
||||
class TranslatedTernaryConditionalExpr extends TranslatedConditionalExpr, ConditionContext {
|
||||
TranslatedTernaryConditionalExpr() { not expr.isTwoOperand() }
|
||||
|
||||
@@ -742,7 +742,7 @@ class NoOpInstruction extends Instruction {
|
||||
* The `ReturnInstruction` for a function will have a control-flow successor edge to a block
|
||||
* containing the `ExitFunction` instruction for that function.
|
||||
*
|
||||
* There are two differet return instructions: `ReturnValueInstruction`, for returning a value from
|
||||
* There are two different return instructions: `ReturnValueInstruction`, for returning a value from
|
||||
* a non-`void`-returning function, and `ReturnVoidInstruction`, for returning from a
|
||||
* `void`-returning function.
|
||||
*/
|
||||
@@ -1331,7 +1331,7 @@ class CheckedConvertOrThrowInstruction extends UnaryInstruction {
|
||||
*
|
||||
* If the operand holds a null address, the result is a null address.
|
||||
*
|
||||
* This instruction is used to represent `dyanmic_cast<void*>` in C++, which returns the pointer to
|
||||
* This instruction is used to represent `dynamic_cast<void*>` in C++, which returns the pointer to
|
||||
* the most-derived object.
|
||||
*/
|
||||
class CompleteObjectAddressInstruction extends UnaryInstruction {
|
||||
|
||||
@@ -64,7 +64,7 @@ private module Cached {
|
||||
or
|
||||
instr = reusedPhiInstruction(_) and
|
||||
// Check that the phi instruction is *not* degenerate, but we can't use
|
||||
// getDegeneratePhiOperand in the first stage with phi instyructions
|
||||
// getDegeneratePhiOperand in the first stage with phi instructions
|
||||
not exists(
|
||||
unique(OldIR::PhiInputOperand operand |
|
||||
operand = instr.(OldIR::PhiInstruction).getAnInputOperand() and
|
||||
@@ -718,7 +718,7 @@ module DefUse {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the rank index of a hyphothetical use one instruction past the end of
|
||||
* Gets the rank index of a hypothetical use one instruction past the end of
|
||||
* the block. This index can be used to determine if a definition reaches the
|
||||
* end of the block, even if the definition is the last instruction in the
|
||||
* block.
|
||||
|
||||
@@ -12,7 +12,7 @@ private Type getDecayedType(Type type) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if the sepcified variable is a structured binding with a non-reference
|
||||
* Holds if the specified variable is a structured binding with a non-reference
|
||||
* type.
|
||||
*/
|
||||
predicate isNonReferenceStructuredBinding(Variable v) {
|
||||
|
||||
@@ -209,7 +209,7 @@ private predicate aClassFile(Class c, File file) { c.getDefinitionLocation().get
|
||||
|
||||
pragma[noopt]
|
||||
private predicate dependsOnFileSimple(MetricFile source, MetricFile dest) {
|
||||
// class derives from classs
|
||||
// class derives from another class
|
||||
exists(Class fromClass, Class toClass |
|
||||
aClassFile(fromClass, source) and
|
||||
fromClass.derivesFrom(toClass) and
|
||||
|
||||
@@ -173,7 +173,7 @@ predicate eqOpWithSwapAndNegate(EqualityOperation cmp, Expr a, Expr b, boolean i
|
||||
|
||||
/**
|
||||
* Holds if `cmp` is an unconverted conversion of `a` to a Boolean that
|
||||
* evalutes to `isEQ` iff `a` is 0.
|
||||
* evaluates to `isEQ` iff `a` is 0.
|
||||
*
|
||||
* Note that `a` can be `cmp` itself or a conversion thereof.
|
||||
*/
|
||||
|
||||
@@ -51,14 +51,14 @@ string getInsecureAlgorithmRegex() {
|
||||
|
||||
/**
|
||||
* Holds if `name` looks like it might be related to operations with an
|
||||
* insecure encyption algorithm.
|
||||
* insecure encryption algorithm.
|
||||
*/
|
||||
bindingset[name]
|
||||
predicate isInsecureEncryption(string name) { name.regexpMatch(getInsecureAlgorithmRegex()) }
|
||||
|
||||
/**
|
||||
* Holds if there is additional evidence that `name` looks like it might be
|
||||
* related to operations with an encyption algorithm, besides the name of a
|
||||
* related to operations with an encryption algorithm, besides the name of a
|
||||
* specific algorithm. This can be used in conjunction with
|
||||
* `isInsecureEncryption` to produce a stronger heuristic.
|
||||
*/
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* DEPRECATED: we now use `semmle.code.cpp.ir.dataflow.DefaultTaintTracking`,
|
||||
* which is based on the IR but designed to behave similarly to this old
|
||||
* libarary.
|
||||
* library.
|
||||
*
|
||||
* Provides the implementation of `semmle.code.cpp.security.TaintTracking`. Do
|
||||
* not import this file directly.
|
||||
|
||||
@@ -104,7 +104,7 @@ private newtype HC_Alloc =
|
||||
HC_HasAlloc(HashCons hc) { mk_HasAlloc(hc, _) }
|
||||
|
||||
/**
|
||||
* Used to implement optional extent expression on `new[]` exprtessions
|
||||
* Used to implement optional extent expression on `new[]` expressions
|
||||
*/
|
||||
private newtype HC_Extent =
|
||||
HC_NoExtent() or
|
||||
@@ -116,7 +116,7 @@ private newtype HC_Args =
|
||||
HC_ArgCons(HashCons hc, int i, HC_Args list) { mk_ArgCons(hc, i, list, _) }
|
||||
|
||||
/**
|
||||
* Used to implement hash-consing of struct initizializers.
|
||||
* Used to implement hash-consing of struct initializers.
|
||||
*/
|
||||
private newtype HC_Fields =
|
||||
HC_EmptyFields(Class c) { exists(ClassAggregateLiteral cal | c = cal.getUnspecifiedType()) } or
|
||||
|
||||
@@ -125,7 +125,7 @@
|
||||
|
||||
* The `security` tag has been added to the `cpp/return-stack-allocated-memory` query. As a result, its results will now appear by default.
|
||||
* The "Uncontrolled data in arithmetic expression" (cpp/uncontrolled-arithmetic) query has been enhanced to reduce false positive results and its @precision increased to high.
|
||||
* A new `cpp/very-likely-overruning-write` query has been added to the default query suite for C/C++. The query reports some results that were formerly flagged by `cpp/overruning-write`.
|
||||
* A new `cpp/very-likely-overrunning-write` query has been added to the default query suite for C/C++. The query reports some results that were formerly flagged by `cpp/overrunning-write`.
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@ predicate verifiedRealloc(FunctionCall reallocCall, Variable v, ControlFlowNode
|
||||
node.(AnalysedExpr).getNonNullSuccessor(newV) = verified and
|
||||
// note: this case uses naive flow logic (getAnAssignedValue).
|
||||
// special case: if the result of the 'realloc' is assigned to the
|
||||
// same variable, we don't descriminate properly between the old
|
||||
// same variable, we don't discriminate properly between the old
|
||||
// and the new allocation; better to not consider this a free at
|
||||
// all in that case.
|
||||
newV != v
|
||||
|
||||
@@ -23,7 +23,7 @@ DoStmt getAFalseLoop() {
|
||||
/**
|
||||
* Gets a `do` ... `while` loop surrounding a statement. This is blocked by a
|
||||
* `switch` statement, since a `continue` inside a `switch` inside a loop may be
|
||||
* jusitifed (`continue` breaks out of the loop whereas `break` only escapes the
|
||||
* justified (`continue` breaks out of the loop whereas `break` only escapes the
|
||||
* `switch`).
|
||||
*/
|
||||
DoStmt enclosingLoop(Stmt s) {
|
||||
|
||||
@@ -17,7 +17,7 @@ import cpp
|
||||
/**
|
||||
* It's common in some projects to use "a double negation" to normalize the boolean
|
||||
* result to either 1 or 0.
|
||||
* This predciate is intended to filter explicit usage of a double negation as it typically
|
||||
* This predicate is intended to filter explicit usage of a double negation as it typically
|
||||
* indicates the explicit purpose to normalize the result for bit-wise or arithmetic purposes.
|
||||
*/
|
||||
predicate doubleNegationNormalization(NotExpr notexpr) { notexpr.getAnOperand() instanceof NotExpr }
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* @name Untrusted network-to-host usage
|
||||
* @description Using the result of a network-to-host byte order function, such as ntohl, as an
|
||||
* array bound or length value without checking it may result in buffer overflows or
|
||||
* other vulnerabilties.
|
||||
* other vulnerabilities.
|
||||
* @kind problem
|
||||
* @problem.severity error
|
||||
*/
|
||||
|
||||
@@ -44,7 +44,7 @@ class ReturnStackAllocatedMemoryConfig extends MustFlowConfiguration {
|
||||
// Holds if `sink` is a node that represents the `StoreInstruction` that is subsequently used in
|
||||
// a `ReturnValueInstruction`.
|
||||
// We use the `StoreInstruction` instead of the instruction that defines the
|
||||
// `ReturnValueInstruction`'s source value oprand because the former has better location information.
|
||||
// `ReturnValueInstruction`'s source value operand because the former has better location information.
|
||||
exists(StoreInstruction store |
|
||||
store.getDestinationAddress().(VariableAddressInstruction).getIRVariable() instanceof
|
||||
IRReturnVariable and
|
||||
|
||||
@@ -24,7 +24,7 @@ import semmle.code.cpp.valuenumbering.GlobalValueNumbering
|
||||
* Holds if `call` is a call to `strncat` such that `sizeArg` and `destArg` are the size and
|
||||
* destination arguments, respectively.
|
||||
*/
|
||||
predicate interestringCallWithArgs(Call call, Expr sizeArg, Expr destArg) {
|
||||
predicate interestingCallWithArgs(Call call, Expr sizeArg, Expr destArg) {
|
||||
exists(StrcatFunction strcat |
|
||||
strcat = call.getTarget() and
|
||||
sizeArg = call.getArgument(strcat.getParamSize()) and
|
||||
@@ -37,7 +37,7 @@ predicate interestringCallWithArgs(Call call, Expr sizeArg, Expr destArg) {
|
||||
* argument `destArg`, and `destArg` is the size of the buffer pointed to by `destArg`.
|
||||
*/
|
||||
predicate case1(FunctionCall fc, Expr sizeArg, VariableAccess destArg) {
|
||||
interestringCallWithArgs(fc, sizeArg, destArg) and
|
||||
interestingCallWithArgs(fc, sizeArg, destArg) and
|
||||
exists(VariableAccess va |
|
||||
va = sizeArg.(BufferSizeExpr).getArg() and
|
||||
destArg.getTarget() = va.getTarget()
|
||||
@@ -49,7 +49,7 @@ predicate case1(FunctionCall fc, Expr sizeArg, VariableAccess destArg) {
|
||||
* argument `destArg`, and `sizeArg` computes the value `sizeof (dest) - strlen (dest)`.
|
||||
*/
|
||||
predicate case2(FunctionCall fc, Expr sizeArg, VariableAccess destArg) {
|
||||
interestringCallWithArgs(fc, sizeArg, destArg) and
|
||||
interestingCallWithArgs(fc, sizeArg, destArg) and
|
||||
exists(SubExpr sub, int n |
|
||||
// The destination buffer is an array of size n
|
||||
destArg.getUnspecifiedType().(ArrayType).getSize() = n and
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* '#include <stdlib.h>' was forgotton */
|
||||
/* '#include <stdlib.h>' was forgotten */
|
||||
|
||||
int main(void) {
|
||||
/* 'int malloc()' assumed */
|
||||
|
||||
@@ -26,7 +26,7 @@ where
|
||||
dest = bw.getDest() and
|
||||
destSize = getBufferSize(dest, _) and
|
||||
estimated = bw.getMaxDataLimited(reason) and
|
||||
// we exclude ValueFlowAnalysis as it is reported in cpp/very-likely-overruning-write
|
||||
// we exclude ValueFlowAnalysis as it is reported in cpp/very-likely-overrunning-write
|
||||
not reason instanceof ValueFlowAnalysis and
|
||||
// we can deduce that too much data may be copied (even without
|
||||
// long '%f' conversions)
|
||||
|
||||
@@ -31,7 +31,7 @@ predicate bounded(Expr e) {
|
||||
) and
|
||||
not convertedExprMightOverflow(e)
|
||||
or
|
||||
// Optimitically assume that a remainder expression always yields a much smaller value.
|
||||
// Optimistically assume that a remainder expression always yields a much smaller value.
|
||||
e = any(RemExpr rem).getLeftOperand()
|
||||
or
|
||||
e = any(AssignRemExpr rem).getLValue()
|
||||
@@ -44,7 +44,7 @@ predicate bounded(Expr e) {
|
||||
boundedBitwiseAnd(e, andExpr, andExpr.getAnOperand(), andExpr.getAnOperand())
|
||||
)
|
||||
or
|
||||
// Optimitically assume that a division always yields a much smaller value.
|
||||
// Optimistically assume that a division always yields a much smaller value.
|
||||
e = any(DivExpr div).getLeftOperand()
|
||||
or
|
||||
e = any(AssignDivExpr div).getLValue()
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
* The `security` tag has been added to the `cpp/return-stack-allocated-memory` query. As a result, its results will now appear by default.
|
||||
* The "Uncontrolled data in arithmetic expression" (cpp/uncontrolled-arithmetic) query has been enhanced to reduce false positive results and its @precision increased to high.
|
||||
* A new `cpp/very-likely-overruning-write` query has been added to the default query suite for C/C++. The query reports some results that were formerly flagged by `cpp/overruning-write`.
|
||||
* A new `cpp/very-likely-overrunning-write` query has been added to the default query suite for C/C++. The query reports some results that were formerly flagged by `cpp/overrunning-write`.
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
|
||||
@@ -13,6 +13,6 @@ where
|
||||
def = definitionOf(e, kind) and
|
||||
// We need to exclude definitions for elements inside template instantiations,
|
||||
// as these often lead to multiple links to definitions from the same source location.
|
||||
// LGTM does not support this bevaviour.
|
||||
// LGTM does not support this behaviour.
|
||||
not e.isFromTemplateInstantiation(_)
|
||||
select e, def, kind
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @id cpp/wrong-uint-access
|
||||
* @name Wrong Uint
|
||||
* @descripion Acess an array of size lower than 256 with a uint16.
|
||||
* @description Access an array of size lower than 256 with a uint16.
|
||||
* @kind problem
|
||||
* @problem.severity recommendation
|
||||
* @tags efficiency
|
||||
@@ -21,5 +21,5 @@ where
|
||||
) and
|
||||
defLine.getArraySize() <= 256
|
||||
select useExpr,
|
||||
"Using a " + useExpr.getArrayOffset().getType() + " to acess the array $@ of size " +
|
||||
"Using a " + useExpr.getArrayOffset().getType() + " to access the array $@ of size " +
|
||||
defLine.getArraySize() + ".", var, var.getName()
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
char *filePath = argv[2];
|
||||
|
||||
{
|
||||
// BAD: the user-controlled string is injected
|
||||
// directly into `wordexp` which performs command substitution
|
||||
|
||||
wordexp_t we;
|
||||
wordexp(filePath, &we, 0);
|
||||
}
|
||||
|
||||
{
|
||||
// GOOD: command substitution is disabled
|
||||
|
||||
wordexp_t we;
|
||||
wordexp(filePath, &we, WRDE_NOCMD);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
<!DOCTYPE qhelp PUBLIC
|
||||
"-//Semmle//qhelp//EN"
|
||||
"qhelp.dtd">
|
||||
<qhelp>
|
||||
<overview>
|
||||
<p>The code passes user input to <code>wordexp</code>. This leaves the code
|
||||
vulnerable to attack by command injection, because <code>wordexp</code> performs command substitution.
|
||||
Command substitution is a feature that replaces <code>$(command)</code> or <code>`command`</code> with the
|
||||
output of the given command, allowing the user to run arbitrary code on the system.
|
||||
</p>
|
||||
|
||||
</overview>
|
||||
<recommendation>
|
||||
|
||||
<p>When calling <code>wordexp</code>, pass the <code>WRDE_NOCMD</code> flag to prevent command substitution.</p>
|
||||
|
||||
</recommendation>
|
||||
<example>
|
||||
<p>The following example passes a user-supplied file path to <code>wordexp</code> in two ways. The
|
||||
first way uses <code>wordexp</code> with no specified flags. As such, it is vulnerable to command
|
||||
injection.
|
||||
The second way uses <code>wordexp</code> with the <code>WRDE_NOCMD</code> flag. As such, no command substitution
|
||||
is performed, making this safe from command injection.</p>
|
||||
<sample src="WordexpTainted.c" />
|
||||
|
||||
</example>
|
||||
<references>
|
||||
|
||||
<li>CERT C Coding Standard:
|
||||
<a href="https://www.securecoding.cert.org/confluence/display/c/STR02-C.+Sanitize+data+passed+to+complex+subsystems">STR02-C.
|
||||
Sanitize data passed to complex subsystems</a>.</li>
|
||||
<li>
|
||||
OWASP:
|
||||
<a href="https://www.owasp.org/index.php/Command_Injection">Command Injection</a>.
|
||||
</li>
|
||||
|
||||
|
||||
<!-- LocalWords: CWE STR
|
||||
-->
|
||||
|
||||
</references>
|
||||
</qhelp>
|
||||
@@ -0,0 +1,57 @@
|
||||
/**
|
||||
* @name Uncontrolled data used in `wordexp` command
|
||||
* @description Using user-supplied data in a `wordexp` command, without
|
||||
* disabling command substitution, can make code vulnerable
|
||||
* to command injection.
|
||||
* @kind path-problem
|
||||
* @problem.severity error
|
||||
* @precision high
|
||||
* @id cpp/wordexp-injection
|
||||
* @tags security
|
||||
* external/cwe/cwe-078
|
||||
*/
|
||||
|
||||
import cpp
|
||||
import semmle.code.cpp.ir.dataflow.TaintTracking
|
||||
import semmle.code.cpp.security.FlowSources
|
||||
import DataFlow::PathGraph
|
||||
|
||||
/**
|
||||
* The `wordexp` function, which can perform command substitution.
|
||||
*/
|
||||
private class WordexpFunction extends Function {
|
||||
WordexpFunction() { hasGlobalName("wordexp") }
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `fc` disables command substitution by containing `WRDE_NOCMD` as a flag argument.
|
||||
*/
|
||||
private predicate isCommandSubstitutionDisabled(FunctionCall fc) {
|
||||
fc.getArgument(2).getValue().toInt().bitAnd(4) = 4
|
||||
/* 4 = WRDE_NOCMD. Check whether the flag is set. */
|
||||
}
|
||||
|
||||
/**
|
||||
* A configuration to track user-supplied data to the `wordexp` function.
|
||||
*/
|
||||
class WordexpTaintConfiguration extends TaintTracking::Configuration {
|
||||
WordexpTaintConfiguration() { this = "WordexpTaintConfiguration" }
|
||||
|
||||
override predicate isSource(DataFlow::Node source) { source instanceof FlowSource }
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) {
|
||||
exists(FunctionCall fc | fc.getTarget() instanceof WordexpFunction |
|
||||
fc.getArgument(0) = sink.asExpr() and
|
||||
not isCommandSubstitutionDisabled(fc)
|
||||
)
|
||||
}
|
||||
|
||||
override predicate isSanitizer(DataFlow::Node node) {
|
||||
node.asExpr().getUnspecifiedType() instanceof IntegralType
|
||||
}
|
||||
}
|
||||
|
||||
from WordexpTaintConfiguration conf, DataFlow::PathNode sourceNode, DataFlow::PathNode sinkNode
|
||||
where conf.hasFlowPath(sourceNode, sinkNode)
|
||||
select sinkNode.getNode(), sourceNode, sinkNode,
|
||||
"Using user-supplied data in a `wordexp` command, without disabling command substitution, can make code vulnerable to command injection."
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @name LinuxPrivilegeDroppingOutoforder
|
||||
* @description A syscall commonly associated with privilege dropping is being called out of order.
|
||||
* Normally a process drops group ID and sets supplimental groups for the target user
|
||||
* Normally a process drops group ID and sets supplemental groups for the target user
|
||||
* before setting the target user ID. This can have security impact if the return code
|
||||
* from these methods is not checked.
|
||||
* @kind problem
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* @name Linux kernel double-fetch vulnerability detection
|
||||
* @description Double-fetch is a very common vulnerability pattern
|
||||
* in linux kernel, attacker can exploit double-fetch
|
||||
* issues to obatain root privilege.
|
||||
* issues to obtain root privilege.
|
||||
* Double-fetch is caused by fetching data from user
|
||||
* mode by calling copy_from_user twice, CVE-2016-6480
|
||||
* is quite a good example for your information.
|
||||
|
||||
@@ -84,7 +84,7 @@ predicate isConditionBig(SwitchStmt swtmp) {
|
||||
}
|
||||
|
||||
/** Holds if there are labels inside the block with names similar to `default` or `case`. */
|
||||
predicate isWrongLableName(SwitchStmt swtmp) {
|
||||
predicate isWrongLabelName(SwitchStmt swtmp) {
|
||||
not swtmp.hasDefaultCase() and
|
||||
exists(LabelStmt lb |
|
||||
(
|
||||
@@ -147,7 +147,7 @@ where
|
||||
isConditionBig(sw) and msg = "The range of condition values is wider than the choices."
|
||||
)
|
||||
or
|
||||
isWrongLableName(sw) and msg = "Possibly erroneous label name."
|
||||
isWrongLabelName(sw) and msg = "Possibly erroneous label name."
|
||||
or
|
||||
isCodeBeforeCase(sw) and msg = "Code before case will not be executed."
|
||||
select sw, msg
|
||||
|
||||
@@ -24,7 +24,7 @@ where
|
||||
texp.getEnclosingStmt().getParentStmt*() = ts.getStmt() and
|
||||
not ts.getACatchClause().isEmpty()
|
||||
) and
|
||||
msg = "DllMain contains an exeption not wrapped in a try..catch block."
|
||||
msg = "DllMain contains an exception not wrapped in a try..catch block."
|
||||
or
|
||||
texp.getExpr().isParenthesised() and
|
||||
texp.getExpr().(CommaExpr).getLeftOperand().isConstant() and
|
||||
|
||||
4
cpp/ql/src/external/CodeDuplication.qll
vendored
4
cpp/ql/src/external/CodeDuplication.qll
vendored
@@ -292,7 +292,7 @@ deprecated predicate duplicateFiles(File f, File other, int percent) {
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: Information on duplciate classes is no longer available.
|
||||
* DEPRECATED: Information on duplicate classes is no longer available.
|
||||
*
|
||||
* Holds if most member functions of `c` (`numDup` out of `total`) are
|
||||
* duplicates of member functions in `other`.
|
||||
@@ -313,7 +313,7 @@ deprecated predicate mostlyDuplicateClassBase(Class c, Class other, int numDup,
|
||||
}
|
||||
|
||||
/**
|
||||
* DEPRECATED: Information on duplciate classes is no longer available.
|
||||
* DEPRECATED: Information on duplicate classes is no longer available.
|
||||
*
|
||||
* Holds if most member functions of `c` are duplicates of member functions in
|
||||
* `other`. Provides the human-readable `message` to describe the amount of
|
||||
|
||||
@@ -14,4 +14,4 @@ from Function f
|
||||
where
|
||||
f.fromSource() and
|
||||
f.calls+(f)
|
||||
select f, "Functions shall not call theselves, either directly or indirectly."
|
||||
select f, "Functions shall not call themselves, either directly or indirectly."
|
||||
|
||||
@@ -41,4 +41,4 @@ where
|
||||
not ae.getParent() instanceof ExprStmt and
|
||||
not ae instanceof ForStmtSideEffectExpr
|
||||
select ae,
|
||||
"AV Rule 160: An assignment expression shall be used only as the exprression in an expression statement."
|
||||
"AV Rule 160: An assignment expression shall be used only as the expression in an expression statement."
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
edges
|
||||
| test.cpp:23:20:23:23 | argv | test.cpp:29:13:29:20 | (const char *)... |
|
||||
| test.cpp:23:20:23:23 | argv | test.cpp:29:13:29:20 | filePath |
|
||||
nodes
|
||||
| test.cpp:23:20:23:23 | argv | semmle.label | argv |
|
||||
| test.cpp:29:13:29:20 | (const char *)... | semmle.label | (const char *)... |
|
||||
| test.cpp:29:13:29:20 | filePath | semmle.label | filePath |
|
||||
subpaths
|
||||
#select
|
||||
| test.cpp:29:13:29:20 | (const char *)... | test.cpp:23:20:23:23 | argv | test.cpp:29:13:29:20 | (const char *)... | Using user-supplied data in a `wordexp` command, without disabling command substitution, can make code vulnerable to command injection. |
|
||||
| test.cpp:29:13:29:20 | filePath | test.cpp:23:20:23:23 | argv | test.cpp:29:13:29:20 | filePath | Using user-supplied data in a `wordexp` command, without disabling command substitution, can make code vulnerable to command injection. |
|
||||
@@ -0,0 +1 @@
|
||||
experimental/Security/CWE/CWE-078/WordexpTainted.ql
|
||||
@@ -0,0 +1,45 @@
|
||||
#ifdef _MSC_VER
|
||||
#define restrict __restrict
|
||||
#else
|
||||
#define restrict __restrict__
|
||||
#endif
|
||||
|
||||
typedef unsigned long size_t;
|
||||
|
||||
typedef struct {
|
||||
size_t we_wordc;
|
||||
char **we_wordv;
|
||||
size_t we_offs;
|
||||
} wordexp_t;
|
||||
|
||||
enum {
|
||||
WRDE_APPEND = (1 << 1),
|
||||
WRDE_NOCMD = (1 << 2)
|
||||
};
|
||||
|
||||
int wordexp(const char *restrict s, wordexp_t *restrict p, int flags);
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
char *filePath = argv[2];
|
||||
|
||||
{
|
||||
// BAD: the user string is injected directly into `wordexp` which performs command substitution
|
||||
|
||||
wordexp_t we;
|
||||
wordexp(filePath, &we, 0);
|
||||
}
|
||||
|
||||
{
|
||||
// GOOD: command substitution is disabled
|
||||
|
||||
wordexp_t we;
|
||||
wordexp(filePath, &we, WRDE_NOCMD);
|
||||
}
|
||||
|
||||
{
|
||||
// GOOD: command substitution is disabled
|
||||
|
||||
wordexp_t we;
|
||||
wordexp(filePath, &we, WRDE_NOCMD | WRDE_APPEND);
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,3 @@
|
||||
| test.cpp:35:3:35:33 | call to runtime_error | Object creation of exception type on stack. Did you forget the throw keyword? |
|
||||
| test.cpp:41:3:41:11 | call to funcTest1 | There is an exception in the function that requires your attention. |
|
||||
| test.cpp:42:3:42:9 | call to DllMain | DllMain contains an exeption not wrapped in a try..catch block. |
|
||||
| test.cpp:42:3:42:9 | call to DllMain | DllMain contains an exception not wrapped in a try..catch block. |
|
||||
|
||||
@@ -1672,6 +1672,8 @@ predicate jumpStep(Node pred, Node succ) {
|
||||
jrk.getTarget() = call.getATarget(_) and
|
||||
succ = getAnOutNode(call, jrk.getTargetReturnKind())
|
||||
)
|
||||
or
|
||||
FlowSummaryImpl::Private::Steps::summaryJumpStep(pred, succ)
|
||||
}
|
||||
|
||||
private class StoreStepConfiguration extends ControlFlowReachabilityConfiguration {
|
||||
|
||||
@@ -61,6 +61,20 @@ module Public {
|
||||
|
||||
/** Gets a summary component for a return of kind `rk`. */
|
||||
SummaryComponent return(ReturnKind rk) { result = TReturnSummaryComponent(rk) }
|
||||
|
||||
/** Gets a summary component for synthetic global `sg`. */
|
||||
SummaryComponent syntheticGlobal(SyntheticGlobal sg) {
|
||||
result = TSyntheticGlobalSummaryComponent(sg)
|
||||
}
|
||||
|
||||
/**
|
||||
* A synthetic global. This represents some form of global state, which
|
||||
* summaries can read and write individually.
|
||||
*/
|
||||
abstract class SyntheticGlobal extends string {
|
||||
bindingset[this]
|
||||
SyntheticGlobal() { any() }
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -256,6 +270,7 @@ module Private {
|
||||
TParameterSummaryComponent(ArgumentPosition pos) or
|
||||
TArgumentSummaryComponent(ParameterPosition pos) or
|
||||
TReturnSummaryComponent(ReturnKind rk) or
|
||||
TSyntheticGlobalSummaryComponent(SummaryComponent::SyntheticGlobal sg) or
|
||||
TWithoutContentSummaryComponent(ContentSet c) or
|
||||
TWithContentSummaryComponent(ContentSet c)
|
||||
|
||||
@@ -563,6 +578,11 @@ module Private {
|
||||
getCallbackReturnType(getNodeType(summaryNodeInputState(pragma[only_bind_out](c),
|
||||
s.tail())), rk)
|
||||
)
|
||||
or
|
||||
exists(SummaryComponent::SyntheticGlobal sg |
|
||||
head = TSyntheticGlobalSummaryComponent(sg) and
|
||||
result = getSyntheticGlobalType(sg)
|
||||
)
|
||||
)
|
||||
or
|
||||
n = summaryNodeOutputState(c, s) and
|
||||
@@ -582,6 +602,11 @@ module Private {
|
||||
getCallbackParameterType(getNodeType(summaryNodeInputState(pragma[only_bind_out](c),
|
||||
s.tail())), pos)
|
||||
)
|
||||
or
|
||||
exists(SummaryComponent::SyntheticGlobal sg |
|
||||
head = TSyntheticGlobalSummaryComponent(sg) and
|
||||
result = getSyntheticGlobalType(sg)
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -692,6 +717,18 @@ module Private {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if there is a jump step from `pred` to `succ`, which is synthesized
|
||||
* from a flow summary.
|
||||
*/
|
||||
predicate summaryJumpStep(Node pred, Node succ) {
|
||||
exists(SummaryComponentStack s |
|
||||
s = SummaryComponentStack::singleton(SummaryComponent::syntheticGlobal(_)) and
|
||||
pred = summaryNodeOutputState(_, s) and
|
||||
succ = summaryNodeInputState(_, s)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if values stored inside content `c` are cleared at `n`. `n` is a
|
||||
* synthesized summary node, so in order for values to be cleared at calls
|
||||
@@ -871,18 +908,28 @@ module Private {
|
||||
AccessPathRange() { relevantSpec(this) }
|
||||
}
|
||||
|
||||
/** Holds if specification component `c` parses as parameter `n`. */
|
||||
/** Holds if specification component `token` parses as parameter `pos`. */
|
||||
predicate parseParam(AccessPathToken token, ArgumentPosition pos) {
|
||||
token.getName() = "Parameter" and
|
||||
pos = parseParamBody(token.getAnArgument())
|
||||
}
|
||||
|
||||
/** Holds if specification component `c` parses as argument `n`. */
|
||||
/** Holds if specification component `token` parses as argument `pos`. */
|
||||
predicate parseArg(AccessPathToken token, ParameterPosition pos) {
|
||||
token.getName() = "Argument" and
|
||||
pos = parseArgBody(token.getAnArgument())
|
||||
}
|
||||
|
||||
/** Holds if specification component `token` parses as synthetic global `sg`. */
|
||||
predicate parseSynthGlobal(AccessPathToken token, string sg) {
|
||||
token.getName() = "SyntheticGlobal" and
|
||||
sg = token.getAnArgument()
|
||||
}
|
||||
|
||||
private class SyntheticGlobalFromAccessPath extends SummaryComponent::SyntheticGlobal {
|
||||
SyntheticGlobalFromAccessPath() { parseSynthGlobal(_, this) }
|
||||
}
|
||||
|
||||
private SummaryComponent interpretComponent(AccessPathToken token) {
|
||||
exists(ParameterPosition pos |
|
||||
parseArg(token, pos) and result = SummaryComponent::argument(pos)
|
||||
@@ -894,6 +941,10 @@ module Private {
|
||||
or
|
||||
token = "ReturnValue" and result = SummaryComponent::return(getReturnValueKind())
|
||||
or
|
||||
exists(string sg |
|
||||
parseSynthGlobal(token, sg) and result = SummaryComponent::syntheticGlobal(sg)
|
||||
)
|
||||
or
|
||||
result = interpretComponentSpecific(token)
|
||||
}
|
||||
|
||||
|
||||
@@ -91,6 +91,12 @@ DataFlowType getCallbackReturnType(DataFlowType t, ReturnKind rk) {
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets the type of synthetic global `sg`. */
|
||||
DataFlowType getSyntheticGlobalType(SummaryComponent::SyntheticGlobal sg) {
|
||||
exists(sg) and
|
||||
result = Gvn::getGlobalValueNumber(any(ObjectType t))
|
||||
}
|
||||
|
||||
bindingset[provenance]
|
||||
private boolean isGenerated(string provenance) {
|
||||
provenance = "generated" and result = true
|
||||
|
||||
@@ -742,7 +742,7 @@ class NoOpInstruction extends Instruction {
|
||||
* The `ReturnInstruction` for a function will have a control-flow successor edge to a block
|
||||
* containing the `ExitFunction` instruction for that function.
|
||||
*
|
||||
* There are two differet return instructions: `ReturnValueInstruction`, for returning a value from
|
||||
* There are two different return instructions: `ReturnValueInstruction`, for returning a value from
|
||||
* a non-`void`-returning function, and `ReturnVoidInstruction`, for returning from a
|
||||
* `void`-returning function.
|
||||
*/
|
||||
@@ -1331,7 +1331,7 @@ class CheckedConvertOrThrowInstruction extends UnaryInstruction {
|
||||
*
|
||||
* If the operand holds a null address, the result is a null address.
|
||||
*
|
||||
* This instruction is used to represent `dyanmic_cast<void*>` in C++, which returns the pointer to
|
||||
* This instruction is used to represent `dynamic_cast<void*>` in C++, which returns the pointer to
|
||||
* the most-derived object.
|
||||
*/
|
||||
class CompleteObjectAddressInstruction extends UnaryInstruction {
|
||||
|
||||
@@ -742,7 +742,7 @@ class NoOpInstruction extends Instruction {
|
||||
* The `ReturnInstruction` for a function will have a control-flow successor edge to a block
|
||||
* containing the `ExitFunction` instruction for that function.
|
||||
*
|
||||
* There are two differet return instructions: `ReturnValueInstruction`, for returning a value from
|
||||
* There are two different return instructions: `ReturnValueInstruction`, for returning a value from
|
||||
* a non-`void`-returning function, and `ReturnVoidInstruction`, for returning from a
|
||||
* `void`-returning function.
|
||||
*/
|
||||
@@ -1331,7 +1331,7 @@ class CheckedConvertOrThrowInstruction extends UnaryInstruction {
|
||||
*
|
||||
* If the operand holds a null address, the result is a null address.
|
||||
*
|
||||
* This instruction is used to represent `dyanmic_cast<void*>` in C++, which returns the pointer to
|
||||
* This instruction is used to represent `dynamic_cast<void*>` in C++, which returns the pointer to
|
||||
* the most-derived object.
|
||||
*/
|
||||
class CompleteObjectAddressInstruction extends UnaryInstruction {
|
||||
|
||||
@@ -64,7 +64,7 @@ private module Cached {
|
||||
or
|
||||
instr = reusedPhiInstruction(_) and
|
||||
// Check that the phi instruction is *not* degenerate, but we can't use
|
||||
// getDegeneratePhiOperand in the first stage with phi instyructions
|
||||
// getDegeneratePhiOperand in the first stage with phi instructions
|
||||
not exists(
|
||||
unique(OldIR::PhiInputOperand operand |
|
||||
operand = instr.(OldIR::PhiInstruction).getAnInputOperand() and
|
||||
@@ -718,7 +718,7 @@ module DefUse {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the rank index of a hyphothetical use one instruction past the end of
|
||||
* Gets the rank index of a hypothetical use one instruction past the end of
|
||||
* the block. This index can be used to determine if a definition reaches the
|
||||
* end of the block, even if the definition is the last instruction in the
|
||||
* block.
|
||||
|
||||
@@ -4243,9 +4243,11 @@ open class KotlinFileExtractor(
|
||||
* this.dispatchReceiver = dispatchReceiver
|
||||
* }
|
||||
*
|
||||
* fun get(): R { return this.dispatchReceiver.FN1() }
|
||||
* override fun get(): R { return this.dispatchReceiver.FN1() }
|
||||
*
|
||||
* fun set(a0: R): Unit { return this.dispatchReceiver.FN2(a0) }
|
||||
* override fun set(a0: R): Unit { return this.dispatchReceiver.FN2(a0) }
|
||||
*
|
||||
* override fun invoke(): R { return this.get() }
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
@@ -4283,8 +4285,8 @@ open class KotlinFileExtractor(
|
||||
)
|
||||
|
||||
val declarationParent = peekDeclStackAsDeclarationParent(propertyReferenceExpr) ?: return
|
||||
val prefix = if (kPropertyClass.owner.name.asString().startsWith("KMutableProperty")) "Mutable" else ""
|
||||
val baseClass = pluginContext.referenceClass(FqName("kotlin.jvm.internal.${prefix}PropertyReference${kPropertyType.arguments.size - 1}"))?.owner?.typeWith()
|
||||
// The base class could be `Any`. `PropertyReference` is used to keep symmetry with function references.
|
||||
val baseClass = pluginContext.referenceClass(FqName("kotlin.jvm.internal.PropertyReference"))?.owner?.typeWith()
|
||||
?: pluginContext.irBuiltIns.anyType
|
||||
|
||||
val classId = extractGeneratedClass(ids, listOf(baseClass, kPropertyType), locId, propertyReferenceExpr, declarationParent)
|
||||
@@ -5043,7 +5045,10 @@ open class KotlinFileExtractor(
|
||||
return
|
||||
}
|
||||
|
||||
if (!st.isFunctionOrKFunction() && !st.isSuspendFunctionOrKFunction()) {
|
||||
fun IrSimpleType.isKProperty() =
|
||||
classFqName?.asString()?.startsWith("kotlin.reflect.KProperty") == true
|
||||
|
||||
if (!st.isFunctionOrKFunction() && !st.isSuspendFunctionOrKFunction() && !st.isKProperty()) {
|
||||
logger.errorElement("Expected to find expression with function type in SAM conversion.", e)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -83,6 +83,8 @@ predicate jumpStep(Node node1, Node node2) {
|
||||
or
|
||||
any(AdditionalValueStep a).step(node1, node2) and
|
||||
node1.getEnclosingCallable() != node2.getEnclosingCallable()
|
||||
or
|
||||
FlowSummaryImpl::Private::Steps::summaryJumpStep(node1, node2)
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -61,6 +61,20 @@ module Public {
|
||||
|
||||
/** Gets a summary component for a return of kind `rk`. */
|
||||
SummaryComponent return(ReturnKind rk) { result = TReturnSummaryComponent(rk) }
|
||||
|
||||
/** Gets a summary component for synthetic global `sg`. */
|
||||
SummaryComponent syntheticGlobal(SyntheticGlobal sg) {
|
||||
result = TSyntheticGlobalSummaryComponent(sg)
|
||||
}
|
||||
|
||||
/**
|
||||
* A synthetic global. This represents some form of global state, which
|
||||
* summaries can read and write individually.
|
||||
*/
|
||||
abstract class SyntheticGlobal extends string {
|
||||
bindingset[this]
|
||||
SyntheticGlobal() { any() }
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -256,6 +270,7 @@ module Private {
|
||||
TParameterSummaryComponent(ArgumentPosition pos) or
|
||||
TArgumentSummaryComponent(ParameterPosition pos) or
|
||||
TReturnSummaryComponent(ReturnKind rk) or
|
||||
TSyntheticGlobalSummaryComponent(SummaryComponent::SyntheticGlobal sg) or
|
||||
TWithoutContentSummaryComponent(ContentSet c) or
|
||||
TWithContentSummaryComponent(ContentSet c)
|
||||
|
||||
@@ -563,6 +578,11 @@ module Private {
|
||||
getCallbackReturnType(getNodeType(summaryNodeInputState(pragma[only_bind_out](c),
|
||||
s.tail())), rk)
|
||||
)
|
||||
or
|
||||
exists(SummaryComponent::SyntheticGlobal sg |
|
||||
head = TSyntheticGlobalSummaryComponent(sg) and
|
||||
result = getSyntheticGlobalType(sg)
|
||||
)
|
||||
)
|
||||
or
|
||||
n = summaryNodeOutputState(c, s) and
|
||||
@@ -582,6 +602,11 @@ module Private {
|
||||
getCallbackParameterType(getNodeType(summaryNodeInputState(pragma[only_bind_out](c),
|
||||
s.tail())), pos)
|
||||
)
|
||||
or
|
||||
exists(SummaryComponent::SyntheticGlobal sg |
|
||||
head = TSyntheticGlobalSummaryComponent(sg) and
|
||||
result = getSyntheticGlobalType(sg)
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -692,6 +717,18 @@ module Private {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if there is a jump step from `pred` to `succ`, which is synthesized
|
||||
* from a flow summary.
|
||||
*/
|
||||
predicate summaryJumpStep(Node pred, Node succ) {
|
||||
exists(SummaryComponentStack s |
|
||||
s = SummaryComponentStack::singleton(SummaryComponent::syntheticGlobal(_)) and
|
||||
pred = summaryNodeOutputState(_, s) and
|
||||
succ = summaryNodeInputState(_, s)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if values stored inside content `c` are cleared at `n`. `n` is a
|
||||
* synthesized summary node, so in order for values to be cleared at calls
|
||||
@@ -871,18 +908,28 @@ module Private {
|
||||
AccessPathRange() { relevantSpec(this) }
|
||||
}
|
||||
|
||||
/** Holds if specification component `c` parses as parameter `n`. */
|
||||
/** Holds if specification component `token` parses as parameter `pos`. */
|
||||
predicate parseParam(AccessPathToken token, ArgumentPosition pos) {
|
||||
token.getName() = "Parameter" and
|
||||
pos = parseParamBody(token.getAnArgument())
|
||||
}
|
||||
|
||||
/** Holds if specification component `c` parses as argument `n`. */
|
||||
/** Holds if specification component `token` parses as argument `pos`. */
|
||||
predicate parseArg(AccessPathToken token, ParameterPosition pos) {
|
||||
token.getName() = "Argument" and
|
||||
pos = parseArgBody(token.getAnArgument())
|
||||
}
|
||||
|
||||
/** Holds if specification component `token` parses as synthetic global `sg`. */
|
||||
predicate parseSynthGlobal(AccessPathToken token, string sg) {
|
||||
token.getName() = "SyntheticGlobal" and
|
||||
sg = token.getAnArgument()
|
||||
}
|
||||
|
||||
private class SyntheticGlobalFromAccessPath extends SummaryComponent::SyntheticGlobal {
|
||||
SyntheticGlobalFromAccessPath() { parseSynthGlobal(_, this) }
|
||||
}
|
||||
|
||||
private SummaryComponent interpretComponent(AccessPathToken token) {
|
||||
exists(ParameterPosition pos |
|
||||
parseArg(token, pos) and result = SummaryComponent::argument(pos)
|
||||
@@ -894,6 +941,10 @@ module Private {
|
||||
or
|
||||
token = "ReturnValue" and result = SummaryComponent::return(getReturnValueKind())
|
||||
or
|
||||
exists(string sg |
|
||||
parseSynthGlobal(token, sg) and result = SummaryComponent::syntheticGlobal(sg)
|
||||
)
|
||||
or
|
||||
result = interpretComponentSpecific(token)
|
||||
}
|
||||
|
||||
|
||||
@@ -52,6 +52,12 @@ DataFlowType getCallbackReturnType(DataFlowType t, ReturnKind rk) {
|
||||
exists(rk)
|
||||
}
|
||||
|
||||
/** Gets the type of synthetic global `sg`. */
|
||||
DataFlowType getSyntheticGlobalType(SummaryComponent::SyntheticGlobal sg) {
|
||||
exists(sg) and
|
||||
result instanceof TypeObject
|
||||
}
|
||||
|
||||
bindingset[provenance]
|
||||
private boolean isGenerated(string provenance) {
|
||||
provenance = "generated" and result = true
|
||||
|
||||
@@ -6432,6 +6432,120 @@ samConversion.kt:
|
||||
# 59| -1: [VarAccess] i0
|
||||
# 59| 0: [IntegerLiteral] 1
|
||||
# 59| 1: [IntegerLiteral] 2
|
||||
# 74| 6: [Method] propertyRefsTest
|
||||
# 74| 3: [TypeAccess] Unit
|
||||
#-----| 4: (Parameters)
|
||||
# 74| 0: [Parameter] prt
|
||||
# 74| 0: [TypeAccess] PropertyRefsTest
|
||||
# 74| 5: [BlockStmt] { ... }
|
||||
# 75| 0: [LocalVariableDeclStmt] var ...;
|
||||
# 75| 1: [LocalVariableDeclExpr] test1
|
||||
# 75| 0: [CastExpr] (...)...
|
||||
# 75| 0: [TypeAccess] IntGetter
|
||||
# 75| 1: [ClassInstanceExpr] new (...)
|
||||
# 75| -4: [AnonymousClass] new IntGetter(...) { ... }
|
||||
# 75| 1: [Constructor]
|
||||
#-----| 4: (Parameters)
|
||||
# 75| 0: [Parameter] <fn>
|
||||
# 75| 5: [BlockStmt] { ... }
|
||||
# 75| 0: [SuperConstructorInvocationStmt] super(...)
|
||||
# 75| 1: [ExprStmt] <Expr>;
|
||||
# 75| 0: [AssignExpr] ...=...
|
||||
# 75| 0: [VarAccess] this.<fn>
|
||||
# 75| -1: [ThisAccess] this
|
||||
# 75| 1: [VarAccess] <fn>
|
||||
# 75| 2: [FieldDeclaration] Function0<Integer> <fn>;
|
||||
# 75| -1: [TypeAccess] Function0<Integer>
|
||||
# 75| 0: [TypeAccess] Integer
|
||||
# 75| 3: [Method] f
|
||||
# 75| 3: [TypeAccess] int
|
||||
# 75| 5: [BlockStmt] { ... }
|
||||
# 75| 0: [ReturnStmt] return ...
|
||||
# 75| 0: [MethodAccess] invoke(...)
|
||||
# 75| -1: [VarAccess] <fn>
|
||||
# 75| -3: [TypeAccess] IntGetter
|
||||
# 75| 0: [PropertyRefExpr] ...::...
|
||||
# 75| -4: [AnonymousClass] new KProperty0<Integer>(...) { ... }
|
||||
# 75| 1: [Constructor]
|
||||
#-----| 4: (Parameters)
|
||||
# 75| 0: [Parameter] <dispatchReceiver>
|
||||
# 75| 5: [BlockStmt] { ... }
|
||||
# 75| 0: [SuperConstructorInvocationStmt] super(...)
|
||||
# 75| 1: [ExprStmt] <Expr>;
|
||||
# 75| 0: [AssignExpr] ...=...
|
||||
# 75| 0: [VarAccess] this.<dispatchReceiver>
|
||||
# 75| -1: [ThisAccess] this
|
||||
# 75| 1: [VarAccess] <dispatchReceiver>
|
||||
# 75| 2: [FieldDeclaration] PropertyRefsTest <dispatchReceiver>;
|
||||
# 75| -1: [TypeAccess] PropertyRefsTest
|
||||
# 75| 3: [Method] get
|
||||
# 75| 5: [BlockStmt] { ... }
|
||||
# 75| 0: [ReturnStmt] return ...
|
||||
# 75| 0: [MethodAccess] getX(...)
|
||||
# 75| -1: [VarAccess] this.<dispatchReceiver>
|
||||
# 75| -1: [ThisAccess] this
|
||||
# 75| 4: [Method] invoke
|
||||
# 75| 5: [BlockStmt] { ... }
|
||||
# 75| 0: [ReturnStmt] return ...
|
||||
# 75| 0: [MethodAccess] get(...)
|
||||
# 75| -1: [ThisAccess] this
|
||||
# 75| -3: [TypeAccess] KProperty0<Integer>
|
||||
# 75| 0: [TypeAccess] Integer
|
||||
# 75| 0: [VarAccess] prt
|
||||
# 76| 1: [LocalVariableDeclStmt] var ...;
|
||||
# 76| 1: [LocalVariableDeclExpr] test2
|
||||
# 76| 0: [CastExpr] (...)...
|
||||
# 76| 0: [TypeAccess] PropertyRefsGetter
|
||||
# 76| 1: [ClassInstanceExpr] new (...)
|
||||
# 76| -4: [AnonymousClass] new PropertyRefsGetter(...) { ... }
|
||||
# 76| 1: [Constructor]
|
||||
#-----| 4: (Parameters)
|
||||
# 76| 0: [Parameter] <fn>
|
||||
# 76| 5: [BlockStmt] { ... }
|
||||
# 76| 0: [SuperConstructorInvocationStmt] super(...)
|
||||
# 76| 1: [ExprStmt] <Expr>;
|
||||
# 76| 0: [AssignExpr] ...=...
|
||||
# 76| 0: [VarAccess] this.<fn>
|
||||
# 76| -1: [ThisAccess] this
|
||||
# 76| 1: [VarAccess] <fn>
|
||||
# 76| 2: [FieldDeclaration] Function1<PropertyRefsTest,Integer> <fn>;
|
||||
# 76| -1: [TypeAccess] Function1<PropertyRefsTest,Integer>
|
||||
# 76| 0: [TypeAccess] PropertyRefsTest
|
||||
# 76| 1: [TypeAccess] Integer
|
||||
# 76| 3: [Method] f
|
||||
# 76| 3: [TypeAccess] int
|
||||
#-----| 4: (Parameters)
|
||||
# 76| 0: [Parameter] prt
|
||||
# 76| 0: [TypeAccess] PropertyRefsTest
|
||||
# 76| 5: [BlockStmt] { ... }
|
||||
# 76| 0: [ReturnStmt] return ...
|
||||
# 76| 0: [MethodAccess] invoke(...)
|
||||
# 76| -1: [VarAccess] <fn>
|
||||
# 76| 0: [VarAccess] prt
|
||||
# 76| -3: [TypeAccess] PropertyRefsGetter
|
||||
# 76| 0: [PropertyRefExpr] ...::...
|
||||
# 76| -4: [AnonymousClass] new KProperty1<PropertyRefsTest,Integer>(...) { ... }
|
||||
# 76| 1: [Constructor]
|
||||
# 76| 5: [BlockStmt] { ... }
|
||||
# 76| 0: [SuperConstructorInvocationStmt] super(...)
|
||||
# 76| 2: [Method] get
|
||||
#-----| 4: (Parameters)
|
||||
# 76| 0: [Parameter] a0
|
||||
# 76| 5: [BlockStmt] { ... }
|
||||
# 76| 0: [ReturnStmt] return ...
|
||||
# 76| 0: [MethodAccess] getX(...)
|
||||
# 76| -1: [VarAccess] a0
|
||||
# 76| 3: [Method] invoke
|
||||
#-----| 4: (Parameters)
|
||||
# 76| 0: [Parameter] a0
|
||||
# 76| 5: [BlockStmt] { ... }
|
||||
# 76| 0: [ReturnStmt] return ...
|
||||
# 76| 0: [MethodAccess] get(...)
|
||||
# 76| -1: [ThisAccess] this
|
||||
# 76| 0: [VarAccess] a0
|
||||
# 76| -3: [TypeAccess] KProperty1<PropertyRefsTest,Integer>
|
||||
# 76| 0: [TypeAccess] PropertyRefsTest
|
||||
# 76| 1: [TypeAccess] Integer
|
||||
# 16| 2: [Interface] IntPredicate
|
||||
# 17| 1: [Method] accept
|
||||
# 17| 3: [TypeAccess] boolean
|
||||
@@ -6520,6 +6634,32 @@ samConversion.kt:
|
||||
# 54| 0: [TypeAccess] int
|
||||
# 54| 1: [Parameter] j
|
||||
# 54| 0: [TypeAccess] int
|
||||
# 62| 8: [Class] PropertyRefsTest
|
||||
# 62| 1: [Constructor] PropertyRefsTest
|
||||
# 62| 5: [BlockStmt] { ... }
|
||||
# 62| 0: [SuperConstructorInvocationStmt] super(...)
|
||||
# 62| 1: [BlockStmt] { ... }
|
||||
# 63| 0: [ExprStmt] <Expr>;
|
||||
# 63| 0: [KtInitializerAssignExpr] ...=...
|
||||
# 63| 0: [VarAccess] x
|
||||
# 63| 2: [Method] getX
|
||||
# 63| 3: [TypeAccess] int
|
||||
# 63| 5: [BlockStmt] { ... }
|
||||
# 63| 0: [ReturnStmt] return ...
|
||||
# 63| 0: [VarAccess] this.x
|
||||
# 63| -1: [ThisAccess] this
|
||||
# 63| 3: [FieldDeclaration] int x;
|
||||
# 63| -1: [TypeAccess] int
|
||||
# 63| 0: [IntegerLiteral] 1
|
||||
# 66| 9: [Interface] PropertyRefsGetter
|
||||
# 67| 1: [Method] f
|
||||
# 67| 3: [TypeAccess] int
|
||||
#-----| 4: (Parameters)
|
||||
# 67| 0: [Parameter] prt
|
||||
# 67| 0: [TypeAccess] PropertyRefsTest
|
||||
# 70| 10: [Interface] IntGetter
|
||||
# 71| 1: [Method] f
|
||||
# 71| 3: [TypeAccess] int
|
||||
whenExpr.kt:
|
||||
# 0| [CompilationUnit] whenExpr
|
||||
# 0| 1: [Class] WhenExprKt
|
||||
|
||||
@@ -4028,6 +4028,72 @@
|
||||
| samConversion.kt:59:8:59:15 | fn1(...) | samConversion.kt:57:9:60:1 | test | MethodAccess |
|
||||
| samConversion.kt:59:12:59:12 | 1 | samConversion.kt:57:9:60:1 | test | IntegerLiteral |
|
||||
| samConversion.kt:59:14:59:14 | 2 | samConversion.kt:57:9:60:1 | test | IntegerLiteral |
|
||||
| samConversion.kt:63:5:63:13 | ...=... | samConversion.kt:62:1:64:1 | PropertyRefsTest | KtInitializerAssignExpr |
|
||||
| samConversion.kt:63:5:63:13 | int | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| samConversion.kt:63:5:63:13 | int | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| samConversion.kt:63:5:63:13 | this | samConversion.kt:63:5:63:13 | getX | ThisAccess |
|
||||
| samConversion.kt:63:5:63:13 | this.x | samConversion.kt:63:5:63:13 | getX | VarAccess |
|
||||
| samConversion.kt:63:5:63:13 | x | samConversion.kt:62:1:64:1 | PropertyRefsTest | VarAccess |
|
||||
| samConversion.kt:63:13:63:13 | 1 | samConversion.kt:62:1:64:1 | PropertyRefsTest | IntegerLiteral |
|
||||
| samConversion.kt:67:5:67:37 | int | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| samConversion.kt:67:11:67:31 | PropertyRefsTest | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| samConversion.kt:71:5:71:16 | int | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| samConversion.kt:74:1:77:1 | Unit | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| samConversion.kt:74:22:74:42 | PropertyRefsTest | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| samConversion.kt:75:5:75:33 | test1 | samConversion.kt:74:1:77:1 | propertyRefsTest | LocalVariableDeclExpr |
|
||||
| samConversion.kt:75:17:75:33 | (...)... | samConversion.kt:74:1:77:1 | propertyRefsTest | CastExpr |
|
||||
| samConversion.kt:75:17:75:33 | ...=... | samConversion.kt:75:17:75:33 | | AssignExpr |
|
||||
| samConversion.kt:75:17:75:33 | <fn> | samConversion.kt:75:17:75:33 | | VarAccess |
|
||||
| samConversion.kt:75:17:75:33 | <fn> | samConversion.kt:75:17:75:33 | f | VarAccess |
|
||||
| samConversion.kt:75:17:75:33 | Function0<Integer> | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| samConversion.kt:75:17:75:33 | IntGetter | samConversion.kt:74:1:77:1 | propertyRefsTest | TypeAccess |
|
||||
| samConversion.kt:75:17:75:33 | IntGetter | samConversion.kt:74:1:77:1 | propertyRefsTest | TypeAccess |
|
||||
| samConversion.kt:75:17:75:33 | Integer | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| samConversion.kt:75:17:75:33 | int | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| samConversion.kt:75:17:75:33 | invoke(...) | samConversion.kt:75:17:75:33 | f | MethodAccess |
|
||||
| samConversion.kt:75:17:75:33 | new (...) | samConversion.kt:74:1:77:1 | propertyRefsTest | ClassInstanceExpr |
|
||||
| samConversion.kt:75:17:75:33 | this | samConversion.kt:75:17:75:33 | | ThisAccess |
|
||||
| samConversion.kt:75:17:75:33 | this.<fn> | samConversion.kt:75:17:75:33 | | VarAccess |
|
||||
| samConversion.kt:75:27:75:29 | prt | samConversion.kt:74:1:77:1 | propertyRefsTest | VarAccess |
|
||||
| samConversion.kt:75:27:75:32 | ...::... | samConversion.kt:74:1:77:1 | propertyRefsTest | PropertyRefExpr |
|
||||
| samConversion.kt:75:27:75:32 | ...=... | samConversion.kt:75:27:75:32 | | AssignExpr |
|
||||
| samConversion.kt:75:27:75:32 | <dispatchReceiver> | samConversion.kt:75:27:75:32 | | VarAccess |
|
||||
| samConversion.kt:75:27:75:32 | Integer | samConversion.kt:74:1:77:1 | propertyRefsTest | TypeAccess |
|
||||
| samConversion.kt:75:27:75:32 | KProperty0<Integer> | samConversion.kt:74:1:77:1 | propertyRefsTest | TypeAccess |
|
||||
| samConversion.kt:75:27:75:32 | PropertyRefsTest | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| samConversion.kt:75:27:75:32 | get(...) | samConversion.kt:75:27:75:32 | invoke | MethodAccess |
|
||||
| samConversion.kt:75:27:75:32 | getX(...) | samConversion.kt:75:27:75:32 | get | MethodAccess |
|
||||
| samConversion.kt:75:27:75:32 | this | samConversion.kt:75:27:75:32 | | ThisAccess |
|
||||
| samConversion.kt:75:27:75:32 | this | samConversion.kt:75:27:75:32 | get | ThisAccess |
|
||||
| samConversion.kt:75:27:75:32 | this | samConversion.kt:75:27:75:32 | invoke | ThisAccess |
|
||||
| samConversion.kt:75:27:75:32 | this.<dispatchReceiver> | samConversion.kt:75:27:75:32 | | VarAccess |
|
||||
| samConversion.kt:75:27:75:32 | this.<dispatchReceiver> | samConversion.kt:75:27:75:32 | get | VarAccess |
|
||||
| samConversion.kt:76:5:76:55 | test2 | samConversion.kt:74:1:77:1 | propertyRefsTest | LocalVariableDeclExpr |
|
||||
| samConversion.kt:76:17:76:55 | (...)... | samConversion.kt:74:1:77:1 | propertyRefsTest | CastExpr |
|
||||
| samConversion.kt:76:17:76:55 | ...=... | samConversion.kt:76:17:76:55 | | AssignExpr |
|
||||
| samConversion.kt:76:17:76:55 | <fn> | samConversion.kt:76:17:76:55 | | VarAccess |
|
||||
| samConversion.kt:76:17:76:55 | <fn> | samConversion.kt:76:17:76:55 | f | VarAccess |
|
||||
| samConversion.kt:76:17:76:55 | Function1<PropertyRefsTest,Integer> | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| samConversion.kt:76:17:76:55 | Integer | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| samConversion.kt:76:17:76:55 | PropertyRefsGetter | samConversion.kt:74:1:77:1 | propertyRefsTest | TypeAccess |
|
||||
| samConversion.kt:76:17:76:55 | PropertyRefsGetter | samConversion.kt:74:1:77:1 | propertyRefsTest | TypeAccess |
|
||||
| samConversion.kt:76:17:76:55 | PropertyRefsTest | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| samConversion.kt:76:17:76:55 | PropertyRefsTest | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| samConversion.kt:76:17:76:55 | int | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| samConversion.kt:76:17:76:55 | invoke(...) | samConversion.kt:76:17:76:55 | f | MethodAccess |
|
||||
| samConversion.kt:76:17:76:55 | new (...) | samConversion.kt:74:1:77:1 | propertyRefsTest | ClassInstanceExpr |
|
||||
| samConversion.kt:76:17:76:55 | prt | samConversion.kt:76:17:76:55 | f | VarAccess |
|
||||
| samConversion.kt:76:17:76:55 | this | samConversion.kt:76:17:76:55 | | ThisAccess |
|
||||
| samConversion.kt:76:17:76:55 | this.<fn> | samConversion.kt:76:17:76:55 | | VarAccess |
|
||||
| samConversion.kt:76:36:76:54 | ...::... | samConversion.kt:74:1:77:1 | propertyRefsTest | PropertyRefExpr |
|
||||
| samConversion.kt:76:36:76:54 | Integer | samConversion.kt:74:1:77:1 | propertyRefsTest | TypeAccess |
|
||||
| samConversion.kt:76:36:76:54 | KProperty1<PropertyRefsTest,Integer> | samConversion.kt:74:1:77:1 | propertyRefsTest | TypeAccess |
|
||||
| samConversion.kt:76:36:76:54 | PropertyRefsTest | samConversion.kt:74:1:77:1 | propertyRefsTest | TypeAccess |
|
||||
| samConversion.kt:76:36:76:54 | a0 | samConversion.kt:76:36:76:54 | get | VarAccess |
|
||||
| samConversion.kt:76:36:76:54 | a0 | samConversion.kt:76:36:76:54 | invoke | VarAccess |
|
||||
| samConversion.kt:76:36:76:54 | get(...) | samConversion.kt:76:36:76:54 | invoke | MethodAccess |
|
||||
| samConversion.kt:76:36:76:54 | getX(...) | samConversion.kt:76:36:76:54 | get | MethodAccess |
|
||||
| samConversion.kt:76:36:76:54 | this | samConversion.kt:76:36:76:54 | invoke | ThisAccess |
|
||||
| whenExpr.kt:1:1:9:1 | int | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| whenExpr.kt:1:14:1:19 | int | file://:0:0:0:0 | <none> | TypeAccess |
|
||||
| whenExpr.kt:2:10:8:3 | <Stmt> | whenExpr.kt:1:1:9:1 | testWhen | StmtExpr |
|
||||
|
||||
@@ -241,6 +241,12 @@ anon_class_member_modifiers
|
||||
| samConversion.kt:46:32:46:44 | new Function1<Integer,Boolean>(...) { ... } | samConversion.kt:46:32:46:44 | invoke | override, public |
|
||||
| samConversion.kt:58:14:58:45 | new InterfaceFn1Sus(...) { ... } | samConversion.kt:58:14:58:45 | fn1 | override, public, suspend |
|
||||
| samConversion.kt:58:30:58:45 | new Function2<Integer,Integer,Unit>(...) { ... } | samConversion.kt:58:30:58:45 | invoke | override, public, suspend |
|
||||
| samConversion.kt:75:17:75:33 | new IntGetter(...) { ... } | samConversion.kt:75:17:75:33 | f | override, public |
|
||||
| samConversion.kt:75:27:75:32 | new KProperty0<Integer>(...) { ... } | samConversion.kt:75:27:75:32 | get | override, public |
|
||||
| samConversion.kt:75:27:75:32 | new KProperty0<Integer>(...) { ... } | samConversion.kt:75:27:75:32 | invoke | override, public |
|
||||
| samConversion.kt:76:17:76:55 | new PropertyRefsGetter(...) { ... } | samConversion.kt:76:17:76:55 | f | override, public |
|
||||
| samConversion.kt:76:36:76:54 | new KProperty1<PropertyRefsTest,Integer>(...) { ... } | samConversion.kt:76:36:76:54 | get | override, public |
|
||||
| samConversion.kt:76:36:76:54 | new KProperty1<PropertyRefsTest,Integer>(...) { ... } | samConversion.kt:76:36:76:54 | invoke | override, public |
|
||||
nonOverrideInvoke
|
||||
| funcExprs.kt:36:29:36:117 | ...->... | funcExprs.kt:36:29:36:117 | invoke | 23 |
|
||||
| funcExprs.kt:90:15:90:69 | ...->... | funcExprs.kt:90:15:90:69 | invoke | 23 |
|
||||
|
||||
@@ -58,3 +58,20 @@ suspend fun test() {
|
||||
val i0 = InterfaceFn1Sus { a, b -> Unit }
|
||||
i0.fn1(1,2)
|
||||
}
|
||||
|
||||
class PropertyRefsTest {
|
||||
val x = 1
|
||||
}
|
||||
|
||||
fun interface PropertyRefsGetter {
|
||||
fun f(prt: PropertyRefsTest): Int
|
||||
}
|
||||
|
||||
fun interface IntGetter {
|
||||
fun f(): Int
|
||||
}
|
||||
|
||||
fun propertyRefsTest(prt: PropertyRefsTest) {
|
||||
val test1 = IntGetter(prt::x)
|
||||
val test2 = PropertyRefsGetter(PropertyRefsTest::x)
|
||||
}
|
||||
|
||||
@@ -2,21 +2,21 @@ variableInitializerType
|
||||
| reflection.kt:7:9:7:54 | KFunction<Double> ref | file://<external>/KFunction.class:0:0:0:0 | KFunction<Double> | reflection.kt:7:49:7:54 | new Function2<Ccc,Integer,Double>(...) { ... } | file://<external>/Function2.class:0:0:0:0 | Function2<Ccc,Integer,Double> | true |
|
||||
| reflection.kt:7:9:7:54 | KFunction<Double> ref | file://<external>/KFunction.class:0:0:0:0 | KFunction<Double> | reflection.kt:7:49:7:54 | new Function2<Ccc,Integer,Double>(...) { ... } | file://<external>/FunctionReference.class:0:0:0:0 | FunctionReference | true |
|
||||
| reflection.kt:10:9:10:42 | KProperty1<C,Integer> x0 | file://<external>/KProperty1.class:0:0:0:0 | KProperty1<C,Integer> | reflection.kt:10:38:10:42 | new KProperty1<C,Integer>(...) { ... } | file://<external>/KProperty1.class:0:0:0:0 | KProperty1<C,Integer> | true |
|
||||
| reflection.kt:10:9:10:42 | KProperty1<C,Integer> x0 | file://<external>/KProperty1.class:0:0:0:0 | KProperty1<C,Integer> | reflection.kt:10:38:10:42 | new KProperty1<C,Integer>(...) { ... } | file://<external>/PropertyReference1.class:0:0:0:0 | PropertyReference1 | true |
|
||||
| reflection.kt:10:9:10:42 | KProperty1<C,Integer> x0 | file://<external>/KProperty1.class:0:0:0:0 | KProperty1<C,Integer> | reflection.kt:10:38:10:42 | new KProperty1<C,Integer>(...) { ... } | file://<external>/PropertyReference.class:0:0:0:0 | PropertyReference | true |
|
||||
| reflection.kt:13:9:13:53 | Getter<C,Integer> x3 | file://<external>/KProperty1$Getter.class:0:0:0:0 | Getter<C,Integer> | file://<external>/KProperty1$Getter.class:0:0:0:0 | Getter<C,Integer> | file://<external>/Function1.class:0:0:0:0 | Function1<C,Integer> | true |
|
||||
| reflection.kt:13:9:13:53 | Getter<C,Integer> x3 | file://<external>/KProperty1$Getter.class:0:0:0:0 | Getter<C,Integer> | file://<external>/KProperty1$Getter.class:0:0:0:0 | Getter<C,Integer> | file://<external>/KProperty$Getter.class:0:0:0:0 | Getter<Integer> | true |
|
||||
| reflection.kt:14:9:14:44 | KFunction<Integer> x4 | file://<external>/KFunction.class:0:0:0:0 | KFunction<Integer> | reflection.kt:14:38:14:44 | new Function1<C,Integer>(...) { ... } | file://<external>/Function1.class:0:0:0:0 | Function1<C,Integer> | true |
|
||||
| reflection.kt:14:9:14:44 | KFunction<Integer> x4 | file://<external>/KFunction.class:0:0:0:0 | KFunction<Integer> | reflection.kt:14:38:14:44 | new Function1<C,Integer>(...) { ... } | file://<external>/FunctionReference.class:0:0:0:0 | FunctionReference | true |
|
||||
| reflection.kt:15:9:15:41 | KProperty0<Integer> x5 | file://<external>/KProperty0.class:0:0:0:0 | KProperty0<Integer> | reflection.kt:15:35:15:41 | new KProperty0<Integer>(...) { ... } | file://<external>/KProperty0.class:0:0:0:0 | KProperty0<Integer> | true |
|
||||
| reflection.kt:15:9:15:41 | KProperty0<Integer> x5 | file://<external>/KProperty0.class:0:0:0:0 | KProperty0<Integer> | reflection.kt:15:35:15:41 | new KProperty0<Integer>(...) { ... } | file://<external>/PropertyReference0.class:0:0:0:0 | PropertyReference0 | true |
|
||||
| reflection.kt:15:9:15:41 | KProperty0<Integer> x5 | file://<external>/KProperty0.class:0:0:0:0 | KProperty0<Integer> | reflection.kt:15:35:15:41 | new KProperty0<Integer>(...) { ... } | file://<external>/PropertyReference.class:0:0:0:0 | PropertyReference | true |
|
||||
| reflection.kt:17:9:17:49 | KMutableProperty1<C,Integer> y0 | file://<external>/KMutableProperty1.class:0:0:0:0 | KMutableProperty1<C,Integer> | reflection.kt:17:45:17:49 | new KMutableProperty1<C,Integer>(...) { ... } | file://<external>/KMutableProperty1.class:0:0:0:0 | KMutableProperty1<C,Integer> | true |
|
||||
| reflection.kt:17:9:17:49 | KMutableProperty1<C,Integer> y0 | file://<external>/KMutableProperty1.class:0:0:0:0 | KMutableProperty1<C,Integer> | reflection.kt:17:45:17:49 | new KMutableProperty1<C,Integer>(...) { ... } | file://<external>/MutablePropertyReference1.class:0:0:0:0 | MutablePropertyReference1 | true |
|
||||
| reflection.kt:17:9:17:49 | KMutableProperty1<C,Integer> y0 | file://<external>/KMutableProperty1.class:0:0:0:0 | KMutableProperty1<C,Integer> | reflection.kt:17:45:17:49 | new KMutableProperty1<C,Integer>(...) { ... } | file://<external>/PropertyReference.class:0:0:0:0 | PropertyReference | true |
|
||||
| reflection.kt:20:9:20:60 | Setter<C,Integer> y3 | file://<external>/KMutableProperty1$Setter.class:0:0:0:0 | Setter<C,Integer> | file://<external>/KMutableProperty1$Setter.class:0:0:0:0 | Setter<C,Integer> | file://<external>/Function2.class:0:0:0:0 | Function2<C,Integer,Unit> | true |
|
||||
| reflection.kt:20:9:20:60 | Setter<C,Integer> y3 | file://<external>/KMutableProperty1$Setter.class:0:0:0:0 | Setter<C,Integer> | file://<external>/KMutableProperty1$Setter.class:0:0:0:0 | Setter<C,Integer> | file://<external>/KMutableProperty$Setter.class:0:0:0:0 | Setter<Integer> | true |
|
||||
| reflection.kt:21:9:21:50 | KFunction<Unit> y4 | file://<external>/KFunction.class:0:0:0:0 | KFunction<Unit> | reflection.kt:21:44:21:50 | new Function2<C,Integer,Unit>(...) { ... } | file://<external>/Function2.class:0:0:0:0 | Function2<C,Integer,Unit> | true |
|
||||
| reflection.kt:21:9:21:50 | KFunction<Unit> y4 | file://<external>/KFunction.class:0:0:0:0 | KFunction<Unit> | reflection.kt:21:44:21:50 | new Function2<C,Integer,Unit>(...) { ... } | file://<external>/FunctionReference.class:0:0:0:0 | FunctionReference | true |
|
||||
| reflection.kt:22:9:22:48 | KMutableProperty0<Integer> y5 | file://<external>/KMutableProperty0.class:0:0:0:0 | KMutableProperty0<Integer> | reflection.kt:22:42:22:48 | new KMutableProperty0<Integer>(...) { ... } | file://<external>/KMutableProperty0.class:0:0:0:0 | KMutableProperty0<Integer> | true |
|
||||
| reflection.kt:22:9:22:48 | KMutableProperty0<Integer> y5 | file://<external>/KMutableProperty0.class:0:0:0:0 | KMutableProperty0<Integer> | reflection.kt:22:42:22:48 | new KMutableProperty0<Integer>(...) { ... } | file://<external>/MutablePropertyReference0.class:0:0:0:0 | MutablePropertyReference0 | true |
|
||||
| reflection.kt:22:9:22:48 | KMutableProperty0<Integer> y5 | file://<external>/KMutableProperty0.class:0:0:0:0 | KMutableProperty0<Integer> | reflection.kt:22:42:22:48 | new KMutableProperty0<Integer>(...) { ... } | file://<external>/PropertyReference.class:0:0:0:0 | PropertyReference | true |
|
||||
| reflection.kt:24:9:24:91 | KProperty2<C,Integer,Integer> prop | file://<external>/KProperty2.class:0:0:0:0 | KProperty2<C,Integer,Integer> | file://<external>/KProperty2.class:0:0:0:0 | KProperty2<C,Integer,Integer> | file://<external>/Function2.class:0:0:0:0 | Function2<C,Integer,Integer> | true |
|
||||
| reflection.kt:24:9:24:91 | KProperty2<C,Integer,Integer> prop | file://<external>/KProperty2.class:0:0:0:0 | KProperty2<C,Integer,Integer> | file://<external>/KProperty2.class:0:0:0:0 | KProperty2<C,Integer,Integer> | file://<external>/KProperty.class:0:0:0:0 | KProperty<Integer> | true |
|
||||
| reflection.kt:116:9:116:44 | KFunction<Unit> x | file://<external>/KFunction.class:0:0:0:0 | KFunction<Unit> | reflection.kt:116:40:116:44 | new Function1<Integer,Unit>(...) { ... } | file://<external>/Function1.class:0:0:0:0 | Function1<Integer,Unit> | true |
|
||||
@@ -243,3 +243,251 @@ compGenerated
|
||||
| reflection.kt:105:18:105:31 | getProp1 | 3 |
|
||||
| reflection.kt:105:18:105:31 | setProp1 | 3 |
|
||||
| reflection.kt:126:9:126:13 | | 1 |
|
||||
propertyReferenceOverrides
|
||||
| reflection.kt:10:38:10:42 | ...::... | reflection.kt:10:38:10:42 | get | kotlin.reflect.KProperty1<C,Integer>.get(Reflection.C) |
|
||||
| reflection.kt:10:38:10:42 | ...::... | reflection.kt:10:38:10:42 | invoke | kotlin.jvm.functions.Function1<C,Integer>.invoke(Reflection.C) |
|
||||
| reflection.kt:15:35:15:41 | ...::... | reflection.kt:15:35:15:41 | get | kotlin.reflect.KProperty0<Integer>.get() |
|
||||
| reflection.kt:15:35:15:41 | ...::... | reflection.kt:15:35:15:41 | invoke | kotlin.jvm.functions.Function0<Integer>.invoke() |
|
||||
| reflection.kt:17:45:17:49 | ...::... | reflection.kt:17:45:17:49 | get | kotlin.reflect.KProperty1<C,Integer>.get(Reflection.C) |
|
||||
| reflection.kt:17:45:17:49 | ...::... | reflection.kt:17:45:17:49 | invoke | kotlin.jvm.functions.Function1<C,Integer>.invoke(Reflection.C) |
|
||||
| reflection.kt:22:42:22:48 | ...::... | reflection.kt:22:42:22:48 | get | kotlin.reflect.KProperty0<Integer>.get() |
|
||||
| reflection.kt:22:42:22:48 | ...::... | reflection.kt:22:42:22:48 | invoke | kotlin.jvm.functions.Function0<Integer>.invoke() |
|
||||
| reflection.kt:50:13:50:28 | ...::... | reflection.kt:50:13:50:28 | get | kotlin.reflect.KProperty1<String,Character>.get(java.lang.String) |
|
||||
| reflection.kt:50:13:50:28 | ...::... | reflection.kt:50:13:50:28 | invoke | kotlin.jvm.functions.Function1<String,Character>.invoke(java.lang.String) |
|
||||
| reflection.kt:51:13:51:28 | ...::... | reflection.kt:51:13:51:28 | get | kotlin.reflect.KProperty0<Character>.get() |
|
||||
| reflection.kt:51:13:51:28 | ...::... | reflection.kt:51:13:51:28 | invoke | kotlin.jvm.functions.Function0<Character>.invoke() |
|
||||
| reflection.kt:67:17:67:32 | ...::... | reflection.kt:67:17:67:32 | get | kotlin.reflect.KProperty1<Generic<Integer>,Integer>.get(Class1.Generic) |
|
||||
| reflection.kt:67:17:67:32 | ...::... | reflection.kt:67:17:67:32 | invoke | kotlin.jvm.functions.Function1<Generic<Integer>,Integer>.invoke(Class1.Generic) |
|
||||
| reflection.kt:67:17:67:32 | ...::... | reflection.kt:67:17:67:32 | set | kotlin.reflect.KMutableProperty1<Generic<Integer>,Integer>.set(Class1.Generic,java.lang.Integer) |
|
||||
| reflection.kt:68:17:68:34 | ...::... | reflection.kt:68:17:68:34 | get | kotlin.reflect.KProperty0<Integer>.get() |
|
||||
| reflection.kt:68:17:68:34 | ...::... | reflection.kt:68:17:68:34 | invoke | kotlin.jvm.functions.Function0<Integer>.invoke() |
|
||||
| reflection.kt:68:17:68:34 | ...::... | reflection.kt:68:17:68:34 | set | kotlin.reflect.KMutableProperty0<Integer>.set(java.lang.Integer) |
|
||||
| reflection.kt:70:17:70:30 | ...::... | reflection.kt:70:17:70:30 | get | kotlin.reflect.KProperty0<Integer>.get() |
|
||||
| reflection.kt:70:17:70:30 | ...::... | reflection.kt:70:17:70:30 | invoke | kotlin.jvm.functions.Function0<Integer>.invoke() |
|
||||
| reflection.kt:71:17:71:34 | ...::... | reflection.kt:71:17:71:34 | get | kotlin.reflect.KProperty0<Integer>.get() |
|
||||
| reflection.kt:71:17:71:34 | ...::... | reflection.kt:71:17:71:34 | invoke | kotlin.jvm.functions.Function0<Integer>.invoke() |
|
||||
| reflection.kt:72:17:72:35 | ...::... | reflection.kt:72:17:72:35 | get | kotlin.reflect.KProperty0<Integer>.get() |
|
||||
| reflection.kt:72:17:72:35 | ...::... | reflection.kt:72:17:72:35 | invoke | kotlin.jvm.functions.Function0<Integer>.invoke() |
|
||||
| reflection.kt:109:17:109:27 | ...::... | reflection.kt:109:17:109:27 | get | kotlin.reflect.KProperty0<Integer>.get() |
|
||||
| reflection.kt:109:17:109:27 | ...::... | reflection.kt:109:17:109:27 | invoke | kotlin.jvm.functions.Function0<Integer>.invoke() |
|
||||
notImplementedInterfaceMembers
|
||||
| reflection.kt:10:38:10:42 | ...::... | kotlin.reflect.KCallable<Integer>.call(java.lang.Object[]) |
|
||||
| reflection.kt:10:38:10:42 | ...::... | kotlin.reflect.KCallable<Integer>.callBy(java.util.Map) |
|
||||
| reflection.kt:10:38:10:42 | ...::... | kotlin.reflect.KCallable<Integer>.getName() |
|
||||
| reflection.kt:10:38:10:42 | ...::... | kotlin.reflect.KCallable<Integer>.getParameters() |
|
||||
| reflection.kt:10:38:10:42 | ...::... | kotlin.reflect.KCallable<Integer>.getReturnType() |
|
||||
| reflection.kt:10:38:10:42 | ...::... | kotlin.reflect.KCallable<Integer>.getTypeParameters() |
|
||||
| reflection.kt:10:38:10:42 | ...::... | kotlin.reflect.KCallable<Integer>.getVisibility() |
|
||||
| reflection.kt:10:38:10:42 | ...::... | kotlin.reflect.KCallable<Integer>.isAbstract() |
|
||||
| reflection.kt:10:38:10:42 | ...::... | kotlin.reflect.KCallable<Integer>.isFinal() |
|
||||
| reflection.kt:10:38:10:42 | ...::... | kotlin.reflect.KCallable<Integer>.isOpen() |
|
||||
| reflection.kt:10:38:10:42 | ...::... | kotlin.reflect.KCallable<Integer>.isSuspend() |
|
||||
| reflection.kt:10:38:10:42 | ...::... | kotlin.reflect.KProperty1<C,Integer>.getDelegate(Reflection.C) |
|
||||
| reflection.kt:10:38:10:42 | ...::... | kotlin.reflect.KProperty1<C,Integer>.getGetter() |
|
||||
| reflection.kt:10:38:10:42 | ...::... | kotlin.reflect.KProperty<Integer>.getGetter() |
|
||||
| reflection.kt:10:38:10:42 | ...::... | kotlin.reflect.KProperty<Integer>.isConst() |
|
||||
| reflection.kt:10:38:10:42 | ...::... | kotlin.reflect.KProperty<Integer>.isLateinit() |
|
||||
| reflection.kt:10:38:10:42 | ...::... | kotlin.reflect.KProperty<Object>.getGetter() |
|
||||
| reflection.kt:15:35:15:41 | ...::... | kotlin.reflect.KCallable<Integer>.call(java.lang.Object[]) |
|
||||
| reflection.kt:15:35:15:41 | ...::... | kotlin.reflect.KCallable<Integer>.callBy(java.util.Map) |
|
||||
| reflection.kt:15:35:15:41 | ...::... | kotlin.reflect.KCallable<Integer>.getName() |
|
||||
| reflection.kt:15:35:15:41 | ...::... | kotlin.reflect.KCallable<Integer>.getParameters() |
|
||||
| reflection.kt:15:35:15:41 | ...::... | kotlin.reflect.KCallable<Integer>.getReturnType() |
|
||||
| reflection.kt:15:35:15:41 | ...::... | kotlin.reflect.KCallable<Integer>.getTypeParameters() |
|
||||
| reflection.kt:15:35:15:41 | ...::... | kotlin.reflect.KCallable<Integer>.getVisibility() |
|
||||
| reflection.kt:15:35:15:41 | ...::... | kotlin.reflect.KCallable<Integer>.isAbstract() |
|
||||
| reflection.kt:15:35:15:41 | ...::... | kotlin.reflect.KCallable<Integer>.isFinal() |
|
||||
| reflection.kt:15:35:15:41 | ...::... | kotlin.reflect.KCallable<Integer>.isOpen() |
|
||||
| reflection.kt:15:35:15:41 | ...::... | kotlin.reflect.KCallable<Integer>.isSuspend() |
|
||||
| reflection.kt:15:35:15:41 | ...::... | kotlin.reflect.KProperty0<Integer>.getDelegate() |
|
||||
| reflection.kt:15:35:15:41 | ...::... | kotlin.reflect.KProperty0<Integer>.getGetter() |
|
||||
| reflection.kt:15:35:15:41 | ...::... | kotlin.reflect.KProperty<Integer>.getGetter() |
|
||||
| reflection.kt:15:35:15:41 | ...::... | kotlin.reflect.KProperty<Integer>.isConst() |
|
||||
| reflection.kt:15:35:15:41 | ...::... | kotlin.reflect.KProperty<Integer>.isLateinit() |
|
||||
| reflection.kt:15:35:15:41 | ...::... | kotlin.reflect.KProperty<Object>.getGetter() |
|
||||
| reflection.kt:17:45:17:49 | ...::... | kotlin.reflect.KCallable<Integer>.call(java.lang.Object[]) |
|
||||
| reflection.kt:17:45:17:49 | ...::... | kotlin.reflect.KCallable<Integer>.callBy(java.util.Map) |
|
||||
| reflection.kt:17:45:17:49 | ...::... | kotlin.reflect.KCallable<Integer>.getName() |
|
||||
| reflection.kt:17:45:17:49 | ...::... | kotlin.reflect.KCallable<Integer>.getParameters() |
|
||||
| reflection.kt:17:45:17:49 | ...::... | kotlin.reflect.KCallable<Integer>.getReturnType() |
|
||||
| reflection.kt:17:45:17:49 | ...::... | kotlin.reflect.KCallable<Integer>.getTypeParameters() |
|
||||
| reflection.kt:17:45:17:49 | ...::... | kotlin.reflect.KCallable<Integer>.getVisibility() |
|
||||
| reflection.kt:17:45:17:49 | ...::... | kotlin.reflect.KCallable<Integer>.isAbstract() |
|
||||
| reflection.kt:17:45:17:49 | ...::... | kotlin.reflect.KCallable<Integer>.isFinal() |
|
||||
| reflection.kt:17:45:17:49 | ...::... | kotlin.reflect.KCallable<Integer>.isOpen() |
|
||||
| reflection.kt:17:45:17:49 | ...::... | kotlin.reflect.KCallable<Integer>.isSuspend() |
|
||||
| reflection.kt:17:45:17:49 | ...::... | kotlin.reflect.KMutableProperty1<C,Integer>.getSetter() |
|
||||
| reflection.kt:17:45:17:49 | ...::... | kotlin.reflect.KMutableProperty1<C,Integer>.set(Reflection.C,java.lang.Integer) |
|
||||
| reflection.kt:17:45:17:49 | ...::... | kotlin.reflect.KMutableProperty<Integer>.getSetter() |
|
||||
| reflection.kt:17:45:17:49 | ...::... | kotlin.reflect.KProperty1<C,Integer>.getDelegate(Reflection.C) |
|
||||
| reflection.kt:17:45:17:49 | ...::... | kotlin.reflect.KProperty1<C,Integer>.getGetter() |
|
||||
| reflection.kt:17:45:17:49 | ...::... | kotlin.reflect.KProperty<Integer>.getGetter() |
|
||||
| reflection.kt:17:45:17:49 | ...::... | kotlin.reflect.KProperty<Integer>.isConst() |
|
||||
| reflection.kt:17:45:17:49 | ...::... | kotlin.reflect.KProperty<Integer>.isLateinit() |
|
||||
| reflection.kt:17:45:17:49 | ...::... | kotlin.reflect.KProperty<Object>.getGetter() |
|
||||
| reflection.kt:22:42:22:48 | ...::... | kotlin.reflect.KCallable<Integer>.call(java.lang.Object[]) |
|
||||
| reflection.kt:22:42:22:48 | ...::... | kotlin.reflect.KCallable<Integer>.callBy(java.util.Map) |
|
||||
| reflection.kt:22:42:22:48 | ...::... | kotlin.reflect.KCallable<Integer>.getName() |
|
||||
| reflection.kt:22:42:22:48 | ...::... | kotlin.reflect.KCallable<Integer>.getParameters() |
|
||||
| reflection.kt:22:42:22:48 | ...::... | kotlin.reflect.KCallable<Integer>.getReturnType() |
|
||||
| reflection.kt:22:42:22:48 | ...::... | kotlin.reflect.KCallable<Integer>.getTypeParameters() |
|
||||
| reflection.kt:22:42:22:48 | ...::... | kotlin.reflect.KCallable<Integer>.getVisibility() |
|
||||
| reflection.kt:22:42:22:48 | ...::... | kotlin.reflect.KCallable<Integer>.isAbstract() |
|
||||
| reflection.kt:22:42:22:48 | ...::... | kotlin.reflect.KCallable<Integer>.isFinal() |
|
||||
| reflection.kt:22:42:22:48 | ...::... | kotlin.reflect.KCallable<Integer>.isOpen() |
|
||||
| reflection.kt:22:42:22:48 | ...::... | kotlin.reflect.KCallable<Integer>.isSuspend() |
|
||||
| reflection.kt:22:42:22:48 | ...::... | kotlin.reflect.KMutableProperty0<Integer>.getSetter() |
|
||||
| reflection.kt:22:42:22:48 | ...::... | kotlin.reflect.KMutableProperty0<Integer>.set(java.lang.Integer) |
|
||||
| reflection.kt:22:42:22:48 | ...::... | kotlin.reflect.KMutableProperty<Integer>.getSetter() |
|
||||
| reflection.kt:22:42:22:48 | ...::... | kotlin.reflect.KProperty0<Integer>.getDelegate() |
|
||||
| reflection.kt:22:42:22:48 | ...::... | kotlin.reflect.KProperty0<Integer>.getGetter() |
|
||||
| reflection.kt:22:42:22:48 | ...::... | kotlin.reflect.KProperty<Integer>.getGetter() |
|
||||
| reflection.kt:22:42:22:48 | ...::... | kotlin.reflect.KProperty<Integer>.isConst() |
|
||||
| reflection.kt:22:42:22:48 | ...::... | kotlin.reflect.KProperty<Integer>.isLateinit() |
|
||||
| reflection.kt:22:42:22:48 | ...::... | kotlin.reflect.KProperty<Object>.getGetter() |
|
||||
| reflection.kt:50:13:50:28 | ...::... | kotlin.reflect.KCallable<Character>.call(java.lang.Object[]) |
|
||||
| reflection.kt:50:13:50:28 | ...::... | kotlin.reflect.KCallable<Character>.callBy(java.util.Map) |
|
||||
| reflection.kt:50:13:50:28 | ...::... | kotlin.reflect.KCallable<Character>.getName() |
|
||||
| reflection.kt:50:13:50:28 | ...::... | kotlin.reflect.KCallable<Character>.getParameters() |
|
||||
| reflection.kt:50:13:50:28 | ...::... | kotlin.reflect.KCallable<Character>.getReturnType() |
|
||||
| reflection.kt:50:13:50:28 | ...::... | kotlin.reflect.KCallable<Character>.getTypeParameters() |
|
||||
| reflection.kt:50:13:50:28 | ...::... | kotlin.reflect.KCallable<Character>.getVisibility() |
|
||||
| reflection.kt:50:13:50:28 | ...::... | kotlin.reflect.KCallable<Character>.isAbstract() |
|
||||
| reflection.kt:50:13:50:28 | ...::... | kotlin.reflect.KCallable<Character>.isFinal() |
|
||||
| reflection.kt:50:13:50:28 | ...::... | kotlin.reflect.KCallable<Character>.isOpen() |
|
||||
| reflection.kt:50:13:50:28 | ...::... | kotlin.reflect.KCallable<Character>.isSuspend() |
|
||||
| reflection.kt:50:13:50:28 | ...::... | kotlin.reflect.KProperty1<String,Character>.getDelegate(java.lang.String) |
|
||||
| reflection.kt:50:13:50:28 | ...::... | kotlin.reflect.KProperty1<String,Character>.getGetter() |
|
||||
| reflection.kt:50:13:50:28 | ...::... | kotlin.reflect.KProperty<Character>.getGetter() |
|
||||
| reflection.kt:50:13:50:28 | ...::... | kotlin.reflect.KProperty<Character>.isConst() |
|
||||
| reflection.kt:50:13:50:28 | ...::... | kotlin.reflect.KProperty<Character>.isLateinit() |
|
||||
| reflection.kt:50:13:50:28 | ...::... | kotlin.reflect.KProperty<Object>.getGetter() |
|
||||
| reflection.kt:51:13:51:28 | ...::... | kotlin.reflect.KCallable<Character>.call(java.lang.Object[]) |
|
||||
| reflection.kt:51:13:51:28 | ...::... | kotlin.reflect.KCallable<Character>.callBy(java.util.Map) |
|
||||
| reflection.kt:51:13:51:28 | ...::... | kotlin.reflect.KCallable<Character>.getName() |
|
||||
| reflection.kt:51:13:51:28 | ...::... | kotlin.reflect.KCallable<Character>.getParameters() |
|
||||
| reflection.kt:51:13:51:28 | ...::... | kotlin.reflect.KCallable<Character>.getReturnType() |
|
||||
| reflection.kt:51:13:51:28 | ...::... | kotlin.reflect.KCallable<Character>.getTypeParameters() |
|
||||
| reflection.kt:51:13:51:28 | ...::... | kotlin.reflect.KCallable<Character>.getVisibility() |
|
||||
| reflection.kt:51:13:51:28 | ...::... | kotlin.reflect.KCallable<Character>.isAbstract() |
|
||||
| reflection.kt:51:13:51:28 | ...::... | kotlin.reflect.KCallable<Character>.isFinal() |
|
||||
| reflection.kt:51:13:51:28 | ...::... | kotlin.reflect.KCallable<Character>.isOpen() |
|
||||
| reflection.kt:51:13:51:28 | ...::... | kotlin.reflect.KCallable<Character>.isSuspend() |
|
||||
| reflection.kt:51:13:51:28 | ...::... | kotlin.reflect.KProperty0<Character>.getDelegate() |
|
||||
| reflection.kt:51:13:51:28 | ...::... | kotlin.reflect.KProperty0<Character>.getGetter() |
|
||||
| reflection.kt:51:13:51:28 | ...::... | kotlin.reflect.KProperty<Character>.getGetter() |
|
||||
| reflection.kt:51:13:51:28 | ...::... | kotlin.reflect.KProperty<Character>.isConst() |
|
||||
| reflection.kt:51:13:51:28 | ...::... | kotlin.reflect.KProperty<Character>.isLateinit() |
|
||||
| reflection.kt:51:13:51:28 | ...::... | kotlin.reflect.KProperty<Object>.getGetter() |
|
||||
| reflection.kt:67:17:67:32 | ...::... | kotlin.reflect.KCallable<Integer>.call(java.lang.Object[]) |
|
||||
| reflection.kt:67:17:67:32 | ...::... | kotlin.reflect.KCallable<Integer>.callBy(java.util.Map) |
|
||||
| reflection.kt:67:17:67:32 | ...::... | kotlin.reflect.KCallable<Integer>.getName() |
|
||||
| reflection.kt:67:17:67:32 | ...::... | kotlin.reflect.KCallable<Integer>.getParameters() |
|
||||
| reflection.kt:67:17:67:32 | ...::... | kotlin.reflect.KCallable<Integer>.getReturnType() |
|
||||
| reflection.kt:67:17:67:32 | ...::... | kotlin.reflect.KCallable<Integer>.getTypeParameters() |
|
||||
| reflection.kt:67:17:67:32 | ...::... | kotlin.reflect.KCallable<Integer>.getVisibility() |
|
||||
| reflection.kt:67:17:67:32 | ...::... | kotlin.reflect.KCallable<Integer>.isAbstract() |
|
||||
| reflection.kt:67:17:67:32 | ...::... | kotlin.reflect.KCallable<Integer>.isFinal() |
|
||||
| reflection.kt:67:17:67:32 | ...::... | kotlin.reflect.KCallable<Integer>.isOpen() |
|
||||
| reflection.kt:67:17:67:32 | ...::... | kotlin.reflect.KCallable<Integer>.isSuspend() |
|
||||
| reflection.kt:67:17:67:32 | ...::... | kotlin.reflect.KMutableProperty1<Generic<Integer>,Integer>.getSetter() |
|
||||
| reflection.kt:67:17:67:32 | ...::... | kotlin.reflect.KMutableProperty<Integer>.getSetter() |
|
||||
| reflection.kt:67:17:67:32 | ...::... | kotlin.reflect.KProperty1<Generic<Integer>,Integer>.getDelegate(Class1.Generic) |
|
||||
| reflection.kt:67:17:67:32 | ...::... | kotlin.reflect.KProperty1<Generic<Integer>,Integer>.getGetter() |
|
||||
| reflection.kt:67:17:67:32 | ...::... | kotlin.reflect.KProperty<Integer>.getGetter() |
|
||||
| reflection.kt:67:17:67:32 | ...::... | kotlin.reflect.KProperty<Integer>.isConst() |
|
||||
| reflection.kt:67:17:67:32 | ...::... | kotlin.reflect.KProperty<Integer>.isLateinit() |
|
||||
| reflection.kt:67:17:67:32 | ...::... | kotlin.reflect.KProperty<Object>.getGetter() |
|
||||
| reflection.kt:68:17:68:34 | ...::... | kotlin.reflect.KCallable<Integer>.call(java.lang.Object[]) |
|
||||
| reflection.kt:68:17:68:34 | ...::... | kotlin.reflect.KCallable<Integer>.callBy(java.util.Map) |
|
||||
| reflection.kt:68:17:68:34 | ...::... | kotlin.reflect.KCallable<Integer>.getName() |
|
||||
| reflection.kt:68:17:68:34 | ...::... | kotlin.reflect.KCallable<Integer>.getParameters() |
|
||||
| reflection.kt:68:17:68:34 | ...::... | kotlin.reflect.KCallable<Integer>.getReturnType() |
|
||||
| reflection.kt:68:17:68:34 | ...::... | kotlin.reflect.KCallable<Integer>.getTypeParameters() |
|
||||
| reflection.kt:68:17:68:34 | ...::... | kotlin.reflect.KCallable<Integer>.getVisibility() |
|
||||
| reflection.kt:68:17:68:34 | ...::... | kotlin.reflect.KCallable<Integer>.isAbstract() |
|
||||
| reflection.kt:68:17:68:34 | ...::... | kotlin.reflect.KCallable<Integer>.isFinal() |
|
||||
| reflection.kt:68:17:68:34 | ...::... | kotlin.reflect.KCallable<Integer>.isOpen() |
|
||||
| reflection.kt:68:17:68:34 | ...::... | kotlin.reflect.KCallable<Integer>.isSuspend() |
|
||||
| reflection.kt:68:17:68:34 | ...::... | kotlin.reflect.KMutableProperty0<Integer>.getSetter() |
|
||||
| reflection.kt:68:17:68:34 | ...::... | kotlin.reflect.KMutableProperty<Integer>.getSetter() |
|
||||
| reflection.kt:68:17:68:34 | ...::... | kotlin.reflect.KProperty0<Integer>.getDelegate() |
|
||||
| reflection.kt:68:17:68:34 | ...::... | kotlin.reflect.KProperty0<Integer>.getGetter() |
|
||||
| reflection.kt:68:17:68:34 | ...::... | kotlin.reflect.KProperty<Integer>.getGetter() |
|
||||
| reflection.kt:68:17:68:34 | ...::... | kotlin.reflect.KProperty<Integer>.isConst() |
|
||||
| reflection.kt:68:17:68:34 | ...::... | kotlin.reflect.KProperty<Integer>.isLateinit() |
|
||||
| reflection.kt:68:17:68:34 | ...::... | kotlin.reflect.KProperty<Object>.getGetter() |
|
||||
| reflection.kt:70:17:70:30 | ...::... | kotlin.reflect.KCallable<Integer>.call(java.lang.Object[]) |
|
||||
| reflection.kt:70:17:70:30 | ...::... | kotlin.reflect.KCallable<Integer>.callBy(java.util.Map) |
|
||||
| reflection.kt:70:17:70:30 | ...::... | kotlin.reflect.KCallable<Integer>.getName() |
|
||||
| reflection.kt:70:17:70:30 | ...::... | kotlin.reflect.KCallable<Integer>.getParameters() |
|
||||
| reflection.kt:70:17:70:30 | ...::... | kotlin.reflect.KCallable<Integer>.getReturnType() |
|
||||
| reflection.kt:70:17:70:30 | ...::... | kotlin.reflect.KCallable<Integer>.getTypeParameters() |
|
||||
| reflection.kt:70:17:70:30 | ...::... | kotlin.reflect.KCallable<Integer>.getVisibility() |
|
||||
| reflection.kt:70:17:70:30 | ...::... | kotlin.reflect.KCallable<Integer>.isAbstract() |
|
||||
| reflection.kt:70:17:70:30 | ...::... | kotlin.reflect.KCallable<Integer>.isFinal() |
|
||||
| reflection.kt:70:17:70:30 | ...::... | kotlin.reflect.KCallable<Integer>.isOpen() |
|
||||
| reflection.kt:70:17:70:30 | ...::... | kotlin.reflect.KCallable<Integer>.isSuspend() |
|
||||
| reflection.kt:70:17:70:30 | ...::... | kotlin.reflect.KProperty0<Integer>.getDelegate() |
|
||||
| reflection.kt:70:17:70:30 | ...::... | kotlin.reflect.KProperty0<Integer>.getGetter() |
|
||||
| reflection.kt:70:17:70:30 | ...::... | kotlin.reflect.KProperty<Integer>.getGetter() |
|
||||
| reflection.kt:70:17:70:30 | ...::... | kotlin.reflect.KProperty<Integer>.isConst() |
|
||||
| reflection.kt:70:17:70:30 | ...::... | kotlin.reflect.KProperty<Integer>.isLateinit() |
|
||||
| reflection.kt:70:17:70:30 | ...::... | kotlin.reflect.KProperty<Object>.getGetter() |
|
||||
| reflection.kt:71:17:71:34 | ...::... | kotlin.reflect.KCallable<Integer>.call(java.lang.Object[]) |
|
||||
| reflection.kt:71:17:71:34 | ...::... | kotlin.reflect.KCallable<Integer>.callBy(java.util.Map) |
|
||||
| reflection.kt:71:17:71:34 | ...::... | kotlin.reflect.KCallable<Integer>.getName() |
|
||||
| reflection.kt:71:17:71:34 | ...::... | kotlin.reflect.KCallable<Integer>.getParameters() |
|
||||
| reflection.kt:71:17:71:34 | ...::... | kotlin.reflect.KCallable<Integer>.getReturnType() |
|
||||
| reflection.kt:71:17:71:34 | ...::... | kotlin.reflect.KCallable<Integer>.getTypeParameters() |
|
||||
| reflection.kt:71:17:71:34 | ...::... | kotlin.reflect.KCallable<Integer>.getVisibility() |
|
||||
| reflection.kt:71:17:71:34 | ...::... | kotlin.reflect.KCallable<Integer>.isAbstract() |
|
||||
| reflection.kt:71:17:71:34 | ...::... | kotlin.reflect.KCallable<Integer>.isFinal() |
|
||||
| reflection.kt:71:17:71:34 | ...::... | kotlin.reflect.KCallable<Integer>.isOpen() |
|
||||
| reflection.kt:71:17:71:34 | ...::... | kotlin.reflect.KCallable<Integer>.isSuspend() |
|
||||
| reflection.kt:71:17:71:34 | ...::... | kotlin.reflect.KProperty0<Integer>.getDelegate() |
|
||||
| reflection.kt:71:17:71:34 | ...::... | kotlin.reflect.KProperty0<Integer>.getGetter() |
|
||||
| reflection.kt:71:17:71:34 | ...::... | kotlin.reflect.KProperty<Integer>.getGetter() |
|
||||
| reflection.kt:71:17:71:34 | ...::... | kotlin.reflect.KProperty<Integer>.isConst() |
|
||||
| reflection.kt:71:17:71:34 | ...::... | kotlin.reflect.KProperty<Integer>.isLateinit() |
|
||||
| reflection.kt:71:17:71:34 | ...::... | kotlin.reflect.KProperty<Object>.getGetter() |
|
||||
| reflection.kt:72:17:72:35 | ...::... | kotlin.reflect.KCallable<Integer>.call(java.lang.Object[]) |
|
||||
| reflection.kt:72:17:72:35 | ...::... | kotlin.reflect.KCallable<Integer>.callBy(java.util.Map) |
|
||||
| reflection.kt:72:17:72:35 | ...::... | kotlin.reflect.KCallable<Integer>.getName() |
|
||||
| reflection.kt:72:17:72:35 | ...::... | kotlin.reflect.KCallable<Integer>.getParameters() |
|
||||
| reflection.kt:72:17:72:35 | ...::... | kotlin.reflect.KCallable<Integer>.getReturnType() |
|
||||
| reflection.kt:72:17:72:35 | ...::... | kotlin.reflect.KCallable<Integer>.getTypeParameters() |
|
||||
| reflection.kt:72:17:72:35 | ...::... | kotlin.reflect.KCallable<Integer>.getVisibility() |
|
||||
| reflection.kt:72:17:72:35 | ...::... | kotlin.reflect.KCallable<Integer>.isAbstract() |
|
||||
| reflection.kt:72:17:72:35 | ...::... | kotlin.reflect.KCallable<Integer>.isFinal() |
|
||||
| reflection.kt:72:17:72:35 | ...::... | kotlin.reflect.KCallable<Integer>.isOpen() |
|
||||
| reflection.kt:72:17:72:35 | ...::... | kotlin.reflect.KCallable<Integer>.isSuspend() |
|
||||
| reflection.kt:72:17:72:35 | ...::... | kotlin.reflect.KMutableProperty0<Integer>.getSetter() |
|
||||
| reflection.kt:72:17:72:35 | ...::... | kotlin.reflect.KMutableProperty0<Integer>.set(java.lang.Integer) |
|
||||
| reflection.kt:72:17:72:35 | ...::... | kotlin.reflect.KMutableProperty<Integer>.getSetter() |
|
||||
| reflection.kt:72:17:72:35 | ...::... | kotlin.reflect.KProperty0<Integer>.getDelegate() |
|
||||
| reflection.kt:72:17:72:35 | ...::... | kotlin.reflect.KProperty0<Integer>.getGetter() |
|
||||
| reflection.kt:72:17:72:35 | ...::... | kotlin.reflect.KProperty<Integer>.getGetter() |
|
||||
| reflection.kt:72:17:72:35 | ...::... | kotlin.reflect.KProperty<Integer>.isConst() |
|
||||
| reflection.kt:72:17:72:35 | ...::... | kotlin.reflect.KProperty<Integer>.isLateinit() |
|
||||
| reflection.kt:72:17:72:35 | ...::... | kotlin.reflect.KProperty<Object>.getGetter() |
|
||||
| reflection.kt:109:17:109:27 | ...::... | kotlin.reflect.KCallable<Integer>.call(java.lang.Object[]) |
|
||||
| reflection.kt:109:17:109:27 | ...::... | kotlin.reflect.KCallable<Integer>.callBy(java.util.Map) |
|
||||
| reflection.kt:109:17:109:27 | ...::... | kotlin.reflect.KCallable<Integer>.getName() |
|
||||
| reflection.kt:109:17:109:27 | ...::... | kotlin.reflect.KCallable<Integer>.getParameters() |
|
||||
| reflection.kt:109:17:109:27 | ...::... | kotlin.reflect.KCallable<Integer>.getReturnType() |
|
||||
| reflection.kt:109:17:109:27 | ...::... | kotlin.reflect.KCallable<Integer>.getTypeParameters() |
|
||||
| reflection.kt:109:17:109:27 | ...::... | kotlin.reflect.KCallable<Integer>.getVisibility() |
|
||||
| reflection.kt:109:17:109:27 | ...::... | kotlin.reflect.KCallable<Integer>.isAbstract() |
|
||||
| reflection.kt:109:17:109:27 | ...::... | kotlin.reflect.KCallable<Integer>.isFinal() |
|
||||
| reflection.kt:109:17:109:27 | ...::... | kotlin.reflect.KCallable<Integer>.isOpen() |
|
||||
| reflection.kt:109:17:109:27 | ...::... | kotlin.reflect.KCallable<Integer>.isSuspend() |
|
||||
| reflection.kt:109:17:109:27 | ...::... | kotlin.reflect.KMutableProperty0<Integer>.getSetter() |
|
||||
| reflection.kt:109:17:109:27 | ...::... | kotlin.reflect.KMutableProperty0<Integer>.set(java.lang.Integer) |
|
||||
| reflection.kt:109:17:109:27 | ...::... | kotlin.reflect.KMutableProperty<Integer>.getSetter() |
|
||||
| reflection.kt:109:17:109:27 | ...::... | kotlin.reflect.KProperty0<Integer>.getDelegate() |
|
||||
| reflection.kt:109:17:109:27 | ...::... | kotlin.reflect.KProperty0<Integer>.getGetter() |
|
||||
| reflection.kt:109:17:109:27 | ...::... | kotlin.reflect.KProperty<Integer>.getGetter() |
|
||||
| reflection.kt:109:17:109:27 | ...::... | kotlin.reflect.KProperty<Integer>.isConst() |
|
||||
| reflection.kt:109:17:109:27 | ...::... | kotlin.reflect.KProperty<Integer>.isLateinit() |
|
||||
| reflection.kt:109:17:109:27 | ...::... | kotlin.reflect.KProperty<Object>.getGetter() |
|
||||
|
||||
@@ -87,3 +87,24 @@ query predicate modifiers(ClassInstanceExpr e, Method m, string modifier) {
|
||||
}
|
||||
|
||||
query predicate compGenerated(Element e, int i) { compiler_generated(e, i) }
|
||||
|
||||
query predicate propertyReferenceOverrides(PropertyRefExpr e, Method m, string overridden) {
|
||||
e.getAnonymousClass().getAMember() = m and
|
||||
exists(Method n |
|
||||
m.overrides(n) and
|
||||
overridden = n.getDeclaringType().getQualifiedName() + "." + n.getSignature()
|
||||
)
|
||||
}
|
||||
|
||||
query predicate notImplementedInterfaceMembers(PropertyRefExpr e, string interfaceMember) {
|
||||
exists(Interface i, Method interfaceMethod |
|
||||
e.getAnonymousClass().extendsOrImplements+(i) and
|
||||
i.getAMethod() = interfaceMethod and
|
||||
interfaceMember = i.getQualifiedName() + "." + interfaceMethod.getSignature() and
|
||||
not exists(Class c, Method classMethod |
|
||||
e.getAnonymousClass().extendsOrImplements*(c) and
|
||||
c.getAMethod() = classMethod and
|
||||
classMethod.overrides(interfaceMethod)
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
Violations of Best Practice/Naming Conventions/ConfusingOverloading.ql
|
||||
@@ -0,0 +1,9 @@
|
||||
class C {
|
||||
var p: Int
|
||||
get() = 1
|
||||
set(value) {}
|
||||
fun fn() {
|
||||
val prop = C::p
|
||||
prop(this)
|
||||
}
|
||||
}
|
||||
25
java/ql/test/library-tests/dataflow/synth-global/A.java
Normal file
25
java/ql/test/library-tests/dataflow/synth-global/A.java
Normal file
@@ -0,0 +1,25 @@
|
||||
package my.qltest.synth;
|
||||
|
||||
public class A {
|
||||
void storeInArray(String x) { }
|
||||
void storeTaintInArray(String x) { }
|
||||
void storeValue(String x) { }
|
||||
|
||||
String readValue() { return null; }
|
||||
String readArray() { return null; }
|
||||
|
||||
String source(String tag) { return "tainted"; }
|
||||
|
||||
void sink(Object o) { }
|
||||
|
||||
void stores() {
|
||||
storeInArray(source("A"));
|
||||
storeTaintInArray(source("B"));
|
||||
storeValue(source("C"));
|
||||
}
|
||||
|
||||
void reads() {
|
||||
sink(readValue()); // $ hasValueFlow=C
|
||||
sink(readArray()); // $ hasValueFlow=A hasTaintFlow=B hasTaintFlow=C
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
failures
|
||||
invalidModelRow
|
||||
16
java/ql/test/library-tests/dataflow/synth-global/test.ql
Normal file
16
java/ql/test/library-tests/dataflow/synth-global/test.ql
Normal file
@@ -0,0 +1,16 @@
|
||||
import java
|
||||
import TestUtilities.InlineFlowTest
|
||||
import CsvValidation
|
||||
|
||||
class SummaryModelTest extends SummaryModelCsv {
|
||||
override predicate row(string row) {
|
||||
row =
|
||||
[
|
||||
"my.qltest.synth;A;false;storeInArray;(String);;Argument[0];SyntheticGlobal[db1].ArrayElement;value;manual",
|
||||
"my.qltest.synth;A;false;storeTaintInArray;(String);;Argument[0];SyntheticGlobal[db1].ArrayElement;taint;manual",
|
||||
"my.qltest.synth;A;false;storeValue;(String);;Argument[0];SyntheticGlobal[db1];value;manual",
|
||||
"my.qltest.synth;A;false;readValue;();;SyntheticGlobal[db1];ReturnValue;value;manual",
|
||||
"my.qltest.synth;A;false;readArray;();;SyntheticGlobal[db1].ArrayElement;ReturnValue;value;manual",
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -106,7 +106,7 @@ predicate useAfterCheck(FileCheck check, FileUse use) {
|
||||
)
|
||||
)
|
||||
or
|
||||
check.getBasicBlock().getASuccessor+() = use.getBasicBlock()
|
||||
check.getBasicBlock().(ReachableBasicBlock).strictlyDominates(use.getBasicBlock())
|
||||
}
|
||||
|
||||
from FileCheck check, FileUse use
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* Removed some false positives from the `js/file-system-race` query by requiring that the file-check dominates the file-access.
|
||||
@@ -41,3 +41,8 @@ const filePath3 = createFile();
|
||||
if (fs.existsSync(filePath3)) {
|
||||
fs.readFileSync(filePath3); // OK - a read after an existence check is OK
|
||||
}
|
||||
|
||||
const filePath4 = createFile();
|
||||
while(Math.random() > 0.5) {
|
||||
fs.open(filePath4); // OK - it is only ever opened here.
|
||||
}
|
||||
@@ -82,7 +82,7 @@ predefined_entity_xml = """<?xml version="1.0"?>
|
||||
# other setup
|
||||
|
||||
# we set up local Flask application so we can tests whether loading external resources
|
||||
# works (such as SSRF from DTD-retrival works)
|
||||
# works (such as SSRF from DTD-retrieval works)
|
||||
app = Flask(__name__)
|
||||
|
||||
@app.route("/alive")
|
||||
@@ -187,7 +187,7 @@ class TestSax():
|
||||
|
||||
@staticmethod
|
||||
@expects_timeout
|
||||
def test_quardratic_blowup_allowed_by_default():
|
||||
def test_quadratic_blowup_allowed_by_default():
|
||||
parser = xml.sax.make_parser()
|
||||
parser.parse(StringIO(quadratic_blowup))
|
||||
|
||||
@@ -263,7 +263,7 @@ class TestEtree:
|
||||
|
||||
@staticmethod
|
||||
@expects_timeout
|
||||
def test_quardratic_blowup_allowed_by_default():
|
||||
def test_quadratic_blowup_allowed_by_default():
|
||||
parser = xml.etree.ElementTree.XMLParser()
|
||||
_root = xml.etree.ElementTree.fromstring(quadratic_blowup, parser=parser)
|
||||
|
||||
@@ -324,7 +324,7 @@ class TestLxml:
|
||||
assert "Detected an entity reference loop" in str(e)
|
||||
|
||||
@staticmethod
|
||||
def test_quardratic_blowup_disabled_by_default():
|
||||
def test_quadratic_blowup_disabled_by_default():
|
||||
parser = lxml.etree.XMLParser()
|
||||
try:
|
||||
_root = lxml.etree.fromstring(quadratic_blowup, parser=parser)
|
||||
@@ -465,7 +465,7 @@ class TestXmltodict:
|
||||
assert d == {"lolz": None}, d
|
||||
|
||||
@staticmethod
|
||||
def test_quardratic_blowup_disabled_by_default():
|
||||
def test_quadratic_blowup_disabled_by_default():
|
||||
d = xmltodict.parse(quadratic_blowup)
|
||||
assert d == {"foo": None}, d
|
||||
|
||||
@@ -476,7 +476,7 @@ class TestXmltodict:
|
||||
|
||||
@staticmethod
|
||||
@expects_timeout
|
||||
def test_quardratic_blowup_manually_enabled():
|
||||
def test_quadratic_blowup_manually_enabled():
|
||||
xmltodict.parse(quadratic_blowup, disable_entities=False)
|
||||
|
||||
@staticmethod
|
||||
@@ -524,7 +524,7 @@ class TestMinidom:
|
||||
|
||||
@staticmethod
|
||||
@expects_timeout
|
||||
def test_quardratic_blowup():
|
||||
def test_quadratic_blowup():
|
||||
xml.dom.minidom.parseString(quadratic_blowup)
|
||||
|
||||
@staticmethod
|
||||
@@ -585,7 +585,7 @@ class TestPulldom:
|
||||
|
||||
@staticmethod
|
||||
@expects_timeout
|
||||
def test_quardratic_blowup():
|
||||
def test_quadratic_blowup():
|
||||
doc = xml.dom.pulldom.parseString(quadratic_blowup)
|
||||
for event, node in doc:
|
||||
pass
|
||||
@@ -670,7 +670,7 @@ class TestExpat:
|
||||
|
||||
@staticmethod
|
||||
@expects_timeout
|
||||
def test_quardratic_blowup():
|
||||
def test_quadratic_blowup():
|
||||
parser = xml.parsers.expat.ParserCreate()
|
||||
parser.Parse(quadratic_blowup, True)
|
||||
|
||||
@@ -699,7 +699,7 @@ class TestExpat:
|
||||
|
||||
assert char_data_recv == []
|
||||
|
||||
# there might be ways to make it vuln, but I did not investigate futher.
|
||||
# there might be ways to make it vuln, but I did not investigate further.
|
||||
|
||||
@staticmethod
|
||||
def test_dtd():
|
||||
@@ -711,4 +711,4 @@ class TestExpat:
|
||||
parser.Parse(dtd_retrieval, True)
|
||||
assert hit_dtd == False
|
||||
|
||||
# there might be ways to make it vuln, but I did not investigate futher.
|
||||
# there might be ways to make it vuln, but I did not investigate further.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
/**
|
||||
* @id py/examples/override-method
|
||||
* @name Override of method
|
||||
* @description Finds methods that overide MyClass.methodName
|
||||
* @description Finds methods that override MyClass.methodName
|
||||
* @tags method
|
||||
* override
|
||||
*/
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* Added the ability to refer to subscript operations in the API graph. It is now possible to write `response().getMember("cookies").getASubscript()` to find code like `resp.cookies["key"]` (assuming `response` returns an API node for reponse objects).
|
||||
* Added the ability to refer to subscript operations in the API graph. It is now possible to write `response().getMember("cookies").getASubscript()` to find code like `resp.cookies["key"]` (assuming `response` returns an API node for response objects).
|
||||
* Added modeling of creating Flask responses with `flask.jsonify`.
|
||||
|
||||
## 0.6.0
|
||||
|
||||
@@ -2,5 +2,5 @@
|
||||
|
||||
### Minor Analysis Improvements
|
||||
|
||||
* Added the ability to refer to subscript operations in the API graph. It is now possible to write `response().getMember("cookies").getASubscript()` to find code like `resp.cookies["key"]` (assuming `response` returns an API node for reponse objects).
|
||||
* Added the ability to refer to subscript operations in the API graph. It is now possible to write `response().getMember("cookies").getASubscript()` to find code like `resp.cookies["key"]` (assuming `response` returns an API node for response objects).
|
||||
* Added modeling of creating Flask responses with `flask.jsonify`.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# The Python libraries
|
||||
|
||||
The Python libraries are a collection of libraries for analysing Python code.
|
||||
Everythng can be imported by importing `python.qll`.
|
||||
Everything can be imported by importing `python.qll`.
|
||||
|
||||
## The analysis layers
|
||||
|
||||
@@ -15,10 +15,10 @@ The analysis is built up in layers. the stack looks like this:
|
||||
|
||||
## Avoiding non-monotonic recursion
|
||||
|
||||
Given the many interactivg layers, it is imprtant to decie which predicates are allowed to be mutually recursive in order to avoid non-monotonic recursion when negation is used to express the predicates.
|
||||
As an example, we have defined local source as those whcih do not receive local flow. This means that the local flow relation is not allowed to be recursive with anything depending on local sources.
|
||||
Given the many interacting layers, it is important to decide which predicates are allowed to be mutually recursive in order to avoid non-monotonic recursion when negation is used to express the predicates.
|
||||
As an example, we have defined local source as those which do not receive local flow. This means that the local flow relation is not allowed to be recursive with anything depending on local sources.
|
||||
|
||||
Some particular reatrictions to keep in mind:
|
||||
Some particular restrictions to keep in mind:
|
||||
|
||||
- Typetracking needs to use a local flow step not including summaries
|
||||
- Typetracking needs to use a call graph not including summaries
|
||||
|
||||
@@ -211,7 +211,7 @@ module API {
|
||||
* Gets a node representing the `i`th parameter of the function represented by this node.
|
||||
*
|
||||
* This predicate may have multiple results when there are multiple invocations of this API component.
|
||||
* Consider using `getAnInvocation()` if there is a need to distingiush between individual calls.
|
||||
* Consider using `getAnInvocation()` if there is a need to distinguish between individual calls.
|
||||
*/
|
||||
Node getParameter(int i) { result = this.getASuccessor(Label::parameter(i)) }
|
||||
|
||||
@@ -219,7 +219,7 @@ module API {
|
||||
* Gets the node representing the keyword parameter `name` of the function represented by this node.
|
||||
*
|
||||
* This predicate may have multiple results when there are multiple invocations of this API component.
|
||||
* Consider using `getAnInvocation()` if there is a need to distingiush between individual calls.
|
||||
* Consider using `getAnInvocation()` if there is a need to distinguish between individual calls.
|
||||
*/
|
||||
Node getKeywordParameter(string name) {
|
||||
result = this.getASuccessor(Label::keywordParameter(name))
|
||||
|
||||
@@ -7,7 +7,7 @@ int major_version() {
|
||||
explicit_major_version(result)
|
||||
or
|
||||
not explicit_major_version(_) and
|
||||
/* If there is more than one version, prefer 2 for backwards compatibilty */
|
||||
/* If there is more than one version, prefer 2 for backwards compatibility */
|
||||
(if py_flags_versioned("version.major", "2", "2") then result = 2 else result = 3)
|
||||
}
|
||||
|
||||
|
||||
@@ -931,7 +931,7 @@ class NameConstantNode extends NameNode {
|
||||
|
||||
}
|
||||
|
||||
/** A control flow node correspoinding to a starred expression, `*a`. */
|
||||
/** A control flow node corresponding to a starred expression, `*a`. */
|
||||
class StarredNode extends ControlFlowNode {
|
||||
StarredNode() { toAst(this) instanceof Starred }
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Provides an extension point for for modeling user-controlled data.
|
||||
* Provides an extension point for modeling user-controlled data.
|
||||
* Such data is often used as data-flow sources in security queries.
|
||||
*/
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Provides an extension point for for modeling sensitive data, such as secrets, certificates, or passwords.
|
||||
* Provides an extension point for modeling sensitive data, such as secrets, certificates, or passwords.
|
||||
* Sensitive data can be interesting to use as data-flow sources in security queries.
|
||||
*/
|
||||
|
||||
|
||||
@@ -205,12 +205,12 @@ module ArgumentPassing {
|
||||
result = TCfgNode(call.getArgByName(unbind_string(argName)))
|
||||
)
|
||||
or
|
||||
// a synthezised argument passed to the starred parameter (at position -1)
|
||||
// a synthesized argument passed to the starred parameter (at position -1)
|
||||
callable.getScope().hasVarArg() and
|
||||
paramN = -1 and
|
||||
result = TPosOverflowNode(call, callable)
|
||||
or
|
||||
// a synthezised argument passed to the doubly starred parameter (at position -2)
|
||||
// a synthesized argument passed to the doubly starred parameter (at position -2)
|
||||
callable.getScope().hasKwArg() and
|
||||
paramN = -2 and
|
||||
result = TKwOverflowNode(call, callable)
|
||||
@@ -769,7 +769,7 @@ DataFlowCallable viableCallable(ExtractedDataFlowCall call) {
|
||||
// A call to a library callable with a flow summary
|
||||
// In this situation we can not resolve the callable from the call,
|
||||
// as that would make data flow depend on type tracking.
|
||||
// Instead we reolve the call from the summary.
|
||||
// Instead we resolve the call from the summary.
|
||||
exists(LibraryCallable callable |
|
||||
result = TLibraryCallable(callable) and
|
||||
call.getNode() = callable.getACall().getNode()
|
||||
|
||||
@@ -453,13 +453,15 @@ predicate jumpStep(Node nodeFrom, Node nodeTo) {
|
||||
jumpStepSharedWithTypeTracker(nodeFrom, nodeTo)
|
||||
or
|
||||
jumpStepNotSharedWithTypeTracker(nodeFrom, nodeTo)
|
||||
or
|
||||
FlowSummaryImpl::Private::Steps::summaryJumpStep(nodeFrom, nodeTo)
|
||||
}
|
||||
|
||||
/**
|
||||
* Set of jumpSteps that are shared with type-tracker implementation.
|
||||
*
|
||||
* For ORM modeling we want to add jumpsteps to global dataflow, but since these are
|
||||
* based on type-trackers, it's important that these new ORM jumsteps are not used in
|
||||
* based on type-trackers, it's important that these new ORM jumpsteps are not used in
|
||||
* the type-trackers as well, as that would make evaluation of type-tracking recursive
|
||||
* with the new jumpsteps.
|
||||
*
|
||||
@@ -485,7 +487,7 @@ predicate jumpStepSharedWithTypeTracker(Node nodeFrom, Node nodeTo) {
|
||||
* Set of jumpSteps that are NOT shared with type-tracker implementation.
|
||||
*
|
||||
* For ORM modeling we want to add jumpsteps to global dataflow, but since these are
|
||||
* based on type-trackers, it's important that these new ORM jumsteps are not used in
|
||||
* based on type-trackers, it's important that these new ORM jumpsteps are not used in
|
||||
* the type-trackers as well, as that would make evaluation of type-tracking recursive
|
||||
* with the new jumpsteps.
|
||||
*
|
||||
@@ -668,7 +670,7 @@ predicate attributeStoreStep(Node nodeFrom, AttributeContent c, PostUpdateNode n
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `nodeFrom` flows into the synthezised positional overflow argument (`nodeTo`)
|
||||
* Holds if `nodeFrom` flows into the synthesized positional overflow argument (`nodeTo`)
|
||||
* at the position indicated by `c`.
|
||||
*/
|
||||
predicate posOverflowStoreStep(CfgNode nodeFrom, TupleElementContent c, Node nodeTo) {
|
||||
@@ -680,7 +682,7 @@ predicate posOverflowStoreStep(CfgNode nodeFrom, TupleElementContent c, Node nod
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `nodeFrom` flows into the synthezised keyword overflow argument (`nodeTo`)
|
||||
* Holds if `nodeFrom` flows into the synthesized keyword overflow argument (`nodeTo`)
|
||||
* at the key indicated by `c`.
|
||||
*/
|
||||
predicate kwOverflowStoreStep(CfgNode nodeFrom, DictionaryElementContent c, Node nodeTo) {
|
||||
@@ -814,7 +816,7 @@ predicate attributeReadStep(Node nodeFrom, AttributeContent c, AttrRead nodeTo)
|
||||
|
||||
/**
|
||||
* Holds if `nodeFrom` is a dictionary argument being unpacked and `nodeTo` is the
|
||||
* synthezised unpacked argument with the name indicated by `c`.
|
||||
* synthesized unpacked argument with the name indicated by `c`.
|
||||
*/
|
||||
predicate kwUnpackReadStep(CfgNode nodeFrom, DictionaryElementContent c, Node nodeTo) {
|
||||
exists(CallNode call, CallableValue callable, string name |
|
||||
|
||||
@@ -61,6 +61,20 @@ module Public {
|
||||
|
||||
/** Gets a summary component for a return of kind `rk`. */
|
||||
SummaryComponent return(ReturnKind rk) { result = TReturnSummaryComponent(rk) }
|
||||
|
||||
/** Gets a summary component for synthetic global `sg`. */
|
||||
SummaryComponent syntheticGlobal(SyntheticGlobal sg) {
|
||||
result = TSyntheticGlobalSummaryComponent(sg)
|
||||
}
|
||||
|
||||
/**
|
||||
* A synthetic global. This represents some form of global state, which
|
||||
* summaries can read and write individually.
|
||||
*/
|
||||
abstract class SyntheticGlobal extends string {
|
||||
bindingset[this]
|
||||
SyntheticGlobal() { any() }
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -256,6 +270,7 @@ module Private {
|
||||
TParameterSummaryComponent(ArgumentPosition pos) or
|
||||
TArgumentSummaryComponent(ParameterPosition pos) or
|
||||
TReturnSummaryComponent(ReturnKind rk) or
|
||||
TSyntheticGlobalSummaryComponent(SummaryComponent::SyntheticGlobal sg) or
|
||||
TWithoutContentSummaryComponent(ContentSet c) or
|
||||
TWithContentSummaryComponent(ContentSet c)
|
||||
|
||||
@@ -563,6 +578,11 @@ module Private {
|
||||
getCallbackReturnType(getNodeType(summaryNodeInputState(pragma[only_bind_out](c),
|
||||
s.tail())), rk)
|
||||
)
|
||||
or
|
||||
exists(SummaryComponent::SyntheticGlobal sg |
|
||||
head = TSyntheticGlobalSummaryComponent(sg) and
|
||||
result = getSyntheticGlobalType(sg)
|
||||
)
|
||||
)
|
||||
or
|
||||
n = summaryNodeOutputState(c, s) and
|
||||
@@ -582,6 +602,11 @@ module Private {
|
||||
getCallbackParameterType(getNodeType(summaryNodeInputState(pragma[only_bind_out](c),
|
||||
s.tail())), pos)
|
||||
)
|
||||
or
|
||||
exists(SummaryComponent::SyntheticGlobal sg |
|
||||
head = TSyntheticGlobalSummaryComponent(sg) and
|
||||
result = getSyntheticGlobalType(sg)
|
||||
)
|
||||
)
|
||||
)
|
||||
}
|
||||
@@ -692,6 +717,18 @@ module Private {
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if there is a jump step from `pred` to `succ`, which is synthesized
|
||||
* from a flow summary.
|
||||
*/
|
||||
predicate summaryJumpStep(Node pred, Node succ) {
|
||||
exists(SummaryComponentStack s |
|
||||
s = SummaryComponentStack::singleton(SummaryComponent::syntheticGlobal(_)) and
|
||||
pred = summaryNodeOutputState(_, s) and
|
||||
succ = summaryNodeInputState(_, s)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if values stored inside content `c` are cleared at `n`. `n` is a
|
||||
* synthesized summary node, so in order for values to be cleared at calls
|
||||
@@ -871,18 +908,28 @@ module Private {
|
||||
AccessPathRange() { relevantSpec(this) }
|
||||
}
|
||||
|
||||
/** Holds if specification component `c` parses as parameter `n`. */
|
||||
/** Holds if specification component `token` parses as parameter `pos`. */
|
||||
predicate parseParam(AccessPathToken token, ArgumentPosition pos) {
|
||||
token.getName() = "Parameter" and
|
||||
pos = parseParamBody(token.getAnArgument())
|
||||
}
|
||||
|
||||
/** Holds if specification component `c` parses as argument `n`. */
|
||||
/** Holds if specification component `token` parses as argument `pos`. */
|
||||
predicate parseArg(AccessPathToken token, ParameterPosition pos) {
|
||||
token.getName() = "Argument" and
|
||||
pos = parseArgBody(token.getAnArgument())
|
||||
}
|
||||
|
||||
/** Holds if specification component `token` parses as synthetic global `sg`. */
|
||||
predicate parseSynthGlobal(AccessPathToken token, string sg) {
|
||||
token.getName() = "SyntheticGlobal" and
|
||||
sg = token.getAnArgument()
|
||||
}
|
||||
|
||||
private class SyntheticGlobalFromAccessPath extends SummaryComponent::SyntheticGlobal {
|
||||
SyntheticGlobalFromAccessPath() { parseSynthGlobal(_, this) }
|
||||
}
|
||||
|
||||
private SummaryComponent interpretComponent(AccessPathToken token) {
|
||||
exists(ParameterPosition pos |
|
||||
parseArg(token, pos) and result = SummaryComponent::argument(pos)
|
||||
@@ -894,6 +941,10 @@ module Private {
|
||||
or
|
||||
token = "ReturnValue" and result = SummaryComponent::return(getReturnValueKind())
|
||||
or
|
||||
exists(string sg |
|
||||
parseSynthGlobal(token, sg) and result = SummaryComponent::syntheticGlobal(sg)
|
||||
)
|
||||
or
|
||||
result = interpretComponentSpecific(token)
|
||||
}
|
||||
|
||||
|
||||
@@ -12,15 +12,15 @@
|
||||
*
|
||||
* Having both extracted and non-extracted callables means that we now have three types of calls:
|
||||
* - Extracted calls to extracted callables, either `NormalCall` or `SpecialCall`. These are handled by standard data flow.
|
||||
* - Extracted calls to non-extracted callables, `LibraryCall`. These are handled by loking up the relevant summary when the
|
||||
* global data flwo graph is connected up via `getViableCallable`.
|
||||
* - Extracted calls to non-extracted callables, `LibraryCall`. These are handled by looking up the relevant summary when the
|
||||
* global data flow graph is connected up via `getViableCallable`.
|
||||
* - Non-extracted calls, `SummaryCall`. These are synthesised by the flow summary framework.
|
||||
*
|
||||
* The first two can be referred to as `ExtractedDataFlowCall`. In fact, `LibraryCall` is a subclass of `NormalCall`, where
|
||||
* `getCallable` is set to `none()`. The member predicate `ExtractedDataFlowCall::getCallable` is _not_ the mechanism for
|
||||
* call resolution in global data flow. That mechanism is `getViableCallable`.
|
||||
* Resolving a call to a non-extracted callable goes via `LibraryCallable::getACall`, which may involve type tracking.
|
||||
* To avoid that type tracking becomes mutualy recursive with data flow, type tracking must use a call graph not including summaries.
|
||||
* To avoid that type tracking becomes mutually recursive with data flow, type tracking must use a call graph not including summaries.
|
||||
* Type tracking sees the callgraph given by `ExtractedDataFlowCall::getACallable`.
|
||||
*
|
||||
* We do not support summaries of special methods via the special methods framework,
|
||||
@@ -73,6 +73,9 @@ DataFlowType getCallbackParameterType(DataFlowType t, int i) { any() }
|
||||
*/
|
||||
DataFlowType getCallbackReturnType(DataFlowType t, ReturnKind rk) { any() }
|
||||
|
||||
/** Gets the type of synthetic global `sg`. */
|
||||
DataFlowType getSyntheticGlobalType(SummaryComponent::SyntheticGlobal sg) { any() }
|
||||
|
||||
/**
|
||||
* Holds if an external flow summary exists for `c` with input specification
|
||||
* `input`, output specification `output`, kind `kind`, and a flag `generated`
|
||||
|
||||
@@ -52,14 +52,14 @@
|
||||
* Note that an empty access path means that the value we are tracking flows directly to the element.
|
||||
*
|
||||
*
|
||||
* The `TIterableSequence(sequence)` is at this point superflous but becomes useful when handling recursive
|
||||
* The `TIterableSequence(sequence)` is at this point superfluous but becomes useful when handling recursive
|
||||
* structures in the LHS, where `sequence` is some internal sequence node. We can have a uniform treatment
|
||||
* by always having these two synthetic nodes. So we transfer to (or, in the recursive case, read into)
|
||||
* `TIterableSequence(sequence)`, from which we take a read step to `TIterableElement(sequence)` and then a
|
||||
* store step to `sequence`.
|
||||
*
|
||||
* This allows the unknown content from the RHS to be read into `TIterableElement(sequence)` and tuple content
|
||||
* to then be stored into `sequence`. If the content is already tuple content, this inderection creates crosstalk
|
||||
* to then be stored into `sequence`. If the content is already tuple content, this indirection creates crosstalk
|
||||
* between indices. Therefore, tuple content is never read into `TIterableElement(sequence)`; it is instead
|
||||
* transferred directly from `TIterableSequence(sequence)` to `sequence` via a flow step. Such a flow step will
|
||||
* also transfer other content, but only tuple content is further read from `sequence` into its elements.
|
||||
|
||||
@@ -185,7 +185,7 @@ private module Cached {
|
||||
/**
|
||||
* Holds if `source` is a `LocalSourceNode` that can reach `sink` via local flow steps.
|
||||
*
|
||||
* The slightly backwards parametering ordering is to force correct indexing.
|
||||
* The slightly backwards parameter ordering is to force correct indexing.
|
||||
*/
|
||||
cached
|
||||
predicate hasLocalSource(Node sink, LocalSourceNode source) {
|
||||
|
||||
@@ -250,7 +250,7 @@ class TaintTrackingImplementation extends string {
|
||||
}
|
||||
|
||||
/**
|
||||
* Hold if taint flows to `src` to `(node, context, path, kind)` in a single step, labelled with `egdeLabel` with this configuration.
|
||||
* Hold if taint flows to `src` to `(node, context, path, kind)` in a single step, labelled with `edgeLabel` with this configuration.
|
||||
* `edgeLabel` is purely informative.
|
||||
*/
|
||||
predicate flowStep(
|
||||
|
||||
@@ -31,7 +31,7 @@ module Aioch {
|
||||
}
|
||||
|
||||
/**
|
||||
* A call to any of the the execute methods on a `aioch.Client`, which are just async
|
||||
* A call to any of the execute methods on a `aioch.Client`, which are just async
|
||||
* versions of the methods in the `clickhouse-driver` PyPI package.
|
||||
*
|
||||
* See
|
||||
|
||||
@@ -45,7 +45,7 @@ module AiohttpWebModel {
|
||||
}
|
||||
|
||||
/** Gets a reference to an `aiohttp.web.UrlDispatcher` instance. */
|
||||
API::Node urlDispathcerInstance() {
|
||||
API::Node urlDispatcherInstance() {
|
||||
result = API::moduleImport("aiohttp").getMember("web").getMember("UrlDispatcher").getReturn()
|
||||
or
|
||||
result = applicationInstance().getMember("router")
|
||||
@@ -170,7 +170,7 @@ module AiohttpWebModel {
|
||||
funcName = "route" and
|
||||
routeArgsStart = 1
|
||||
|
|
||||
this = urlDispathcerInstance().getMember("add_" + funcName).getACall()
|
||||
this = urlDispatcherInstance().getMember("add_" + funcName).getACall()
|
||||
or
|
||||
this = API::moduleImport("aiohttp").getMember("web").getMember(funcName).getACall()
|
||||
)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user