mirror of
https://github.com/github/codeql.git
synced 2026-04-24 16:25:15 +02:00
Merge remote-tracking branch 'origin/main' into dbartol/threat-models-2
This commit is contained in:
@@ -13,17 +13,17 @@ private import AutomodelEndpointTypes
|
||||
private import AutomodelJavaUtil
|
||||
|
||||
from
|
||||
Endpoint endpoint, SinkType sinkType, FrameworkModeMetadataExtractor meta, DollarAtString package,
|
||||
DollarAtString type, DollarAtString subtypes, DollarAtString name, DollarAtString signature,
|
||||
DollarAtString input, DollarAtString output, DollarAtString parameterName,
|
||||
DollarAtString extensibleType
|
||||
Endpoint endpoint, EndpointType endpointType, FrameworkModeMetadataExtractor meta,
|
||||
DollarAtString package, DollarAtString type, DollarAtString subtypes, DollarAtString name,
|
||||
DollarAtString signature, DollarAtString input, DollarAtString output,
|
||||
DollarAtString parameterName, DollarAtString extensibleType
|
||||
where
|
||||
endpoint.getExtensibleType() = extensibleType and
|
||||
meta.hasMetadata(endpoint, package, type, subtypes, name, signature, input, output, parameterName) and
|
||||
// Extract positive examples of sinks belonging to the existing ATM query configurations.
|
||||
CharacteristicsImpl::isKnownAs(endpoint, sinkType, _)
|
||||
CharacteristicsImpl::isKnownAs(endpoint, endpointType, _)
|
||||
select endpoint,
|
||||
sinkType + "\nrelated locations: $@, $@." + "\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@.", //
|
||||
endpointType + "\nrelated locations: $@, $@." + "\nmetadata: $@, $@, $@, $@, $@, $@, $@, $@, $@.", //
|
||||
CharacteristicsImpl::getRelatedLocationOrCandidate(endpoint, MethodDoc()), "MethodDoc", //
|
||||
CharacteristicsImpl::getRelatedLocationOrCandidate(endpoint, ClassDoc()), "ClassDoc", //
|
||||
package, "package", //
|
||||
|
||||
183
java/ql/automodel/src/README.md
Normal file
183
java/ql/automodel/src/README.md
Normal file
@@ -0,0 +1,183 @@
|
||||
# Automodel Java Extraction Queries
|
||||
|
||||
This pack contains the automodel extraction queries for Java. Automodel uses extraction queries to extract the information it needs in order to create a prompt for a large language model. There's extraction queries for positive examples (things that are known to be, e.g., a sink), for negative examples (things that are known not to be, e.g., a sink), and for candidates (things where we should ask the large language model to classify).
|
||||
|
||||
## Extraction Queries in `java/ql/automodel/src`
|
||||
|
||||
Included in this pack are queries for both application mode and framework mode.
|
||||
|
||||
| Kind | Mode | Query File |
|
||||
|------|------|------------|
|
||||
| Candidates | Application Mode | [AutomodelApplicationModeExtractCandidates.ql](https://github.com/github/codeql/blob/main/java/ql/automodel/src/AutomodelApplicationModeExtractCandidates.ql) |
|
||||
| Positive Examples | Application Mode | [AutomodelApplicationModeExtractPositiveExamples.ql](https://github.com/github/codeql/blob/main/java/ql/automodel/src/AutomodelApplicationModeExtractPositiveExamples.ql) |
|
||||
| Negative Examples | Application Mode | [AutomodelApplicationModeExtractNegativeExamples.ql](https://github.com/github/codeql/blob/main/java/ql/automodel/src/AutomodelApplicationModeExtractNegativeExamples.ql) |
|
||||
| Candidates | Framework Mode | [AutomodelFrameworkModeExtractCandidates.ql](https://github.com/github/codeql/blob/main/java/ql/automodel/src/AutomodelFrameworkModeExtractCandidates.ql) |
|
||||
| Positive Examples | Framework Mode | [AutomodelFrameworkModeExtractPositiveExamples.ql](https://github.com/github/codeql/blob/main/java/ql/automodel/src/AutomodelFrameworkModeExtractPositiveExamples.ql) |
|
||||
| Negative Examples | Framework Mode | [AutomodelFrameworkModeExtractNegativeExamples.ql](https://github.com/github/codeql/blob/main/java/ql/automodel/src/AutomodelFrameworkModeExtractNegativeExamples.ql) |
|
||||
|
||||
## Running the Queries
|
||||
|
||||
The extraction queries are part of a separate query pack, `codeql/java-automodel-queries`. Use this pack to run them. The queries are tagged appropriately, you can use the tags (example here: https://github.com/github/codeql/blob/main/java/ql/automodel/src/AutomodelApplicationModeExtractNegativeExamples.ql#L8) to construct query suites.
|
||||
|
||||
For example, a query suite selecting all example extraction queries (positive and negative) for application mode looks like this:
|
||||
|
||||
```
|
||||
# File: automodel-application-mode-extraction-examples.qls
|
||||
# ---
|
||||
# Query suite for extracting examples for automodel
|
||||
|
||||
- description: Automodel application mode examples extraction.
|
||||
- queries: .
|
||||
from: codeql/java-automodel-queries
|
||||
- include:
|
||||
tags contain all:
|
||||
- automodel
|
||||
- extract
|
||||
- application-mode
|
||||
- examples
|
||||
```
|
||||
|
||||
## Important Software Design Concepts and Goals
|
||||
|
||||
### Concept: `Endpoint`
|
||||
|
||||
Endpoints are source code locations of interest. All positive examples, negative examples, and all candidates are endpoints, but not all endpoints are examples or candidates. Each mode decides which endpoints are relevant. For instance, if the Java application mode wants to support candidates for sinks that are arguments passed to unknown method calls, then the Java application mode implementation needs to make sure that method arguments are endpoints. If you look at the `TApplicationModeEndpoint` implementation in [AutomodelApplicationModeCharacteristics.qll](https://github.com/github/codeql/blob/main/java/ql/automodel/src/AutomodelApplicationModeCharacteristics.qll), you can see that this is the case: the `TExplicitArgument` implements this behavior.
|
||||
|
||||
Whether or not an endpoint is a positive/negative example, or a candidate depends on the individual extraction queries.
|
||||
|
||||
### Concept: `EndpointCharacteristics`
|
||||
|
||||
In the file [AutomodelSharedCharacteristics.ql](https://github.com/github/codeql/blob/main/java/ql/automodel/src/AutomodelSharedCharacteristics.ql), you will find the definition of the QL class `EndpointCharacteristic`.
|
||||
|
||||
An endpoint characteristic is a QL class that "tags" all endpoints for which the characteristic's `appliesToEndpoint` predicate holds. The characteristic defines a `hasImplications` predicate that declares whether all the endpoints should be considered as sinks/sources/negatives, and with which confidence.
|
||||
|
||||
The positive, negative, and candidate extraction queries largely[^1] use characteristics to decide which endpoint to select. For instance, if a characteristic exists that applies to an endpoint, and the characteristic implies (cf. `hasImplications`) that the endpoint is a sink with a high confidence – then that endpoint will be selected as a positive example. See the use of `isKnownAs` in [AutomodelFrameworkModeExtractPositiveExamples.ql](https://github.com/github/codeql/blob/main/java/ql/automodel/src/AutomodelFrameworkModeExtractPositiveExamples.ql).
|
||||
|
||||
[^1]: Candidate extraction queries are an exception, they treat `UninterestingToModelCharacteristic` differently.
|
||||
|
||||
#### :warning: Warning
|
||||
|
||||
Do not try to "fix" shortcomings that could be fixed by a better prompt or better example selection by adding language- or mode-specific characteristics . Those "fixes" tend to be confusing downstream when questions like "why wasn't this location selected as a candidate?" becomes progressively harder and harder to answer. It's best to rely on characteristics in the code that is shared across all languages and modes (see [Shared Code](#shared-code)).
|
||||
|
||||
## Shared Code
|
||||
|
||||
A significant part of the behavior of extraction queries is implemented in shared modules. When we add support for new languages, we expect to move the shared code to a separate QL pack. In the mean time, shared code modules must not import any java libraries.
|
||||
|
||||
## Packaging
|
||||
|
||||
Automodel extraction queries come as a dedicated package. See [qlpack.yml](https://github.com/github/codeql/blob/main/java/ql/automodel/src/qlpack.yml). The [publish.sh](https://github.com/github/codeql/blob/main/java/ql/automodel/publish.sh) script is responsible for publishing a new version to the [package registry](https://github.com/orgs/codeql/packages/container/package/java-automodel-queries).
|
||||
|
||||
### Backwards Compatibility
|
||||
|
||||
We try to keep changes to extraction queries backwards-compatible whenever feasible. There's several reasons:
|
||||
|
||||
- That automodel can always decide which version of the package to run is a flawed assumption. We don't have direct control over the version of the extraction queries running on the user's local machine.
|
||||
- An automodel deployment will sometimes require the extraction queries to be published. If the new version of the extraction queries works with the old version of automodel, then it is much easier to roll back deployments of automodel.
|
||||
|
||||
## Candidate Examples
|
||||
|
||||
This section contains a few examples of the kinds of candidates that our queries might select, and why.
|
||||
|
||||
:warning: For clarity, this section presents "candidates" that are **actual** sinks. Therefore, the candidates presented here would actually be selected as positive examples in practice - rather than as candidates.
|
||||
|
||||
### Framework Mode Candidates
|
||||
|
||||
Framework mode is special because in framework mode, we extract candidates (as well as examples) from the implementation of a framework or library while the resulting models are applied in code bases that are _using_ the framework or library.
|
||||
|
||||
In framework mode, endpoints currently can have a number of shapes (see: `newtype TFrameworkModeEndpoint` in [AutomodelApplicationModeExtractCandidates.ql](https://github.com/github/codeql/blob/main/java/ql/automodel/src/AutomodelFrameworkModeCharacteristics.qll)). Depending on what kind of endpoint it is, the candidate is a candidate for one or several extensible types (eg., `sinkModel`, `sourceModel`).
|
||||
|
||||
#### Framework Mode Sink Candidates
|
||||
|
||||
Sink candidates in framework mode are modelled as formal parameters of functions defined within the framework. We use these to represent the corresponding inputs of function calls in a client codebase, which would be passed into those parameters.
|
||||
|
||||
For example, customer code could call the `Files.copy` method:
|
||||
|
||||
```java
|
||||
// customer code using a library
|
||||
...
|
||||
Files.copy(userInputPath, outStream);
|
||||
...
|
||||
```
|
||||
|
||||
In order for `userInputPath` to be modeled as a sink, the corresponding parameter must be selected as a candidate. In the following example, assuming they're not modeled yet, the parameters `source` and `out` would be candidates:
|
||||
|
||||
```java
|
||||
// Files.java
|
||||
// library code that's analyzed in framework mode
|
||||
public class Files {
|
||||
public static void copy(Path source, OutputStream out) throws IOException {
|
||||
// ...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### Framework Mode Source Candidates
|
||||
|
||||
Source candidates are a bit more varied than sink candidates:
|
||||
|
||||
##### Parameters as Source Candidates
|
||||
|
||||
A parameter could be a source, e.g. when a framework passes user-controlled data to a handler defined in customer code.
|
||||
```java
|
||||
// customer code using a library:
|
||||
import java.net.http.WebSocket;
|
||||
|
||||
final class MyListener extends WebSocket.Listener {
|
||||
@override
|
||||
public CompletionStage<?> onText(WebSocket ws, CharSequence cs, boolean last) {
|
||||
... process data that was received from websocket
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
In this case, data passed to the program via a web socket connection is a source of remote data. Therefore, when we look at the implementation of `WebSocket.Listener` in framework mode, we need to produce a candidate for each parameter:
|
||||
|
||||
```java
|
||||
// WebSocket.java
|
||||
// library code that's analyzed in framework mode
|
||||
interface Listener {
|
||||
...
|
||||
default CompletionStage<?> onText(WebSocket webSocket CharSequence data, boolean last) {
|
||||
// <omitting default implementation>
|
||||
}
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
For framework mode, all parameters of the `onText` method should be candidates. If the candidates result in a model, the parameters of classes implementing this interface will be recognized as sources of remote data.
|
||||
|
||||
:warning: a consequence of this is that we can have endpoints in framework mode that are both sink candidates, as well as source candidates.
|
||||
|
||||
##### Return Values as Source Candidates
|
||||
|
||||
The other kind of source candidate we model is the return value of a method. For example:
|
||||
|
||||
```java
|
||||
public class Socket {
|
||||
...
|
||||
public InputStream getInputStream() throws IOException {
|
||||
...
|
||||
}
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
This method returns a source of remote data that should be modeled as a sink. We therefore want to select the _method_ as a candidate.
|
||||
|
||||
### Application Mode Candidates
|
||||
|
||||
In application mode, we extract candidates from an application that is using various libraries.
|
||||
|
||||
#### Application Mode Source Candidates
|
||||
|
||||
##### Overridden Parameters as Source Candidates
|
||||
|
||||
In application mode, a parameter of a method that is overriding another method is taken as a source parameter to account for cases like the `WebSocket.Listener` example above where an application is implementing a "handler" that receives remote data.
|
||||
|
||||
##### Return Values as Source Candidates
|
||||
|
||||
Just like in framework mode, application mode also has to consider the return value of a call as a source candidate. The difference is that in application mode, we extract from the application sources, not the library sources. Therefore, we use the invocation expression as a candidate (unlike in framework mode, where we use the method definition).
|
||||
|
||||
#### Application Mode Sink Candidates
|
||||
|
||||
In application mode, arguments to calls are sink candidates.
|
||||
@@ -1,6 +1,6 @@
|
||||
import java
|
||||
|
||||
from MethodAccess ma
|
||||
from MethodCall ma
|
||||
// Generally Kotlin calls will always use an explicit qualifier, except for calls
|
||||
// to the synthetic instance initializer <obinit>, which use an implicit `this`.
|
||||
where
|
||||
|
||||
@@ -44,7 +44,7 @@ predicate shouldBeDeadEnd(ControlFlowNode n) {
|
||||
or
|
||||
n instanceof WildcardTypeAccess // TODO
|
||||
or
|
||||
n instanceof MethodAccess // TODO
|
||||
n instanceof MethodCall // TODO
|
||||
or
|
||||
n instanceof Method
|
||||
or
|
||||
|
||||
@@ -37,11 +37,11 @@ predicate gapInChildren(Element e, int i) {
|
||||
// For statements may or may not declare a new variable (child 0), or
|
||||
// have a condition (child 1).
|
||||
not (e instanceof ForStmt and i = [0, 1]) and
|
||||
// TODO: Clarify situation with Kotlin and MethodAccess.
|
||||
// TODO: Clarify situation with Kotlin and MethodCall.
|
||||
// -1 can be skipped (type arguments from -2 down, no qualifier at -1,
|
||||
// then arguments from 0).
|
||||
// Can we also skip arguments, e.g. due to defaults for parameters?
|
||||
not (e instanceof MethodAccess and e.getFile().isKotlinSourceFile()) and
|
||||
not (e instanceof MethodCall and e.getFile().isKotlinSourceFile()) and
|
||||
// Kotlin-extracted annotations can have missing children where a default
|
||||
// value should be, because kotlinc doesn't load annotation defaults and we
|
||||
// want to leave a space for another extractor to fill in the default if it
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
import java
|
||||
|
||||
from MethodAccess call, Method method
|
||||
from MethodCall call, Method method
|
||||
where
|
||||
call.getMethod() = method and
|
||||
method.hasName("methodName") and
|
||||
|
||||
@@ -10,7 +10,7 @@ import java
|
||||
|
||||
from Method m, Method n
|
||||
where
|
||||
exists(MethodAccess ma | ma.getCaller() = m and ma.getCallee() = n) and
|
||||
exists(MethodAccess ma | ma.getCaller() = n and ma.getCallee() = m) and
|
||||
exists(MethodCall ma | ma.getCaller() = m and ma.getCallee() = n) and
|
||||
exists(MethodCall ma | ma.getCaller() = n and ma.getCallee() = m) and
|
||||
m != n
|
||||
select m, n
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
|
||||
import java
|
||||
|
||||
from MethodAccess call, Method add
|
||||
from MethodCall call, Method add
|
||||
where
|
||||
call.getMethod().overrides*(add) and
|
||||
add.hasName("add") and
|
||||
|
||||
@@ -10,10 +10,10 @@ User.java:
|
||||
# 3| 0: [TypeAccess] Ann2
|
||||
# 3| 5: [BlockStmt] { ... }
|
||||
# 4| 0: [ExprStmt] <Expr>;
|
||||
# 4| 0: [MethodAccess] x(...)
|
||||
# 4| 0: [MethodCall] x(...)
|
||||
# 4| -1: [VarAccess] a1
|
||||
# 4| 1: [ExprStmt] <Expr>;
|
||||
# 4| 0: [MethodAccess] z(...)
|
||||
# 4| 0: [MethodCall] z(...)
|
||||
# 4| -1: [VarAccess] a2
|
||||
# 4| 2: [ExprStmt] <Expr>;
|
||||
# 4| 0: [ClassInstanceExpr] new Annotated(...)
|
||||
@@ -49,7 +49,7 @@ ktUser.kt:
|
||||
# 8| 3: [ExprStmt] <Expr>;
|
||||
# 8| 0: [ImplicitCoercionToUnitExpr] <implicit coercion to unit>
|
||||
# 8| 0: [TypeAccess] Unit
|
||||
# 8| 1: [MethodAccess] isJavaLetter(...)
|
||||
# 8| 1: [MethodCall] isJavaLetter(...)
|
||||
# 8| -1: [TypeAccess] Character
|
||||
# 8| 0: [CharacterLiteral] a
|
||||
test.kt:
|
||||
|
||||
@@ -5,7 +5,7 @@ private import semmle.code.java.dataflow.ExternalFlow
|
||||
|
||||
module Config implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node n) {
|
||||
n.asExpr().(MethodAccess).getCallee().getName() = "source"
|
||||
n.asExpr().(MethodCall).getCallee().getName() = "source"
|
||||
or
|
||||
sourceNode(n, "kotlinMadFlowTest")
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import java
|
||||
|
||||
from MethodAccess ma
|
||||
from MethodCall ma
|
||||
select ma, ma.getCallee()
|
||||
|
||||
@@ -31,11 +31,11 @@ app/src/main/kotlin/testProject/App.kt:
|
||||
# 7| 0: [IntegerLiteral] 3
|
||||
# 7| 1: [VarAccess] seen1
|
||||
# 7| 1: [ExprStmt] <Expr>;
|
||||
# 7| 0: [MethodAccess] throwMissingFieldException(...)
|
||||
# 7| 0: [MethodCall] throwMissingFieldException(...)
|
||||
# 7| -1: [TypeAccess] PluginExceptionsKt
|
||||
# 7| 0: [VarAccess] seen1
|
||||
# 7| 1: [IntegerLiteral] 3
|
||||
# 7| 2: [MethodAccess] getDescriptor(...)
|
||||
# 7| 2: [MethodCall] getDescriptor(...)
|
||||
# 7| -1: [VarAccess] INSTANCE
|
||||
# 7| 1: [SuperConstructorInvocationStmt] super(...)
|
||||
# 7| 2: [ExprStmt] <Expr>;
|
||||
@@ -118,7 +118,7 @@ app/src/main/kotlin/testProject/App.kt:
|
||||
# 0| 1: [VarAccess] p0.language
|
||||
# 0| -1: [VarAccess] p0
|
||||
# 0| 2: [ReturnStmt] return ...
|
||||
# 0| 0: [MethodAccess] copy(...)
|
||||
# 0| 0: [MethodCall] copy(...)
|
||||
# 0| -1: [VarAccess] p0
|
||||
# 0| 0: [VarAccess] p1
|
||||
# 0| 1: [VarAccess] p2
|
||||
@@ -176,7 +176,7 @@ app/src/main/kotlin/testProject/App.kt:
|
||||
# 0| 5: [BlockStmt] { ... }
|
||||
# 0| 0: [LocalVariableDeclStmt] var ...;
|
||||
# 0| 1: [LocalVariableDeclExpr] result
|
||||
# 0| 0: [MethodAccess] hashCode(...)
|
||||
# 0| 0: [MethodCall] hashCode(...)
|
||||
# 0| -1: [VarAccess] this.name
|
||||
# 0| -1: [ThisAccess] this
|
||||
# 0| 1: [ExprStmt] <Expr>;
|
||||
@@ -186,7 +186,7 @@ app/src/main/kotlin/testProject/App.kt:
|
||||
# 0| 0: [MulExpr] ... * ...
|
||||
# 0| 0: [VarAccess] result
|
||||
# 0| 1: [IntegerLiteral] 31
|
||||
# 0| 1: [MethodAccess] hashCode(...)
|
||||
# 0| 1: [MethodCall] hashCode(...)
|
||||
# 0| -1: [VarAccess] this.language
|
||||
# 0| -1: [ThisAccess] this
|
||||
# 0| 2: [ReturnStmt] return ...
|
||||
@@ -226,18 +226,18 @@ app/src/main/kotlin/testProject/App.kt:
|
||||
# 0| 0: [TypeAccess] SerialDescriptor
|
||||
# 7| 5: [BlockStmt] { ... }
|
||||
# 7| 0: [ExprStmt] <Expr>;
|
||||
# 7| 0: [MethodAccess] encodeStringElement(...)
|
||||
# 7| 0: [MethodCall] encodeStringElement(...)
|
||||
# 7| -1: [VarAccess] output
|
||||
# 7| 0: [VarAccess] serialDesc
|
||||
# 7| 1: [IntegerLiteral] 0
|
||||
# 7| 2: [MethodAccess] getName(...)
|
||||
# 7| 2: [MethodCall] getName(...)
|
||||
# 7| -1: [VarAccess] self
|
||||
# 7| 1: [ExprStmt] <Expr>;
|
||||
# 7| 0: [MethodAccess] encodeIntElement(...)
|
||||
# 7| 0: [MethodCall] encodeIntElement(...)
|
||||
# 7| -1: [VarAccess] output
|
||||
# 7| 0: [VarAccess] serialDesc
|
||||
# 7| 1: [IntegerLiteral] 1
|
||||
# 7| 2: [MethodAccess] getLanguage(...)
|
||||
# 7| 2: [MethodCall] getLanguage(...)
|
||||
# 7| -1: [VarAccess] self
|
||||
# 7| 10: [Class] $serializer
|
||||
#-----| -3: (Annotations)
|
||||
@@ -274,7 +274,7 @@ app/src/main/kotlin/testProject/App.kt:
|
||||
# 7| 5: [BlockStmt] { ... }
|
||||
# 7| 0: [LocalVariableDeclStmt] var ...;
|
||||
# 7| 1: [LocalVariableDeclExpr] tmp0_desc
|
||||
# 7| 0: [MethodAccess] getDescriptor(...)
|
||||
# 7| 0: [MethodCall] getDescriptor(...)
|
||||
# 7| -1: [ThisAccess] this
|
||||
# 7| 1: [LocalVariableDeclStmt] var ...;
|
||||
# 7| 1: [LocalVariableDeclExpr] tmp1_flag
|
||||
@@ -293,20 +293,20 @@ app/src/main/kotlin/testProject/App.kt:
|
||||
# 7| 0: [IntegerLiteral] 0
|
||||
# 7| 6: [LocalVariableDeclStmt] var ...;
|
||||
# 7| 1: [LocalVariableDeclExpr] tmp6_input
|
||||
# 7| 0: [MethodAccess] beginStructure(...)
|
||||
# 7| 0: [MethodCall] beginStructure(...)
|
||||
# 7| -1: [VarAccess] decoder
|
||||
# 7| 0: [VarAccess] tmp0_desc
|
||||
# 7| 7: [ExprStmt] <Expr>;
|
||||
# 7| 0: [WhenExpr] when ...
|
||||
# 7| 0: [WhenBranch] ... -> ...
|
||||
# 7| 0: [MethodAccess] decodeSequentially(...)
|
||||
# 7| 0: [MethodCall] decodeSequentially(...)
|
||||
# 7| -1: [VarAccess] tmp6_input
|
||||
# 7| 1: [BlockStmt] { ... }
|
||||
# 7| 0: [BlockStmt] { ... }
|
||||
# 7| 0: [ExprStmt] <Expr>;
|
||||
# 7| 0: [AssignExpr] ...=...
|
||||
# 7| 0: [VarAccess] tmp4_local0
|
||||
# 7| 1: [MethodAccess] decodeStringElement(...)
|
||||
# 7| 1: [MethodCall] decodeStringElement(...)
|
||||
# 7| -1: [VarAccess] tmp6_input
|
||||
# 7| 0: [VarAccess] tmp0_desc
|
||||
# 7| 1: [IntegerLiteral] 0
|
||||
@@ -320,7 +320,7 @@ app/src/main/kotlin/testProject/App.kt:
|
||||
# 7| 0: [ExprStmt] <Expr>;
|
||||
# 7| 0: [AssignExpr] ...=...
|
||||
# 7| 0: [VarAccess] tmp5_local1
|
||||
# 7| 1: [MethodAccess] decodeIntElement(...)
|
||||
# 7| 1: [MethodCall] decodeIntElement(...)
|
||||
# 7| -1: [VarAccess] tmp6_input
|
||||
# 7| 0: [VarAccess] tmp0_desc
|
||||
# 7| 1: [IntegerLiteral] 1
|
||||
@@ -338,7 +338,7 @@ app/src/main/kotlin/testProject/App.kt:
|
||||
# 7| 0: [ExprStmt] <Expr>;
|
||||
# 7| 0: [AssignExpr] ...=...
|
||||
# 7| 0: [VarAccess] tmp2_index
|
||||
# 7| 1: [MethodAccess] decodeElementIndex(...)
|
||||
# 7| 1: [MethodCall] decodeElementIndex(...)
|
||||
# 7| -1: [VarAccess] tmp6_input
|
||||
# 7| 0: [VarAccess] tmp0_desc
|
||||
# 7| 1: [ExprStmt] <Expr>;
|
||||
@@ -359,7 +359,7 @@ app/src/main/kotlin/testProject/App.kt:
|
||||
# 7| 0: [ExprStmt] <Expr>;
|
||||
# 7| 0: [AssignExpr] ...=...
|
||||
# 7| 0: [VarAccess] tmp4_local0
|
||||
# 7| 1: [MethodAccess] decodeStringElement(...)
|
||||
# 7| 1: [MethodCall] decodeStringElement(...)
|
||||
# 7| -1: [VarAccess] tmp6_input
|
||||
# 7| 0: [VarAccess] tmp0_desc
|
||||
# 7| 1: [IntegerLiteral] 0
|
||||
@@ -377,7 +377,7 @@ app/src/main/kotlin/testProject/App.kt:
|
||||
# 7| 0: [ExprStmt] <Expr>;
|
||||
# 7| 0: [AssignExpr] ...=...
|
||||
# 7| 0: [VarAccess] tmp5_local1
|
||||
# 7| 1: [MethodAccess] decodeIntElement(...)
|
||||
# 7| 1: [MethodCall] decodeIntElement(...)
|
||||
# 7| -1: [VarAccess] tmp6_input
|
||||
# 7| 0: [VarAccess] tmp0_desc
|
||||
# 7| 1: [IntegerLiteral] 1
|
||||
@@ -394,7 +394,7 @@ app/src/main/kotlin/testProject/App.kt:
|
||||
# 7| -3: [TypeAccess] UnknownFieldException
|
||||
# 7| 0: [VarAccess] tmp2_index
|
||||
# 7| 8: [ExprStmt] <Expr>;
|
||||
# 7| 0: [MethodAccess] endStructure(...)
|
||||
# 7| 0: [MethodCall] endStructure(...)
|
||||
# 7| -1: [VarAccess] tmp6_input
|
||||
# 7| 0: [VarAccess] tmp0_desc
|
||||
# 7| 9: [ReturnStmt] return ...
|
||||
@@ -426,21 +426,21 @@ app/src/main/kotlin/testProject/App.kt:
|
||||
# 7| 5: [BlockStmt] { ... }
|
||||
# 7| 0: [LocalVariableDeclStmt] var ...;
|
||||
# 7| 1: [LocalVariableDeclExpr] tmp0_desc
|
||||
# 7| 0: [MethodAccess] getDescriptor(...)
|
||||
# 7| 0: [MethodCall] getDescriptor(...)
|
||||
# 7| -1: [ThisAccess] this
|
||||
# 7| 1: [LocalVariableDeclStmt] var ...;
|
||||
# 7| 1: [LocalVariableDeclExpr] tmp1_output
|
||||
# 7| 0: [MethodAccess] beginStructure(...)
|
||||
# 7| 0: [MethodCall] beginStructure(...)
|
||||
# 7| -1: [VarAccess] encoder
|
||||
# 7| 0: [VarAccess] tmp0_desc
|
||||
# 7| 2: [ExprStmt] <Expr>;
|
||||
# 7| 0: [MethodAccess] write$Self(...)
|
||||
# 7| 0: [MethodCall] write$Self(...)
|
||||
# 7| -1: [TypeAccess] Project
|
||||
# 7| 0: [VarAccess] value
|
||||
# 7| 1: [VarAccess] tmp1_output
|
||||
# 7| 2: [VarAccess] tmp0_desc
|
||||
# 7| 3: [ExprStmt] <Expr>;
|
||||
# 7| 0: [MethodAccess] endStructure(...)
|
||||
# 7| 0: [MethodCall] endStructure(...)
|
||||
# 7| -1: [VarAccess] tmp1_output
|
||||
# 7| 0: [VarAccess] tmp0_desc
|
||||
# 7| 6: [Constructor] $serializer
|
||||
@@ -456,12 +456,12 @@ app/src/main/kotlin/testProject/App.kt:
|
||||
# 7| 0: [TypeAccess] $serializer
|
||||
# 7| 2: [IntegerLiteral] 2
|
||||
# 7| 1: [ExprStmt] <Expr>;
|
||||
# 7| 0: [MethodAccess] addElement(...)
|
||||
# 7| 0: [MethodCall] addElement(...)
|
||||
# 7| -1: [VarAccess] tmp0_serialDesc
|
||||
# 7| 0: [StringLiteral] "name"
|
||||
# 7| 1: [BooleanLiteral] false
|
||||
# 7| 2: [ExprStmt] <Expr>;
|
||||
# 7| 0: [MethodAccess] addElement(...)
|
||||
# 7| 0: [MethodCall] addElement(...)
|
||||
# 7| -1: [VarAccess] tmp0_serialDesc
|
||||
# 7| 0: [StringLiteral] "language"
|
||||
# 7| 1: [BooleanLiteral] false
|
||||
@@ -477,7 +477,7 @@ app/src/main/kotlin/testProject/App.kt:
|
||||
# 7| 0: [WildcardTypeAccess] ? ...
|
||||
# 7| 5: [BlockStmt] { ... }
|
||||
# 7| 0: [ReturnStmt] return ...
|
||||
# 7| 0: [MethodAccess] typeParametersSerializers(...)
|
||||
# 7| 0: [MethodCall] typeParametersSerializers(...)
|
||||
# 7| -1: [SuperAccess] GeneratedSerializer.super
|
||||
# 7| 0: [TypeAccess] GeneratedSerializer
|
||||
# 7| 11: [Class] Companion
|
||||
@@ -564,11 +564,11 @@ app/src/main/kotlin/testProject/App.kt:
|
||||
# 14| 0: [IntegerLiteral] 0
|
||||
# 14| 1: [VarAccess] seen1
|
||||
# 14| 1: [ExprStmt] <Expr>;
|
||||
# 14| 0: [MethodAccess] throwMissingFieldException(...)
|
||||
# 14| 0: [MethodCall] throwMissingFieldException(...)
|
||||
# 14| -1: [TypeAccess] PluginExceptionsKt
|
||||
# 14| 0: [VarAccess] seen1
|
||||
# 14| 1: [IntegerLiteral] 0
|
||||
# 14| 2: [MethodAccess] getDescriptor(...)
|
||||
# 14| 2: [MethodCall] getDescriptor(...)
|
||||
# 14| -1: [VarAccess] INSTANCE
|
||||
# 14| 1: [SuperConstructorInvocationStmt] super(...)
|
||||
# 14| 2: [ExprStmt] <Expr>;
|
||||
@@ -616,7 +616,7 @@ app/src/main/kotlin/testProject/App.kt:
|
||||
# 14| 0: [WhenBranch] ... -> ...
|
||||
# 14| 0: [WhenExpr] when ...
|
||||
# 14| 0: [WhenBranch] ... -> ...
|
||||
# 14| 0: [MethodAccess] shouldEncodeElementDefault(...)
|
||||
# 14| 0: [MethodCall] shouldEncodeElementDefault(...)
|
||||
# 14| -1: [VarAccess] output
|
||||
# 14| 0: [VarAccess] serialDesc
|
||||
# 14| 1: [IntegerLiteral] 0
|
||||
@@ -626,15 +626,15 @@ app/src/main/kotlin/testProject/App.kt:
|
||||
# 14| 0: [BooleanLiteral] true
|
||||
# 14| 1: [ExprStmt] <Expr>;
|
||||
# 14| 0: [ValueNEExpr] ... (value not-equals) ...
|
||||
# 14| 0: [MethodAccess] getId(...)
|
||||
# 14| 0: [MethodCall] getId(...)
|
||||
# 14| -1: [VarAccess] self
|
||||
# 16| 1: [StringLiteral] "X"
|
||||
# 14| 1: [ExprStmt] <Expr>;
|
||||
# 14| 0: [MethodAccess] encodeStringElement(...)
|
||||
# 14| 0: [MethodCall] encodeStringElement(...)
|
||||
# 14| -1: [VarAccess] output
|
||||
# 14| 0: [VarAccess] serialDesc
|
||||
# 14| 1: [IntegerLiteral] 0
|
||||
# 14| 2: [MethodAccess] getId(...)
|
||||
# 14| 2: [MethodCall] getId(...)
|
||||
# 14| -1: [VarAccess] self
|
||||
# 14| 3: [Class] $serializer
|
||||
#-----| -3: (Annotations)
|
||||
@@ -671,7 +671,7 @@ app/src/main/kotlin/testProject/App.kt:
|
||||
# 14| 5: [BlockStmt] { ... }
|
||||
# 14| 0: [LocalVariableDeclStmt] var ...;
|
||||
# 14| 1: [LocalVariableDeclExpr] tmp0_desc
|
||||
# 14| 0: [MethodAccess] getDescriptor(...)
|
||||
# 14| 0: [MethodCall] getDescriptor(...)
|
||||
# 14| -1: [ThisAccess] this
|
||||
# 14| 1: [LocalVariableDeclStmt] var ...;
|
||||
# 14| 1: [LocalVariableDeclExpr] tmp1_flag
|
||||
@@ -687,20 +687,20 @@ app/src/main/kotlin/testProject/App.kt:
|
||||
# 14| 0: [NullLiteral] null
|
||||
# 14| 5: [LocalVariableDeclStmt] var ...;
|
||||
# 14| 1: [LocalVariableDeclExpr] tmp5_input
|
||||
# 14| 0: [MethodAccess] beginStructure(...)
|
||||
# 14| 0: [MethodCall] beginStructure(...)
|
||||
# 14| -1: [VarAccess] decoder
|
||||
# 14| 0: [VarAccess] tmp0_desc
|
||||
# 14| 6: [ExprStmt] <Expr>;
|
||||
# 14| 0: [WhenExpr] when ...
|
||||
# 14| 0: [WhenBranch] ... -> ...
|
||||
# 14| 0: [MethodAccess] decodeSequentially(...)
|
||||
# 14| 0: [MethodCall] decodeSequentially(...)
|
||||
# 14| -1: [VarAccess] tmp5_input
|
||||
# 14| 1: [BlockStmt] { ... }
|
||||
# 14| 0: [BlockStmt] { ... }
|
||||
# 14| 0: [ExprStmt] <Expr>;
|
||||
# 14| 0: [AssignExpr] ...=...
|
||||
# 14| 0: [VarAccess] tmp4_local0
|
||||
# 14| 1: [MethodAccess] decodeStringElement(...)
|
||||
# 14| 1: [MethodCall] decodeStringElement(...)
|
||||
# 14| -1: [VarAccess] tmp5_input
|
||||
# 14| 0: [VarAccess] tmp0_desc
|
||||
# 14| 1: [IntegerLiteral] 0
|
||||
@@ -718,7 +718,7 @@ app/src/main/kotlin/testProject/App.kt:
|
||||
# 14| 0: [ExprStmt] <Expr>;
|
||||
# 14| 0: [AssignExpr] ...=...
|
||||
# 14| 0: [VarAccess] tmp2_index
|
||||
# 14| 1: [MethodAccess] decodeElementIndex(...)
|
||||
# 14| 1: [MethodCall] decodeElementIndex(...)
|
||||
# 14| -1: [VarAccess] tmp5_input
|
||||
# 14| 0: [VarAccess] tmp0_desc
|
||||
# 14| 1: [ExprStmt] <Expr>;
|
||||
@@ -739,7 +739,7 @@ app/src/main/kotlin/testProject/App.kt:
|
||||
# 14| 0: [ExprStmt] <Expr>;
|
||||
# 14| 0: [AssignExpr] ...=...
|
||||
# 14| 0: [VarAccess] tmp4_local0
|
||||
# 14| 1: [MethodAccess] decodeStringElement(...)
|
||||
# 14| 1: [MethodCall] decodeStringElement(...)
|
||||
# 14| -1: [VarAccess] tmp5_input
|
||||
# 14| 0: [VarAccess] tmp0_desc
|
||||
# 14| 1: [IntegerLiteral] 0
|
||||
@@ -756,7 +756,7 @@ app/src/main/kotlin/testProject/App.kt:
|
||||
# 14| -3: [TypeAccess] UnknownFieldException
|
||||
# 14| 0: [VarAccess] tmp2_index
|
||||
# 14| 7: [ExprStmt] <Expr>;
|
||||
# 14| 0: [MethodAccess] endStructure(...)
|
||||
# 14| 0: [MethodCall] endStructure(...)
|
||||
# 14| -1: [VarAccess] tmp5_input
|
||||
# 14| 0: [VarAccess] tmp0_desc
|
||||
# 14| 8: [ReturnStmt] return ...
|
||||
@@ -787,21 +787,21 @@ app/src/main/kotlin/testProject/App.kt:
|
||||
# 14| 5: [BlockStmt] { ... }
|
||||
# 14| 0: [LocalVariableDeclStmt] var ...;
|
||||
# 14| 1: [LocalVariableDeclExpr] tmp0_desc
|
||||
# 14| 0: [MethodAccess] getDescriptor(...)
|
||||
# 14| 0: [MethodCall] getDescriptor(...)
|
||||
# 14| -1: [ThisAccess] this
|
||||
# 14| 1: [LocalVariableDeclStmt] var ...;
|
||||
# 14| 1: [LocalVariableDeclExpr] tmp1_output
|
||||
# 14| 0: [MethodAccess] beginStructure(...)
|
||||
# 14| 0: [MethodCall] beginStructure(...)
|
||||
# 14| -1: [VarAccess] encoder
|
||||
# 14| 0: [VarAccess] tmp0_desc
|
||||
# 14| 2: [ExprStmt] <Expr>;
|
||||
# 14| 0: [MethodAccess] write$Self(...)
|
||||
# 14| 0: [MethodCall] write$Self(...)
|
||||
# 14| -1: [TypeAccess] X
|
||||
# 14| 0: [VarAccess] value
|
||||
# 14| 1: [VarAccess] tmp1_output
|
||||
# 14| 2: [VarAccess] tmp0_desc
|
||||
# 14| 3: [ExprStmt] <Expr>;
|
||||
# 14| 0: [MethodAccess] endStructure(...)
|
||||
# 14| 0: [MethodCall] endStructure(...)
|
||||
# 14| -1: [VarAccess] tmp1_output
|
||||
# 14| 0: [VarAccess] tmp0_desc
|
||||
# 14| 6: [Constructor] $serializer
|
||||
@@ -817,7 +817,7 @@ app/src/main/kotlin/testProject/App.kt:
|
||||
# 14| 0: [TypeAccess] $serializer
|
||||
# 14| 2: [IntegerLiteral] 1
|
||||
# 14| 1: [ExprStmt] <Expr>;
|
||||
# 14| 0: [MethodAccess] addElement(...)
|
||||
# 14| 0: [MethodCall] addElement(...)
|
||||
# 14| -1: [VarAccess] tmp0_serialDesc
|
||||
# 14| 0: [StringLiteral] "id"
|
||||
# 14| 1: [BooleanLiteral] true
|
||||
@@ -833,7 +833,7 @@ app/src/main/kotlin/testProject/App.kt:
|
||||
# 14| 0: [WildcardTypeAccess] ? ...
|
||||
# 14| 5: [BlockStmt] { ... }
|
||||
# 14| 0: [ReturnStmt] return ...
|
||||
# 14| 0: [MethodAccess] typeParametersSerializers(...)
|
||||
# 14| 0: [MethodCall] typeParametersSerializers(...)
|
||||
# 14| -1: [SuperAccess] GeneratedSerializer.super
|
||||
# 14| 0: [TypeAccess] GeneratedSerializer
|
||||
# 14| 4: [Class] Companion
|
||||
|
||||
@@ -30,9 +30,7 @@ query predicate nestedTypes(NestedType nt, RefType parent) {
|
||||
parent = nt.getEnclosingType()
|
||||
}
|
||||
|
||||
query predicate javaKotlinCalleeAgreement(
|
||||
MethodAccess javaMa, MethodAccess kotlinMa, Callable callee
|
||||
) {
|
||||
query predicate javaKotlinCalleeAgreement(MethodCall javaMa, MethodCall kotlinMa, Callable callee) {
|
||||
javaMa.getCallee() = callee and
|
||||
kotlinMa.getCallee() = callee and
|
||||
javaMa.getFile().getExtension() = "java" and
|
||||
|
||||
@@ -39,7 +39,7 @@ c.kt:
|
||||
# 0| 0: [TypeAccess] ProcessBuilder
|
||||
# 0| 5: [BlockStmt] { ... }
|
||||
# 0| 0: [ReturnStmt] return ...
|
||||
# 0| 0: [MethodAccess] start(...)
|
||||
# 0| 0: [MethodCall] start(...)
|
||||
# 0| -1: [VarAccess] param
|
||||
# 1| 2: [Constructor] C
|
||||
# 1| 5: [BlockStmt] { ... }
|
||||
@@ -62,7 +62,7 @@ e.kt:
|
||||
# 0| 3: [TypeAccess] boolean
|
||||
# 0| 5: [BlockStmt] { ... }
|
||||
# 0| 0: [ReturnStmt] return ...
|
||||
# 0| 0: [MethodAccess] add(...)
|
||||
# 0| 0: [MethodCall] add(...)
|
||||
# 0| -1: [ClassInstanceExpr] new ArrayList<Object>(...)
|
||||
# 0| -3: [TypeAccess] ArrayList<Object>
|
||||
# 0| 0: [IntegerLiteral] 1
|
||||
@@ -71,7 +71,7 @@ e.kt:
|
||||
# 0| 3: [TypeAccess] Object
|
||||
# 0| 5: [BlockStmt] { ... }
|
||||
# 0| 0: [ReturnStmt] return ...
|
||||
# 0| 0: [MethodAccess] put(...)
|
||||
# 0| 0: [MethodCall] put(...)
|
||||
# 0| -1: [ClassInstanceExpr] new LinkedHashMap<Object,Object>(...)
|
||||
# 0| -3: [TypeAccess] LinkedHashMap<Object,Object>
|
||||
# 0| 0: [IntegerLiteral] 1
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import java
|
||||
|
||||
from MethodAccess ma
|
||||
from MethodCall ma
|
||||
select ma, ma.getCallee().toString(), ma.getCallee().getAParamType().toString()
|
||||
|
||||
4
java/ql/lib/change-notes/2023-10-23-spring-6-models.md
Normal file
4
java/ql/lib/change-notes/2023-10-23-spring-6-models.md
Normal file
@@ -0,0 +1,4 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* Added up to date models related to Spring Framework 6's `org.springframework.http.ResponseEntity`.
|
||||
5
java/ql/lib/change-notes/2023-10-24-java-renames.md
Normal file
5
java/ql/lib/change-notes/2023-10-24-java-renames.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
category: minorAnalysis
|
||||
---
|
||||
* Java classes `MethodAccess`, `LValue` and `RValue` were renamed to `MethodCall`, `VarWrite` and `VarRead` respectively, along with related predicates and class names. The old names remain usable for the time being but are deprecated and should be replaced.
|
||||
* New class `NewClassExpr` was added to represent specifically an explicit `new ClassName(...)` invocation, in contrast to `ClassInstanceExpr` which also includes expressions that implicitly instantiate classes, such as defining a lambda or taking a method reference.
|
||||
@@ -15,7 +15,7 @@ import IDEContextual
|
||||
* the location may be slightly inaccurate and include such whitespace,
|
||||
* but it should suffice for the purpose of avoiding overlapping definitions.
|
||||
*/
|
||||
private class LocationOverridingMethodAccess extends MethodAccess {
|
||||
private class LocationOverridingMethodCall extends MethodCall {
|
||||
override predicate hasLocationInfo(string path, int sl, int sc, int el, int ec) {
|
||||
exists(MemberRefExpr e | e.getReferencedCallable() = this.getMethod() |
|
||||
exists(int elRef, int ecRef | e.hasLocationInfo(path, _, _, elRef, ecRef) |
|
||||
@@ -152,7 +152,7 @@ private class LocationOverridingImportStaticTypeMember extends ImportStaticTypeM
|
||||
}
|
||||
|
||||
private Element definition(Element e, string kind) {
|
||||
e.(MethodAccess).getMethod().getSourceDeclaration() = result and
|
||||
e.(MethodCall).getMethod().getSourceDeclaration() = result and
|
||||
kind = "M" and
|
||||
not result instanceof InitializerMethod
|
||||
or
|
||||
|
||||
@@ -64,10 +64,16 @@ extensions:
|
||||
- ["org.springframework.http", "RequestEntity", True, "getUrl", "()", "", "Argument[this]", "ReturnValue", "taint", "manual"]
|
||||
- ["org.springframework.http", "ResponseEntity", True, "ResponseEntity", "(MultiValueMap,HttpStatus)", "", "Argument[0].MapKey", "Argument[this]", "taint", "manual"]
|
||||
- ["org.springframework.http", "ResponseEntity", True, "ResponseEntity", "(MultiValueMap,HttpStatus)", "", "Argument[0].MapValue.Element", "Argument[this]", "taint", "manual"]
|
||||
- ["org.springframework.http", "ResponseEntity", True, "ResponseEntity", "(MultiValueMap,HttpStatusCode)", "", "Argument[0].MapKey", "Argument[this]", "taint", "manual"]
|
||||
- ["org.springframework.http", "ResponseEntity", True, "ResponseEntity", "(MultiValueMap,HttpStatusCode)", "", "Argument[0].MapValue.Element", "Argument[this]", "taint", "manual"]
|
||||
- ["org.springframework.http", "ResponseEntity", True, "ResponseEntity", "(Object,HttpStatus)", "", "Argument[0]", "Argument[this]", "taint", "manual"]
|
||||
- ["org.springframework.http", "ResponseEntity", True, "ResponseEntity", "(Object,HttpStatusCode)", "", "Argument[0]", "Argument[this]", "taint", "manual"]
|
||||
- ["org.springframework.http", "ResponseEntity", True, "ResponseEntity", "(Object,MultiValueMap,HttpStatus)", "", "Argument[0]", "Argument[this]", "taint", "manual"]
|
||||
- ["org.springframework.http", "ResponseEntity", True, "ResponseEntity", "(Object,MultiValueMap,HttpStatus)", "", "Argument[1].MapKey", "Argument[this]", "taint", "manual"]
|
||||
- ["org.springframework.http", "ResponseEntity", True, "ResponseEntity", "(Object,MultiValueMap,HttpStatus)", "", "Argument[1].MapValue.Element", "Argument[this]", "taint", "manual"]
|
||||
- ["org.springframework.http", "ResponseEntity", True, "ResponseEntity", "(Object,MultiValueMap,HttpStatusCode)", "", "Argument[0]", "Argument[this]", "taint", "manual"]
|
||||
- ["org.springframework.http", "ResponseEntity", True, "ResponseEntity", "(Object,MultiValueMap,HttpStatusCode)", "", "Argument[1].MapKey", "Argument[this]", "taint", "manual"]
|
||||
- ["org.springframework.http", "ResponseEntity", True, "ResponseEntity", "(Object,MultiValueMap,HttpStatusCode)", "", "Argument[1].MapValue.Element", "Argument[this]", "taint", "manual"]
|
||||
- ["org.springframework.http", "ResponseEntity", True, "ResponseEntity", "(Object,MultiValueMap,int)", "", "Argument[0]", "Argument[this]", "taint", "manual"]
|
||||
- ["org.springframework.http", "ResponseEntity", True, "ResponseEntity", "(Object,MultiValueMap,int)", "", "Argument[1].MapKey", "Argument[this]", "taint", "manual"]
|
||||
- ["org.springframework.http", "ResponseEntity", True, "ResponseEntity", "(Object,MultiValueMap,int)", "", "Argument[1].MapValue.Element", "Argument[this]", "taint", "manual"]
|
||||
|
||||
@@ -8,6 +8,7 @@ upgrades: upgrades
|
||||
dependencies:
|
||||
codeql/dataflow: ${workspace}
|
||||
codeql/mad: ${workspace}
|
||||
codeql/rangeanalysis: ${workspace}
|
||||
codeql/regex: ${workspace}
|
||||
codeql/threat-models: ${workspace}
|
||||
codeql/tutorial: ${workspace}
|
||||
|
||||
@@ -82,7 +82,7 @@ class CollectionMutator extends CollectionMethod {
|
||||
}
|
||||
|
||||
/** A method call that mutates a collection. */
|
||||
class CollectionMutation extends MethodAccess {
|
||||
class CollectionMutation extends MethodCall {
|
||||
CollectionMutation() { this.getMethod() instanceof CollectionMutator }
|
||||
|
||||
/** Holds if the result of this call is not immediately discarded. */
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
*
|
||||
* An important goal of the CFG is to get the order of side-effects correct.
|
||||
* Most expressions can have side-effects and must therefore be modeled in the
|
||||
* CFG in AST post-order. For example, a `MethodAccess` evaluates its arguments
|
||||
* CFG in AST post-order. For example, a `MethodCall` evaluates its arguments
|
||||
* before the call. Most statements don't have side-effects, but merely affect
|
||||
* the control-flow and some could therefore be excluded from the CFG. However,
|
||||
* as a design choice, all statements are included in the CFG and generally
|
||||
@@ -190,7 +190,7 @@ private module ControlFlowGraphImpl {
|
||||
/**
|
||||
* Bind `t` to an unchecked exception that may occur in a precondition check.
|
||||
*/
|
||||
private predicate uncheckedExceptionFromMethod(MethodAccess ma, ThrowableType t) {
|
||||
private predicate uncheckedExceptionFromMethod(MethodCall ma, ThrowableType t) {
|
||||
conditionCheckArgument(ma, _, _) and
|
||||
(t instanceof TypeError or t instanceof TypeRuntimeException)
|
||||
}
|
||||
@@ -349,8 +349,8 @@ private module ControlFlowGraphImpl {
|
||||
forall(Parameter p | p = this.getAParameter() | exists(p.getAnAccess()))
|
||||
}
|
||||
|
||||
/** Gets a `MethodAccess` that calls this method. */
|
||||
MethodAccess getAnAccess() { result.getMethod().getAPossibleImplementation() = this }
|
||||
/** Gets a `MethodCall` that calls this method. */
|
||||
MethodCall getAnAccess() { result.getMethod().getAPossibleImplementation() = this }
|
||||
}
|
||||
|
||||
/** Holds if a call to `m` indicates that `m` is expected to return. */
|
||||
@@ -390,9 +390,9 @@ private module ControlFlowGraphImpl {
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a `MethodAccess` that always throws an exception or calls `exit`.
|
||||
* Gets a `MethodCall` that always throws an exception or calls `exit`.
|
||||
*/
|
||||
private MethodAccess nonReturningMethodAccess() {
|
||||
private MethodCall nonReturningMethodCall() {
|
||||
result.getMethod().getSourceDeclaration() = nonReturningMethod() or
|
||||
result = likelyNonReturningMethod().getAnAccess()
|
||||
}
|
||||
@@ -422,7 +422,7 @@ private module ControlFlowGraphImpl {
|
||||
* Gets an expression that always throws an exception or calls `exit`.
|
||||
*/
|
||||
private Expr nonReturningExpr() {
|
||||
result = nonReturningMethodAccess()
|
||||
result = nonReturningMethodCall()
|
||||
or
|
||||
result.(StmtExpr).getStmt() = nonReturningStmt()
|
||||
or
|
||||
@@ -473,7 +473,7 @@ private module ControlFlowGraphImpl {
|
||||
or
|
||||
this instanceof ClassExpr
|
||||
or
|
||||
this instanceof RValue
|
||||
this instanceof VarRead
|
||||
or
|
||||
this instanceof Call // includes both expressions and statements
|
||||
or
|
||||
@@ -554,7 +554,7 @@ private module ControlFlowGraphImpl {
|
||||
or
|
||||
index = 0 and result = this.(LocalVariableDeclExpr).getInit()
|
||||
or
|
||||
index = 0 and result = this.(RValue).getQualifier() and not result instanceof TypeAccess
|
||||
index = 0 and result = this.(VarRead).getQualifier() and not result instanceof TypeAccess
|
||||
or
|
||||
exists(Call e | e = this |
|
||||
index = -1 and result = e.getQualifier() and not result instanceof TypeAccess
|
||||
@@ -588,7 +588,7 @@ private module ControlFlowGraphImpl {
|
||||
not this instanceof BooleanLiteral and
|
||||
not this instanceof ReturnStmt and
|
||||
not this instanceof ThrowStmt and
|
||||
not this = nonReturningMethodAccess()
|
||||
not this = nonReturningMethodCall()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -530,6 +530,9 @@ class Literal extends Expr, @literal {
|
||||
* Gets a string representation of this literal as it appeared
|
||||
* in the source code.
|
||||
*
|
||||
* For Kotlin the result might not match the exact representation
|
||||
* used in the source code.
|
||||
*
|
||||
* **Important:** Unless a query explicitly wants to check how
|
||||
* a literal was written in the source code, the predicate
|
||||
* `getValue()` (or value predicates of subclasses) should be
|
||||
@@ -1251,6 +1254,14 @@ class ClassInstanceExpr extends Expr, ConstructorCall, @classinstancexpr {
|
||||
override string getAPrimaryQlClass() { result = "ClassInstanceExpr" }
|
||||
}
|
||||
|
||||
/**
|
||||
* An explicit `new TypeName(...)` expression.
|
||||
*
|
||||
* Note this does not include implicit instance creation such as lambda expressions
|
||||
* or `instanceVar::methodName` references. To include those too, use `ClassInstanceExpr`.
|
||||
*/
|
||||
class NewClassExpr extends @newexpr, ClassInstanceExpr { }
|
||||
|
||||
/** A functional expression is either a lambda expression or a member reference expression. */
|
||||
abstract class FunctionalExpr extends ClassInstanceExpr {
|
||||
/** Gets the implicit method corresponding to this functional expression. */
|
||||
@@ -1372,7 +1383,7 @@ class MemberRefExpr extends FunctionalExpr, @memberref {
|
||||
*/
|
||||
RefType getReceiverType() {
|
||||
exists(Expr resultExpr | resultExpr = this.getResultExpr() |
|
||||
result = resultExpr.(MethodAccess).getReceiverType() or
|
||||
result = resultExpr.(MethodCall).getReceiverType() or
|
||||
result = resultExpr.(ClassInstanceExpr).getConstructedType() or
|
||||
result = resultExpr.(ArrayCreationExpr).getType()
|
||||
)
|
||||
@@ -1768,24 +1779,29 @@ class VarAccess extends Expr, @varaccess {
|
||||
Variable getVariable() { variableBinding(this, result) }
|
||||
|
||||
/**
|
||||
* Holds if this variable access is an l-value.
|
||||
* Holds if this variable access is a write access.
|
||||
*
|
||||
* An l-value is a write access to a variable, which occurs as the destination of an assignment.
|
||||
* That means the access is the destination of an assignment.
|
||||
*/
|
||||
predicate isLValue() {
|
||||
predicate isVarWrite() {
|
||||
exists(Assignment a | a.getDest() = this) or
|
||||
exists(UnaryAssignExpr e | e.getExpr() = this)
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for `isVarWrite`. */
|
||||
deprecated predicate isLValue() { this.isVarWrite() }
|
||||
|
||||
/**
|
||||
* Holds if this variable access is an r-value.
|
||||
* Holds if this variable access is a read access.
|
||||
*
|
||||
* An r-value is a read access to a variable.
|
||||
* In other words, it is a variable access that does _not_ occur as the destination of
|
||||
* a simple assignment, but it may occur as the destination of a compound assignment
|
||||
* or a unary assignment.
|
||||
*/
|
||||
predicate isRValue() { not exists(AssignExpr a | a.getDest() = this) }
|
||||
predicate isVarRead() { not exists(AssignExpr a | a.getDest() = this) }
|
||||
|
||||
/** DEPRECATED: Alias for `isVarRead`. */
|
||||
deprecated predicate isRValue() { this.isVarRead() }
|
||||
|
||||
/** Gets a printable representation of this expression. */
|
||||
override string toString() {
|
||||
@@ -1831,37 +1847,46 @@ class ExtensionReceiverAccess extends VarAccess {
|
||||
}
|
||||
|
||||
/**
|
||||
* An l-value is a write access to a variable, which occurs as the destination of an assignment.
|
||||
* A write access to a variable, which occurs as the destination of an assignment.
|
||||
*/
|
||||
class LValue extends VarAccess {
|
||||
LValue() { this.isLValue() }
|
||||
class VarWrite extends VarAccess {
|
||||
VarWrite() { this.isVarWrite() }
|
||||
|
||||
/**
|
||||
* Gets a source expression used in an assignment to this l-value.
|
||||
* Gets a source of the assignment that executes this variable write.
|
||||
*
|
||||
* For assignments using the `=` operator, the source expression
|
||||
* is simply the RHS of the assignment.
|
||||
*
|
||||
* Note that for l-values occurring on the LHS of compound assignment operators
|
||||
* Note that for writes occurring on the LHS of compound assignment operators
|
||||
* (such as (`+=`), both the RHS and the LHS of the compound assignment
|
||||
* are source expressions of the assignment.
|
||||
*/
|
||||
Expr getRhs() { exists(Assignment e | e.getDest() = this and e.getSource() = result) }
|
||||
Expr getASource() { exists(Assignment e | e.getDest() = this and e.getSource() = result) }
|
||||
|
||||
/** DEPRECATED: (Inaccurately-named) alias for `getASource` */
|
||||
deprecated Expr getRhs() { result = this.getASource() }
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for `VarWrite`. */
|
||||
deprecated class LValue = VarWrite;
|
||||
|
||||
/**
|
||||
* An r-value is a read access to a variable.
|
||||
* A read access to a variable.
|
||||
*
|
||||
* In other words, it is a variable access that does _not_ occur as the destination of
|
||||
* a simple assignment, but it may occur as the destination of a compound assignment
|
||||
* or a unary assignment.
|
||||
*/
|
||||
class RValue extends VarAccess {
|
||||
RValue() { this.isRValue() }
|
||||
class VarRead extends VarAccess {
|
||||
VarRead() { this.isVarRead() }
|
||||
}
|
||||
|
||||
/** A method access is an invocation of a method with a list of arguments. */
|
||||
class MethodAccess extends Expr, Call, @methodaccess {
|
||||
/** DEPRECATED: Alias for `VarRead`. */
|
||||
deprecated class RValue = VarRead;
|
||||
|
||||
/** A method call is an invocation of a method with a list of arguments. */
|
||||
class MethodCall extends Expr, Call, @methodaccess {
|
||||
/** Gets the qualifying expression of this method access, if any. */
|
||||
override Expr getQualifier() { result.isNthChildOf(this, -1) }
|
||||
|
||||
@@ -1909,21 +1934,30 @@ class MethodAccess extends Expr, Call, @methodaccess {
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if this is a method access to an instance method of `this`. That is,
|
||||
* Holds if this is a method call to an instance method of `this`. That is,
|
||||
* the qualifier is either an explicit or implicit unqualified `this` or `super`.
|
||||
*/
|
||||
predicate isOwnMethodAccess() { Qualifier::ownMemberAccess(this) }
|
||||
predicate isOwnMethodCall() { Qualifier::ownMemberAccess(this) }
|
||||
|
||||
/** DEPRECATED: Alias for `isOwnMethodCall`. */
|
||||
deprecated predicate isOwnMethodAccess() { this.isOwnMethodCall() }
|
||||
|
||||
/**
|
||||
* Holds if this is a method access to an instance method of the enclosing
|
||||
* Holds if this is a method call to an instance method of the enclosing
|
||||
* class `t`. That is, the qualifier is either an explicit or implicit
|
||||
* `t`-qualified `this` or `super`.
|
||||
*/
|
||||
predicate isEnclosingMethodAccess(RefType t) { Qualifier::enclosingMemberAccess(this, t) }
|
||||
predicate isEnclosingMethodCall(RefType t) { Qualifier::enclosingMemberAccess(this, t) }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "MethodAccess" }
|
||||
/** DEPRECATED: Alias for `isEnclosingMethodCall`. */
|
||||
deprecated predicate isEnclosingMethodAccess(RefType t) { this.isEnclosingMethodCall(t) }
|
||||
|
||||
override string getAPrimaryQlClass() { result = "MethodCall" }
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for `MethodCall`. */
|
||||
deprecated class MethodAccess = MethodCall;
|
||||
|
||||
/** A type access is a (possibly qualified) reference to a type. */
|
||||
class TypeAccess extends Expr, Annotatable, @typeaccess {
|
||||
/** Gets the qualifier of this type access, if any. */
|
||||
@@ -2085,23 +2119,32 @@ class Call extends ExprParent, @caller {
|
||||
}
|
||||
|
||||
/** A polymorphic call to an instance method. */
|
||||
class VirtualMethodAccess extends MethodAccess {
|
||||
VirtualMethodAccess() {
|
||||
class VirtualMethodCall extends MethodCall {
|
||||
VirtualMethodCall() {
|
||||
this.getMethod().isVirtual() and
|
||||
not this.getQualifier() instanceof SuperAccess
|
||||
}
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for `VirtualMethodCall`. */
|
||||
deprecated class VirtualMethodAccess = VirtualMethodCall;
|
||||
|
||||
/** A static method call. */
|
||||
class StaticMethodAccess extends MethodAccess {
|
||||
StaticMethodAccess() { this.getMethod().isStatic() }
|
||||
class StaticMethodCall extends MethodCall {
|
||||
StaticMethodCall() { this.getMethod().isStatic() }
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for `StaticMethodCall`. */
|
||||
deprecated class StaticMethodAccess = StaticMethodCall;
|
||||
|
||||
/** A call to a method in the superclass. */
|
||||
class SuperMethodAccess extends MethodAccess {
|
||||
SuperMethodAccess() { this.getQualifier() instanceof SuperAccess }
|
||||
class SuperMethodCall extends MethodCall {
|
||||
SuperMethodCall() { this.getQualifier() instanceof SuperAccess }
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for `SuperMethodCall`. */
|
||||
deprecated class SuperMethodAccess = SuperMethodCall;
|
||||
|
||||
/**
|
||||
* A constructor call, which occurs either as a constructor invocation inside a
|
||||
* constructor, or as part of a class instance expression.
|
||||
@@ -2150,23 +2193,23 @@ private module Qualifier {
|
||||
TThis() or
|
||||
TEnclosing(RefType t)
|
||||
|
||||
/** An expression that accesses a member. That is, either a `FieldAccess` or a `MethodAccess`. */
|
||||
/** An expression that accesses a member. That is, either a `FieldAccess` or a `MethodCall`. */
|
||||
class MemberAccess extends Expr {
|
||||
MemberAccess() {
|
||||
this instanceof FieldAccess or
|
||||
this instanceof MethodAccess
|
||||
this instanceof MethodCall
|
||||
}
|
||||
|
||||
/** Gets the member accessed by this member access. */
|
||||
Member getMember() {
|
||||
result = this.(FieldAccess).getField() or
|
||||
result = this.(MethodAccess).getMethod()
|
||||
result = this.(MethodCall).getMethod()
|
||||
}
|
||||
|
||||
/** Gets the qualifier of this member access, if any. */
|
||||
Expr getQualifier() {
|
||||
result = this.(FieldAccess).getQualifier() or
|
||||
result = this.(MethodAccess).getQualifier()
|
||||
result = this.(MethodCall).getQualifier()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2236,10 +2279,10 @@ private module Qualifier {
|
||||
}
|
||||
|
||||
/** An expression that assigns a value to a field. */
|
||||
class FieldWrite extends FieldAccess, LValue { }
|
||||
class FieldWrite extends FieldAccess, VarWrite { }
|
||||
|
||||
/** An expression that reads a field. */
|
||||
class FieldRead extends FieldAccess, RValue { }
|
||||
class FieldRead extends FieldAccess, VarRead { }
|
||||
|
||||
private predicate hasInstantiation(RefType t) {
|
||||
t instanceof TypeVariable or
|
||||
|
||||
@@ -479,7 +479,7 @@ class GenericCall extends Call {
|
||||
}
|
||||
|
||||
private RefType getAnExplicitTypeArgument(TypeVariable v) {
|
||||
exists(GenericCallable gen, MethodAccess call, int i |
|
||||
exists(GenericCallable gen, MethodCall call, int i |
|
||||
this = call and
|
||||
gen = call.getCallee() and
|
||||
v = gen.getTypeParameter(i) and
|
||||
|
||||
@@ -259,10 +259,10 @@ class MethodSystemGetProperty extends ValuePreservingMethod {
|
||||
}
|
||||
|
||||
/**
|
||||
* An access to a method named `getProperty` on class `java.lang.System`.
|
||||
* A call to a method named `getProperty` on class `java.lang.System`.
|
||||
*/
|
||||
class MethodAccessSystemGetProperty extends MethodAccess {
|
||||
MethodAccessSystemGetProperty() { this.getMethod() instanceof MethodSystemGetProperty }
|
||||
class MethodCallSystemGetProperty extends MethodCall {
|
||||
MethodCallSystemGetProperty() { this.getMethod() instanceof MethodSystemGetProperty }
|
||||
|
||||
/**
|
||||
* Holds if this call has a compile-time constant first argument with the value `propertyName`.
|
||||
@@ -276,6 +276,9 @@ class MethodAccessSystemGetProperty extends MethodAccess {
|
||||
}
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for `MethodCallSystemGetProperty`. */
|
||||
deprecated class MethodAccessSystemGetProperty = MethodCallSystemGetProperty;
|
||||
|
||||
/**
|
||||
* Any method named `exit` on class `java.lang.Runtime` or `java.lang.System`.
|
||||
*/
|
||||
|
||||
@@ -39,7 +39,7 @@ class RegisteredManagedBeanImpl extends Class {
|
||||
/**
|
||||
* A call that registers an object with the `MBeanServer`, directly or indirectly.
|
||||
*/
|
||||
class JmxRegistrationCall extends MethodAccess {
|
||||
class JmxRegistrationCall extends MethodCall {
|
||||
JmxRegistrationCall() { this.getCallee() instanceof JmxRegistrationMethod }
|
||||
|
||||
/**
|
||||
|
||||
@@ -49,7 +49,7 @@ class MapSizeMethod extends MapMethod {
|
||||
}
|
||||
|
||||
/** A method call that mutates a map. */
|
||||
class MapMutation extends MethodAccess {
|
||||
class MapMutation extends MethodCall {
|
||||
MapMutation() { this.getMethod() instanceof MapMutator }
|
||||
|
||||
/** Holds if the result of this call is not immediately discarded. */
|
||||
@@ -76,7 +76,7 @@ class FreshMap extends ClassInstanceExpr {
|
||||
/**
|
||||
* A call to `Map.put(key, value)`.
|
||||
*/
|
||||
class MapPutCall extends MethodAccess {
|
||||
class MapPutCall extends MethodCall {
|
||||
MapPutCall() { this.getCallee().(MapMethod).hasName("put") }
|
||||
|
||||
/** Gets the key argument of this call. */
|
||||
|
||||
@@ -129,7 +129,7 @@ class Callable extends StmtParent, Member, @callable {
|
||||
* Holds if this callable calls `target`
|
||||
* using a `super` method call.
|
||||
*/
|
||||
predicate callsSuper(Method target) { this.getACallSite(target) instanceof SuperMethodAccess }
|
||||
predicate callsSuper(Method target) { this.getACallSite(target) instanceof SuperMethodCall }
|
||||
|
||||
/**
|
||||
* Holds if this callable calls `c` using
|
||||
@@ -161,13 +161,13 @@ class Callable extends StmtParent, Member, @callable {
|
||||
* Holds if field `f` may be assigned a value
|
||||
* within the body of this callable.
|
||||
*/
|
||||
predicate writes(Field f) { f.getAnAccess().(LValue).getEnclosingCallable() = this }
|
||||
predicate writes(Field f) { f.getAnAccess().(VarWrite).getEnclosingCallable() = this }
|
||||
|
||||
/**
|
||||
* Holds if field `f` may be read
|
||||
* within the body of this callable.
|
||||
*/
|
||||
predicate reads(Field f) { f.getAnAccess().(RValue).getEnclosingCallable() = this }
|
||||
predicate reads(Field f) { f.getAnAccess().(VarRead).getEnclosingCallable() = this }
|
||||
|
||||
/**
|
||||
* Holds if field `f` may be either read or written
|
||||
@@ -526,7 +526,7 @@ class Method extends Callable, @method {
|
||||
this.getSourceDeclaration().getAPossibleImplementationOfSrcMethod() = result
|
||||
}
|
||||
|
||||
override MethodAccess getAReference() { result = Callable.super.getAReference() }
|
||||
override MethodCall getAReference() { result = Callable.super.getAReference() }
|
||||
|
||||
override predicate isPublic() {
|
||||
Callable.super.isPublic()
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
import java
|
||||
|
||||
/** A call to a string to number conversion. */
|
||||
private class SpecialMethodAccess extends MethodAccess {
|
||||
private class SpecialMethodCall extends MethodCall {
|
||||
predicate isValueOfMethod(string klass) {
|
||||
this.getMethod().getName() = "valueOf" and
|
||||
this.getQualifier().getType().(RefType).hasQualifiedName("java.lang", klass) and
|
||||
@@ -78,7 +78,7 @@ deprecated predicate catchesNFE = catchesNfe/1;
|
||||
|
||||
/** Holds if `java.lang.NumberFormatException` can be thrown. */
|
||||
predicate throwsNfe(Expr e) {
|
||||
e.(SpecialClassInstanceExpr).throwsNfe() or e.(SpecialMethodAccess).throwsNfe()
|
||||
e.(SpecialClassInstanceExpr).throwsNfe() or e.(SpecialMethodCall).throwsNfe()
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for throwsNfe */
|
||||
|
||||
@@ -300,7 +300,7 @@ private class PpCall extends PpAst, Call {
|
||||
or
|
||||
i = 2 and
|
||||
(
|
||||
result = this.(MethodAccess).getMethod().getName()
|
||||
result = this.(MethodCall).getMethod().getName()
|
||||
or
|
||||
result = "this" and this instanceof ThisConstructorInvocationStmt
|
||||
or
|
||||
|
||||
@@ -62,8 +62,8 @@ private class ReflectiveClassIdentifierLiteral extends ReflectiveClassIdentifier
|
||||
/**
|
||||
* A call to a Java standard library method which constructs or returns a `Class<T>` from a `String`.
|
||||
*/
|
||||
class ReflectiveClassIdentifierMethodAccess extends ReflectiveClassIdentifier, MethodAccess {
|
||||
ReflectiveClassIdentifierMethodAccess() {
|
||||
class ReflectiveClassIdentifierMethodCall extends ReflectiveClassIdentifier, MethodCall {
|
||||
ReflectiveClassIdentifierMethodCall() {
|
||||
// A call to `Class.forName(...)`, from which we can infer `T` in the returned type `Class<T>`.
|
||||
this.getCallee().getDeclaringType() instanceof TypeClass and this.getCallee().hasName("forName")
|
||||
or
|
||||
@@ -83,6 +83,9 @@ class ReflectiveClassIdentifierMethodAccess extends ReflectiveClassIdentifier, M
|
||||
}
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for `ReflectiveClassIdentifierMethodCall`. */
|
||||
deprecated class ReflectiveClassIdentifierMethodAccess = ReflectiveClassIdentifierMethodCall;
|
||||
|
||||
/**
|
||||
* Gets a `ReflectiveClassIdentifier` that we believe may represent the value of `expr`.
|
||||
*/
|
||||
@@ -92,7 +95,7 @@ private ReflectiveClassIdentifier pointsToReflectiveClassIdentifier(Expr expr) {
|
||||
or
|
||||
// Or if this is an access of a variable which was defined as an expression creating a `Class<T>`,
|
||||
// return the inferred `T` from the definition expression.
|
||||
exists(RValue use, VariableAssign assign |
|
||||
exists(VarRead use, VariableAssign assign |
|
||||
use = expr and
|
||||
defUsePair(assign, use) and
|
||||
// The source of the assignment must be a `ReflectiveClassIdentifier`.
|
||||
@@ -211,7 +214,7 @@ private predicate expectsEnclosingInstance(RefType r) {
|
||||
/**
|
||||
* A call to `Class.newInstance()` or `Constructor.newInstance()`.
|
||||
*/
|
||||
class NewInstance extends MethodAccess {
|
||||
class NewInstance extends MethodCall {
|
||||
NewInstance() {
|
||||
(
|
||||
this.getCallee().getDeclaringType() instanceof TypeClass or
|
||||
@@ -301,10 +304,10 @@ class NewInstance extends MethodAccess {
|
||||
}
|
||||
|
||||
/**
|
||||
* A `MethodAccess` on a `Class` element.
|
||||
* A `MethodCall` on a `Class` instance.
|
||||
*/
|
||||
class ClassMethodAccess extends MethodAccess {
|
||||
ClassMethodAccess() { this.getCallee().getDeclaringType() instanceof TypeClass }
|
||||
class ClassMethodCall extends MethodCall {
|
||||
ClassMethodCall() { this.getCallee().getDeclaringType() instanceof TypeClass }
|
||||
|
||||
/**
|
||||
* Gets an inferred type for the `Class` represented by this expression.
|
||||
@@ -317,31 +320,40 @@ class ClassMethodAccess extends MethodAccess {
|
||||
}
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for `ClassMethodCall`. */
|
||||
deprecated class ClassMethodAccess = ClassMethodCall;
|
||||
|
||||
/**
|
||||
* A call to `Class.getConstructors(..)` or `Class.getDeclaredConstructors(..)`.
|
||||
*/
|
||||
class ReflectiveConstructorsAccess extends ClassMethodAccess {
|
||||
ReflectiveConstructorsAccess() {
|
||||
class ReflectiveGetConstructorsCall extends ClassMethodCall {
|
||||
ReflectiveGetConstructorsCall() {
|
||||
this.getCallee().hasName("getConstructors") or
|
||||
this.getCallee().hasName("getDeclaredConstructors")
|
||||
}
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for `ReflectiveGetConstructorsCall`. */
|
||||
deprecated class ReflectiveConstructorsAccess = ReflectiveGetConstructorsCall;
|
||||
|
||||
/**
|
||||
* A call to `Class.getMethods(..)` or `Class.getDeclaredMethods(..)`.
|
||||
*/
|
||||
class ReflectiveMethodsAccess extends ClassMethodAccess {
|
||||
ReflectiveMethodsAccess() {
|
||||
class ReflectiveGetMethodsCall extends ClassMethodCall {
|
||||
ReflectiveGetMethodsCall() {
|
||||
this.getCallee().hasName("getMethods") or
|
||||
this.getCallee().hasName("getDeclaredMethods")
|
||||
}
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for `ReflectiveGetMethodsCall`. */
|
||||
deprecated class ReflectiveMethodsAccess = ReflectiveGetMethodsCall;
|
||||
|
||||
/**
|
||||
* A call to `Class.getMethod(..)` or `Class.getDeclaredMethod(..)`.
|
||||
*/
|
||||
class ReflectiveMethodAccess extends ClassMethodAccess {
|
||||
ReflectiveMethodAccess() {
|
||||
class ReflectiveGetMethodCall extends ClassMethodCall {
|
||||
ReflectiveGetMethodCall() {
|
||||
this.getCallee().hasName("getMethod") or
|
||||
this.getCallee().hasName("getDeclaredMethod")
|
||||
}
|
||||
@@ -366,11 +378,14 @@ class ReflectiveMethodAccess extends ClassMethodAccess {
|
||||
}
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for `ReflectiveGetMethodCall`. */
|
||||
deprecated class ReflectiveMethodAccess = ReflectiveGetMethodCall;
|
||||
|
||||
/**
|
||||
* A call to `Class.getAnnotation(..)`.
|
||||
*/
|
||||
class ReflectiveAnnotationAccess extends ClassMethodAccess {
|
||||
ReflectiveAnnotationAccess() { this.getCallee().hasName("getAnnotation") }
|
||||
class ReflectiveGetAnnotationCall extends ClassMethodCall {
|
||||
ReflectiveGetAnnotationCall() { this.getCallee().hasName("getAnnotation") }
|
||||
|
||||
/**
|
||||
* Gets a possible annotation type for this reflective annotation access.
|
||||
@@ -380,11 +395,14 @@ class ReflectiveAnnotationAccess extends ClassMethodAccess {
|
||||
}
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for `ReflectiveGetAnnotationCall`. */
|
||||
deprecated class ReflectiveAnnotationAccess = ReflectiveGetAnnotationCall;
|
||||
|
||||
/**
|
||||
* A call to `Class.getField(..)` that accesses a field.
|
||||
*/
|
||||
class ReflectiveFieldAccess extends ClassMethodAccess {
|
||||
ReflectiveFieldAccess() {
|
||||
class ReflectiveGetFieldCall extends ClassMethodCall {
|
||||
ReflectiveGetFieldCall() {
|
||||
this.getCallee().hasName("getField") or
|
||||
this.getCallee().hasName("getDeclaredField")
|
||||
}
|
||||
@@ -405,3 +423,6 @@ class ReflectiveFieldAccess extends ClassMethodAccess {
|
||||
result.hasName(this.getArgument(0).(StringLiteral).getValue())
|
||||
}
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for `ReflectiveGetFieldCall`. */
|
||||
deprecated class ReflectiveFieldAccess = ReflectiveGetFieldCall;
|
||||
|
||||
@@ -242,7 +242,7 @@ predicate implicitToStringCall(Expr e) {
|
||||
or
|
||||
exists(AddExpr add | add.getType() instanceof TypeString and add.getAnOperand() = e)
|
||||
or
|
||||
exists(MethodAccess ma, Method m, int i |
|
||||
exists(MethodCall ma, Method m, int i |
|
||||
ma.getMethod() = m and
|
||||
ma.getArgument(i) = e and
|
||||
printMethod(m, i)
|
||||
@@ -253,7 +253,7 @@ predicate implicitToStringCall(Expr e) {
|
||||
/**
|
||||
* A call to a `format` or `printf` method.
|
||||
*/
|
||||
class StringFormat extends MethodAccess, FormattingCall {
|
||||
class StringFormat extends MethodCall, FormattingCall {
|
||||
StringFormat() { this.getCallee() instanceof StringFormatMethod }
|
||||
}
|
||||
|
||||
|
||||
@@ -1090,6 +1090,24 @@ class PrimitiveType extends Type, @primitive {
|
||||
override string getAPrimaryQlClass() { result = "PrimitiveType" }
|
||||
}
|
||||
|
||||
private int getByteSize(PrimitiveType t) {
|
||||
t.hasName("boolean") and result = 1
|
||||
or
|
||||
t.hasName("byte") and result = 1
|
||||
or
|
||||
t.hasName("char") and result = 2
|
||||
or
|
||||
t.hasName("short") and result = 2
|
||||
or
|
||||
t.hasName("int") and result = 4
|
||||
or
|
||||
t.hasName("float") and result = 4
|
||||
or
|
||||
t.hasName("long") and result = 8
|
||||
or
|
||||
t.hasName("double") and result = 8
|
||||
}
|
||||
|
||||
/** The type of the `null` literal. */
|
||||
class NullType extends Type, @primitive {
|
||||
NullType() { this.hasName("<nulltype>") }
|
||||
@@ -1282,6 +1300,12 @@ class IntegralType extends Type {
|
||||
name = ["byte", "char", "short", "int", "long"]
|
||||
)
|
||||
}
|
||||
|
||||
/** Gets the size in bytes of this numeric type. */
|
||||
final int getByteSize() {
|
||||
result = getByteSize(this) or
|
||||
result = getByteSize(this.(BoxedType).getPrimitiveType())
|
||||
}
|
||||
}
|
||||
|
||||
/** A boolean type, which may be either a primitive or a boxed type. */
|
||||
|
||||
@@ -187,14 +187,14 @@ private predicate switchCaseControls(SwitchCase sc, BasicBlock bb) {
|
||||
}
|
||||
|
||||
private predicate preconditionBranchEdge(
|
||||
MethodAccess ma, BasicBlock bb1, BasicBlock bb2, boolean branch
|
||||
MethodCall ma, BasicBlock bb1, BasicBlock bb2, boolean branch
|
||||
) {
|
||||
conditionCheckArgument(ma, _, branch) and
|
||||
bb1.getLastNode() = ma.getControlFlowNode() and
|
||||
bb2 = bb1.getLastNode().getANormalSuccessor()
|
||||
}
|
||||
|
||||
private predicate preconditionControls(MethodAccess ma, BasicBlock controlled, boolean branch) {
|
||||
private predicate preconditionControls(MethodCall ma, BasicBlock controlled, boolean branch) {
|
||||
exists(BasicBlock check, BasicBlock succ |
|
||||
preconditionBranchEdge(ma, check, succ, branch) and
|
||||
dominatingEdge(check, succ) and
|
||||
@@ -249,7 +249,7 @@ private predicate equalityGuard(Guard g, Expr e1, Expr e2, boolean polarity) {
|
||||
eqtest.hasOperands(e1, e2)
|
||||
)
|
||||
or
|
||||
exists(MethodAccess ma |
|
||||
exists(MethodCall ma |
|
||||
ma = g and
|
||||
ma.getMethod() instanceof EqualsMethod and
|
||||
polarity = true and
|
||||
@@ -257,7 +257,7 @@ private predicate equalityGuard(Guard g, Expr e1, Expr e2, boolean polarity) {
|
||||
ma.getQualifier() = e2
|
||||
)
|
||||
or
|
||||
exists(MethodAccess ma, Method equals |
|
||||
exists(MethodCall ma, Method equals |
|
||||
ma = g and
|
||||
ma.getMethod() = equals and
|
||||
polarity = true and
|
||||
|
||||
@@ -59,7 +59,7 @@ predicate implies_v1(Guard g1, boolean b1, Guard g2, boolean b2) {
|
||||
or
|
||||
g1.(DefaultCase).getSwitchExpr().getAConstCase() = g2 and b1 = true and b2 = false
|
||||
or
|
||||
exists(MethodAccess check, int argIndex | check = g1 |
|
||||
exists(MethodCall check, int argIndex | check = g1 |
|
||||
conditionCheckArgument(check, argIndex, _) and
|
||||
g2 = check.getArgument(argIndex) and
|
||||
b1 = [true, false] and
|
||||
|
||||
@@ -17,7 +17,7 @@ predicate conditionCheckMethodArgument(Method m, int argument, boolean checkTrue
|
||||
or
|
||||
condtionCheckMethodTestingFramework(m, argument, checkTrue)
|
||||
or
|
||||
exists(Parameter p, MethodAccess ma, int argIndex, boolean ct, Expr arg |
|
||||
exists(Parameter p, MethodCall ma, int argIndex, boolean ct, Expr arg |
|
||||
p = m.getParameter(argument) and
|
||||
not m.isOverridable() and
|
||||
m.getBody().getStmt(0).(ExprStmt).getExpr() = ma and
|
||||
@@ -100,6 +100,6 @@ private predicate condtionCheckMethodTestingFramework(Method m, int argument, bo
|
||||
* Holds if `ma` is an access to a non-overridable method that checks that its
|
||||
* zero-indexed `argument` is equal to `checkTrue` and throws otherwise.
|
||||
*/
|
||||
predicate conditionCheckArgument(MethodAccess ma, int argument, boolean checkTrue) {
|
||||
predicate conditionCheckArgument(MethodCall ma, int argument, boolean checkTrue) {
|
||||
conditionCheckMethodArgument(ma.getMethod().getSourceDeclaration(), argument, checkTrue)
|
||||
}
|
||||
|
||||
@@ -25,16 +25,8 @@ abstract class Bound extends TBound {
|
||||
/** Gets an expression that equals this bound. */
|
||||
Expr getExpr() { result = this.getExpr(0) }
|
||||
|
||||
/**
|
||||
* Holds if this element is at the specified location.
|
||||
* The location spans column `sc` of line `sl` to
|
||||
* column `ec` of line `el` in file `path`.
|
||||
* For more information, see
|
||||
* [Locations](https://codeql.github.com/docs/writing-codeql-queries/providing-locations-in-codeql-queries/).
|
||||
*/
|
||||
predicate hasLocationInfo(string path, int sl, int sc, int el, int ec) {
|
||||
path = "" and sl = 0 and sc = 0 and el = 0 and ec = 0
|
||||
}
|
||||
/** Gets the location of this bound. */
|
||||
abstract Location getLocation();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -45,6 +37,8 @@ class ZeroBound extends Bound, TBoundZero {
|
||||
override string toString() { result = "0" }
|
||||
|
||||
override Expr getExpr(int delta) { result.(ConstantIntegerExpr).getIntValue() = delta }
|
||||
|
||||
override Location getLocation() { result.hasLocationInfo("", 0, 0, 0, 0) }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -58,9 +52,7 @@ class SsaBound extends Bound, TBoundSsa {
|
||||
|
||||
override Expr getExpr(int delta) { result = this.getSsa().getAUse() and delta = 0 }
|
||||
|
||||
override predicate hasLocationInfo(string path, int sl, int sc, int el, int ec) {
|
||||
this.getSsa().getLocation().hasLocationInfo(path, sl, sc, el, ec)
|
||||
}
|
||||
override Location getLocation() { result = this.getSsa().getLocation() }
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -72,7 +64,5 @@ class ExprBound extends Bound, TBoundExpr {
|
||||
|
||||
override Expr getExpr(int delta) { this = TBoundExpr(result) and delta = 0 }
|
||||
|
||||
override predicate hasLocationInfo(string path, int sl, int sc, int el, int ec) {
|
||||
this.getExpr().getLocation().hasLocationInfo(path, sl, sc, el, ec)
|
||||
}
|
||||
override Location getLocation() { result = this.getExpr().getLocation() }
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ private import SSA
|
||||
*
|
||||
* This is the transitive closure of `adjacentUseUseSameVar`.
|
||||
*/
|
||||
predicate useUsePairSameVar(RValue use1, RValue use2) { adjacentUseUseSameVar+(use1, use2) }
|
||||
predicate useUsePairSameVar(VarRead use1, VarRead use2) { adjacentUseUseSameVar+(use1, use2) }
|
||||
|
||||
/**
|
||||
* Holds if `use1` and `use2` form a use-use-pair of the same
|
||||
@@ -23,7 +23,7 @@ predicate useUsePairSameVar(RValue use1, RValue use2) { adjacentUseUseSameVar+(u
|
||||
*
|
||||
* This is the transitive closure of `adjacentUseUse`.
|
||||
*/
|
||||
predicate useUsePair(RValue use1, RValue use2) { adjacentUseUse+(use1, use2) }
|
||||
predicate useUsePair(VarRead use1, VarRead use2) { adjacentUseUse+(use1, use2) }
|
||||
|
||||
/**
|
||||
* Holds if there exists a path from `def` to `use` without passing through another
|
||||
@@ -31,7 +31,7 @@ predicate useUsePair(RValue use1, RValue use2) { adjacentUseUse+(use1, use2) }
|
||||
*
|
||||
* Other paths may also exist, so the SSA variables in `def` and `use` can be different.
|
||||
*/
|
||||
predicate defUsePair(VariableUpdate def, RValue use) {
|
||||
predicate defUsePair(VariableUpdate def, VarRead use) {
|
||||
exists(SsaVariable v |
|
||||
v.getAUse() = use and v.getAnUltimateDefinition().(SsaExplicitUpdate).getDefiningExpr() = def
|
||||
)
|
||||
@@ -43,7 +43,7 @@ predicate defUsePair(VariableUpdate def, RValue use) {
|
||||
*
|
||||
* Other paths may also exist, so the SSA variables can be different.
|
||||
*/
|
||||
predicate parameterDefUsePair(Parameter p, RValue use) {
|
||||
predicate parameterDefUsePair(Parameter p, VarRead use) {
|
||||
exists(SsaVariable v |
|
||||
v.getAUse() = use and v.getAnUltimateDefinition().(SsaImplicitInit).isParameterDefinition(p)
|
||||
)
|
||||
|
||||
@@ -122,9 +122,9 @@ private predicate variableStep(Expr tracked, VarAccess sink) {
|
||||
private class ReverseDnsSource extends RemoteFlowSource {
|
||||
ReverseDnsSource() {
|
||||
// Try not to trigger on `localhost`.
|
||||
exists(MethodAccess m | m = this.asExpr() |
|
||||
exists(MethodCall m | m = this.asExpr() |
|
||||
m.getMethod() instanceof ReverseDnsMethod and
|
||||
not exists(MethodAccess l |
|
||||
not exists(MethodCall l |
|
||||
(variableStep(l, m.getQualifier()) or l = m.getQualifier()) and
|
||||
l.getMethod().getName() = "getLocalHost"
|
||||
)
|
||||
@@ -321,7 +321,7 @@ class AndroidIntentInput extends DataFlow::Node {
|
||||
Type receiverType;
|
||||
|
||||
AndroidIntentInput() {
|
||||
exists(MethodAccess ma, AndroidGetIntentMethod m |
|
||||
exists(MethodCall ma, AndroidGetIntentMethod m |
|
||||
ma.getMethod().overrides*(m) and
|
||||
this.asExpr() = ma and
|
||||
receiverType = ma.getReceiverType()
|
||||
|
||||
@@ -58,9 +58,7 @@ private predicate implicitEnclosingThisCopy(ConstructorCall cc, RefType t1, RefT
|
||||
private predicate enclosingInstanceAccess(ExprParent e, RefType t) {
|
||||
e.(InstanceAccess).isEnclosingInstanceAccess(t)
|
||||
or
|
||||
exists(MethodAccess ma |
|
||||
ma.isEnclosingMethodAccess(t) and ma = e and not exists(ma.getQualifier())
|
||||
)
|
||||
exists(MethodCall ma | ma.isEnclosingMethodCall(t) and ma = e and not exists(ma.getQualifier()))
|
||||
or
|
||||
exists(FieldAccess fa | fa.isEnclosingFieldAccess(t) and fa = e and not exists(fa.getQualifier()))
|
||||
or
|
||||
@@ -95,7 +93,7 @@ private newtype TInstanceAccessExt =
|
||||
or
|
||||
c instanceof SuperConstructorInvocationStmt
|
||||
or
|
||||
c.(MethodAccess).isOwnMethodAccess() and not exists(c.getQualifier())
|
||||
c.(MethodCall).isOwnMethodCall() and not exists(c.getQualifier())
|
||||
} or
|
||||
TThisEnclosingInstanceCapture(ConstructorCall cc) { implicitSetEnclosingInstanceToThis(cc) } or
|
||||
TEnclosingInstanceAccess(ExprParent e, RefType t) {
|
||||
@@ -113,7 +111,7 @@ private newtype TInstanceAccessExt =
|
||||
* - Implicit field qualifier: The implicit access associated with an
|
||||
* unqualified `FieldAccess` to a non-static field.
|
||||
* - Implicit method qualifier: The implicit access associated with an
|
||||
* unqualified `MethodAccess` to a non-static method.
|
||||
* unqualified `MethodCall` to a non-static method.
|
||||
* - Implicit this constructor argument: The implicit argument of the value of
|
||||
* `this` to a constructor call of the form `this()` or `super()`.
|
||||
* - Implicit enclosing instance capture: The implicit capture of the value of
|
||||
@@ -180,7 +178,7 @@ class InstanceAccessExt extends TInstanceAccessExt {
|
||||
}
|
||||
|
||||
/** Holds if this is the implicit qualifier of `ma`. */
|
||||
predicate isImplicitMethodQualifier(MethodAccess ma) {
|
||||
predicate isImplicitMethodQualifier(MethodCall ma) {
|
||||
this = TThisArgument(ma) or
|
||||
this = TEnclosingInstanceAccess(ma, _)
|
||||
}
|
||||
@@ -234,7 +232,7 @@ class InstanceAccessExt extends TInstanceAccessExt {
|
||||
e instanceof InstanceAccess and result = e
|
||||
or
|
||||
exists(FieldAccess fa | fa = e |
|
||||
if fa instanceof RValue then fa = result else result.(AssignExpr).getDest() = fa
|
||||
if fa instanceof VarRead then fa = result else result.(AssignExpr).getDest() = fa
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -15,10 +15,10 @@ private Expr exprWithIntValue(int i) {
|
||||
|
||||
/**
|
||||
* An expression for which the predicate `integerGuard` is relevant.
|
||||
* This includes `RValue` and `MethodAccess`.
|
||||
* This includes `VarRead` and `MethodCall`.
|
||||
*/
|
||||
class IntComparableExpr extends Expr {
|
||||
IntComparableExpr() { this instanceof RValue or this instanceof MethodAccess }
|
||||
IntComparableExpr() { this instanceof VarRead or this instanceof MethodCall }
|
||||
|
||||
/** Gets an integer that is directly assigned to the expression in case of a variable; or zero. */
|
||||
int relevantInt() {
|
||||
@@ -132,7 +132,7 @@ Expr integerGuard(IntComparableExpr e, boolean branch, int k, boolean is_k) {
|
||||
* If `branch_with_lower_bound_k` is true then `result` is equivalent to `k <= x`
|
||||
* and if it is false then `result` is equivalent to `k > x`.
|
||||
*/
|
||||
Expr intBoundGuard(RValue x, boolean branch_with_lower_bound_k, int k) {
|
||||
Expr intBoundGuard(VarRead x, boolean branch_with_lower_bound_k, int k) {
|
||||
exists(ComparisonExpr comp, ConstantIntegerExpr c, int val |
|
||||
comp = result and
|
||||
comp.hasOperands(x, c) and
|
||||
|
||||
@@ -79,7 +79,7 @@ Expr clearlyNotNullExpr(Expr reason) {
|
||||
(reason = r1 or reason = r2)
|
||||
)
|
||||
or
|
||||
exists(SsaVariable v, boolean branch, RValue rval, Guard guard |
|
||||
exists(SsaVariable v, boolean branch, VarRead rval, Guard guard |
|
||||
guard = directNullGuard(v, branch, false) and
|
||||
guard.controls(rval.getBasicBlock(), branch) and
|
||||
reason = guard and
|
||||
@@ -89,7 +89,7 @@ Expr clearlyNotNullExpr(Expr reason) {
|
||||
or
|
||||
exists(SsaVariable v | clearlyNotNull(v, reason) and result = v.getAUse())
|
||||
or
|
||||
exists(Method m | m = result.(MethodAccess).getMethod() and reason = result |
|
||||
exists(Method m | m = result.(MethodCall).getMethod() and reason = result |
|
||||
m.getDeclaringType().hasQualifiedName("com.google.common.base", "Strings") and
|
||||
m.hasName("nullToEmpty")
|
||||
)
|
||||
@@ -187,7 +187,7 @@ Expr basicNullGuard(Expr e, boolean branch, boolean isnull) {
|
||||
or
|
||||
result.(InstanceOfExpr).getExpr() = e and branch = true and isnull = false
|
||||
or
|
||||
exists(MethodAccess call |
|
||||
exists(MethodCall call |
|
||||
call = result and
|
||||
call.getAnArgument() = e and
|
||||
nullCheckMethod(call.getMethod(), branch, isnull)
|
||||
@@ -212,7 +212,7 @@ Expr basicNullGuard(Expr e, boolean branch, boolean isnull) {
|
||||
Expr basicOrCustomNullGuard(Expr e, boolean branch, boolean isnull) {
|
||||
result = basicNullGuard(e, branch, isnull)
|
||||
or
|
||||
exists(MethodAccess call, Method m, int ix |
|
||||
exists(MethodCall call, Method m, int ix |
|
||||
call = result and
|
||||
call.getArgument(ix) = e and
|
||||
call.getMethod().getSourceDeclaration() = m and
|
||||
|
||||
@@ -106,7 +106,7 @@ predicate dereference(Expr e) {
|
||||
or
|
||||
exists(FieldAccess fa, Field f | fa.getQualifier() = e and fa.getField() = f and not f.isStatic())
|
||||
or
|
||||
exists(MethodAccess ma, Method m |
|
||||
exists(MethodCall ma, Method m |
|
||||
ma.getQualifier() = e and ma.getMethod() = m and not m.isStatic()
|
||||
)
|
||||
or
|
||||
@@ -149,10 +149,10 @@ private ControlFlowNode ensureNotNull(SsaVariable v) {
|
||||
or
|
||||
exists(AssertNotNullMethod m | result = m.getACheck(v.getAUse()))
|
||||
or
|
||||
exists(AssertThatMethod m, MethodAccess ma |
|
||||
exists(AssertThatMethod m, MethodCall ma |
|
||||
result = m.getACheck(v.getAUse()) and ma.getControlFlowNode() = result
|
||||
|
|
||||
ma.getAnArgument().(MethodAccess).getMethod().getName() = "notNullValue"
|
||||
ma.getAnArgument().(MethodCall).getMethod().getName() = "notNullValue"
|
||||
)
|
||||
}
|
||||
|
||||
@@ -195,7 +195,7 @@ private predicate varMaybeNull(SsaVariable v, string msg, Expr reason) {
|
||||
not exists(TryStmt try | try.getFinally() = e.getEnclosingStmt().getEnclosingStmt*()) and
|
||||
(
|
||||
e = any(ConditionalExpr c).getCondition().getAChildExpr*() or
|
||||
not exists(MethodAccess ma | ma.getAnArgument().getAChildExpr*() = e)
|
||||
not exists(MethodCall ma | ma.getAnArgument().getAChildExpr*() = e)
|
||||
) and
|
||||
// Don't use a guard as reason if there is a null assignment.
|
||||
not v.(SsaExplicitUpdate).getDefiningExpr().(VariableAssign).getSource() = nullExpr()
|
||||
@@ -250,7 +250,7 @@ private Expr nonEmptyExpr() {
|
||||
// ...it is guarded by a condition...
|
||||
cond.controls(result.getBasicBlock(), branch) and
|
||||
// ...and it isn't modified in the scope of the condition...
|
||||
forall(MethodAccess ma, Method m |
|
||||
forall(MethodCall ma, Method m |
|
||||
m = ma.getMethod() and
|
||||
ma.getQualifier() = v.getSourceVariable().getAnAccess() and
|
||||
cond.controls(ma.getBasicBlock(), branch)
|
||||
@@ -260,12 +260,12 @@ private Expr nonEmptyExpr() {
|
||||
cond.getCondition() = c
|
||||
|
|
||||
// ...and the condition proves that it is non-empty, either by using the `isEmpty` method...
|
||||
c.(MethodAccess).getMethod().hasName("isEmpty") and
|
||||
c.(MethodCall).getMethod().hasName("isEmpty") and
|
||||
branch = false and
|
||||
c.(MethodAccess).getQualifier() = v.getAUse()
|
||||
c.(MethodCall).getQualifier() = v.getAUse()
|
||||
or
|
||||
// ...or a check on its `size`.
|
||||
exists(MethodAccess size |
|
||||
exists(MethodCall size |
|
||||
c = integerGuard(size, branch, 0, false) and
|
||||
size.getMethod().hasName("size") and
|
||||
size.getQualifier() = v.getAUse()
|
||||
@@ -485,7 +485,7 @@ private predicate correlatedConditions(
|
||||
inverted = branch1.booleanXor(branch2)
|
||||
)
|
||||
or
|
||||
exists(SsaVariable v, RValue rv1, RValue rv2, int k, boolean branch1, boolean branch2 |
|
||||
exists(SsaVariable v, VarRead rv1, VarRead rv2, int k, boolean branch1, boolean branch2 |
|
||||
rv1 = v.getAUse() and
|
||||
rv2 = v.getAUse() and
|
||||
cond1.getCondition() = integerGuard(rv1, branch1, k, true) and
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -145,6 +145,9 @@ class ConstantStringExpr extends Expr {
|
||||
string getStringValue() { constantStringExpr(this, result) }
|
||||
}
|
||||
|
||||
bindingset[f]
|
||||
private predicate okInt(float f) { -2.pow(31) <= f and f <= 2.pow(31) - 1 }
|
||||
|
||||
/**
|
||||
* Gets an expression that equals `v - d`.
|
||||
*/
|
||||
@@ -153,14 +156,16 @@ Expr ssaRead(SsaVariable v, int delta) {
|
||||
or
|
||||
exists(int d1, ConstantIntegerExpr c |
|
||||
result.(AddExpr).hasOperands(ssaRead(v, d1), c) and
|
||||
delta = d1 - c.getIntValue()
|
||||
delta = d1 - c.getIntValue() and
|
||||
okInt(d1.(float) - c.getIntValue().(float))
|
||||
)
|
||||
or
|
||||
exists(SubExpr sub, int d1, ConstantIntegerExpr c |
|
||||
result = sub and
|
||||
sub.getLeftOperand() = ssaRead(v, d1) and
|
||||
sub.getRightOperand() = c and
|
||||
delta = d1 + c.getIntValue()
|
||||
delta = d1 + c.getIntValue() and
|
||||
okInt(d1.(float) + c.getIntValue().(float))
|
||||
)
|
||||
or
|
||||
v.(SsaExplicitUpdate).getDefiningExpr().(PreIncExpr) = result and delta = 0
|
||||
|
||||
@@ -275,7 +275,7 @@ private module SsaImpl {
|
||||
}
|
||||
|
||||
/** Holds if `VarAccess` `use` of `v` occurs in `b` at index `i`. */
|
||||
private predicate variableUse(TrackedVar v, RValue use, BasicBlock b, int i) {
|
||||
private predicate variableUse(TrackedVar v, VarRead use, BasicBlock b, int i) {
|
||||
v.getAnAccess() = use and b.getNode(i) = use
|
||||
}
|
||||
|
||||
@@ -381,7 +381,7 @@ private module SsaImpl {
|
||||
* ```
|
||||
*/
|
||||
private predicate intraInstanceCallEdge(Callable c1, Method m2) {
|
||||
exists(MethodAccess ma, RefType t1 |
|
||||
exists(MethodCall ma, RefType t1 |
|
||||
ma.getCaller() = c1 and
|
||||
m2 = viableImpl_v2(ma) and
|
||||
not m2.isStatic() and
|
||||
@@ -652,7 +652,7 @@ private module SsaImpl {
|
||||
* Holds if the SSA definition of `v` at `def` reaches `use` in the same basic block
|
||||
* without crossing another SSA definition of `v`.
|
||||
*/
|
||||
private predicate ssaDefReachesUseWithinBlock(TrackedVar v, TrackedSsaDef def, RValue use) {
|
||||
private predicate ssaDefReachesUseWithinBlock(TrackedVar v, TrackedSsaDef def, VarRead use) {
|
||||
exists(BasicBlock b, int rankix, int i |
|
||||
ssaDefReachesRank(v, def, b, rankix) and
|
||||
defUseRank(v, b, rankix, i) and
|
||||
@@ -665,7 +665,7 @@ private module SsaImpl {
|
||||
* SSA definition of `v`.
|
||||
*/
|
||||
cached
|
||||
predicate ssaDefReachesUse(TrackedVar v, TrackedSsaDef def, RValue use) {
|
||||
predicate ssaDefReachesUse(TrackedVar v, TrackedSsaDef def, VarRead use) {
|
||||
ssaDefReachesUseWithinBlock(v, def, use)
|
||||
or
|
||||
exists(BasicBlock b |
|
||||
@@ -813,7 +813,7 @@ private module SsaImpl {
|
||||
* any other uses, but possibly through phi nodes and uncertain implicit updates.
|
||||
*/
|
||||
cached
|
||||
predicate firstUse(TrackedSsaDef def, RValue use) {
|
||||
predicate firstUse(TrackedSsaDef def, VarRead use) {
|
||||
exists(TrackedVar v, BasicBlock b1, int i1, BasicBlock b2, int i2 |
|
||||
adjacentVarRefs(v, b1, i1, b2, i2) and
|
||||
def.definesAt(v, b1, i1) and
|
||||
@@ -838,7 +838,7 @@ private module SsaImpl {
|
||||
* through any other use or any SSA definition of the variable.
|
||||
*/
|
||||
cached
|
||||
predicate adjacentUseUseSameVar(RValue use1, RValue use2) {
|
||||
predicate adjacentUseUseSameVar(VarRead use1, VarRead use2) {
|
||||
exists(TrackedVar v, BasicBlock b1, int i1, BasicBlock b2, int i2 |
|
||||
adjacentVarRefs(v, b1, i1, b2, i2) and
|
||||
variableUse(v, use1, b1, i1) and
|
||||
@@ -853,7 +853,7 @@ private module SsaImpl {
|
||||
* except for phi nodes and uncertain implicit updates.
|
||||
*/
|
||||
cached
|
||||
predicate adjacentUseUse(RValue use1, RValue use2) {
|
||||
predicate adjacentUseUse(VarRead use1, VarRead use2) {
|
||||
adjacentUseUseSameVar(use1, use2)
|
||||
or
|
||||
exists(TrackedVar v, TrackedSsaDef def, BasicBlock b1, int i1, BasicBlock b2, int i2 |
|
||||
@@ -938,7 +938,7 @@ class SsaVariable extends TSsaVariable {
|
||||
BasicBlock getBasicBlock() { result = this.getCfgNode().getBasicBlock() }
|
||||
|
||||
/** Gets an access of this SSA variable. */
|
||||
RValue getAUse() {
|
||||
VarRead getAUse() {
|
||||
ssaDefReachesUse(_, this, result) or
|
||||
this = TSsaUntracked(_, result)
|
||||
}
|
||||
@@ -952,7 +952,7 @@ class SsaVariable extends TSsaVariable {
|
||||
* Subsequent uses can be found by following the steps defined by
|
||||
* `adjacentUseUse`.
|
||||
*/
|
||||
RValue getAFirstUse() {
|
||||
VarRead getAFirstUse() {
|
||||
firstUse(this, result) or
|
||||
this = TSsaUntracked(_, result)
|
||||
}
|
||||
|
||||
@@ -54,7 +54,7 @@ private Expr getAnInterestingPrefix(InterestingPrefix root) {
|
||||
result.(AddExpr).getAnOperand() = getAnInterestingPrefix(root)
|
||||
}
|
||||
|
||||
private class StringBuilderAppend extends MethodAccess {
|
||||
private class StringBuilderAppend extends MethodCall {
|
||||
StringBuilderAppend() {
|
||||
this.getMethod().getDeclaringType() instanceof StringBuildingType and
|
||||
this.getMethod().hasName("append")
|
||||
@@ -68,7 +68,7 @@ private class StringBuilderConstructorOrAppend extends Call {
|
||||
}
|
||||
}
|
||||
|
||||
private Expr getQualifier(Expr e) { result = e.(MethodAccess).getQualifier() }
|
||||
private Expr getQualifier(Expr e) { result = e.(MethodCall).getQualifier() }
|
||||
|
||||
/**
|
||||
* An extension of `StringBuilderVar` that also accounts for strings appended in StringBuilder/Buffer's constructor
|
||||
|
||||
@@ -118,7 +118,7 @@ private module SsaImpl {
|
||||
}
|
||||
|
||||
/** Holds if `VarAccess` `use` of `v` occurs in `b` at index `i`. */
|
||||
private predicate variableUse(BaseSsaSourceVariable v, RValue use, BasicBlock b, int i) {
|
||||
private predicate variableUse(BaseSsaSourceVariable v, VarRead use, BasicBlock b, int i) {
|
||||
v.getAnAccess() = use and b.getNode(i) = use
|
||||
}
|
||||
|
||||
@@ -243,7 +243,7 @@ private module SsaImpl {
|
||||
* without crossing another SSA definition of `v`.
|
||||
*/
|
||||
private predicate ssaDefReachesUseWithinBlock(
|
||||
BaseSsaSourceVariable v, TrackedSsaDef def, RValue use
|
||||
BaseSsaSourceVariable v, TrackedSsaDef def, VarRead use
|
||||
) {
|
||||
exists(BasicBlock b, int rankix, int i |
|
||||
ssaDefReachesRank(v, def, b, rankix) and
|
||||
@@ -257,7 +257,7 @@ private module SsaImpl {
|
||||
* SSA definition of `v`.
|
||||
*/
|
||||
cached
|
||||
predicate ssaDefReachesUse(BaseSsaSourceVariable v, TrackedSsaDef def, RValue use) {
|
||||
predicate ssaDefReachesUse(BaseSsaSourceVariable v, TrackedSsaDef def, VarRead use) {
|
||||
ssaDefReachesUseWithinBlock(v, def, use)
|
||||
or
|
||||
exists(BasicBlock b |
|
||||
@@ -378,7 +378,7 @@ private module SsaImpl {
|
||||
* any other uses, but possibly through phi nodes.
|
||||
*/
|
||||
cached
|
||||
predicate firstUse(TrackedSsaDef def, RValue use) {
|
||||
predicate firstUse(TrackedSsaDef def, VarRead use) {
|
||||
exists(BaseSsaSourceVariable v, BasicBlock b1, int i1, BasicBlock b2, int i2 |
|
||||
adjacentVarRefs(v, b1, i1, b2, i2) and
|
||||
def.definesAt(v, b1, i1) and
|
||||
@@ -405,7 +405,7 @@ private module SsaImpl {
|
||||
* through any other use or any SSA definition of the variable.
|
||||
*/
|
||||
cached
|
||||
predicate baseSsaAdjacentUseUseSameVar(RValue use1, RValue use2) {
|
||||
predicate baseSsaAdjacentUseUseSameVar(VarRead use1, VarRead use2) {
|
||||
exists(BaseSsaSourceVariable v, BasicBlock b1, int i1, BasicBlock b2, int i2 |
|
||||
adjacentVarRefs(v, b1, i1, b2, i2) and
|
||||
variableUse(v, use1, b1, i1) and
|
||||
@@ -420,7 +420,7 @@ private module SsaImpl {
|
||||
* except for phi nodes.
|
||||
*/
|
||||
cached
|
||||
predicate baseSsaAdjacentUseUse(RValue use1, RValue use2) {
|
||||
predicate baseSsaAdjacentUseUse(VarRead use1, VarRead use2) {
|
||||
baseSsaAdjacentUseUseSameVar(use1, use2)
|
||||
or
|
||||
exists(
|
||||
@@ -490,7 +490,7 @@ class BaseSsaVariable extends TBaseSsaVariable {
|
||||
BasicBlock getBasicBlock() { result = this.getCfgNode().getBasicBlock() }
|
||||
|
||||
/** Gets an access of this SSA variable. */
|
||||
RValue getAUse() { ssaDefReachesUse(_, this, result) }
|
||||
VarRead getAUse() { ssaDefReachesUse(_, this, result) }
|
||||
|
||||
/**
|
||||
* Gets an access of the SSA source variable underlying this SSA variable
|
||||
@@ -500,7 +500,7 @@ class BaseSsaVariable extends TBaseSsaVariable {
|
||||
* Subsequent uses can be found by following the steps defined by
|
||||
* `baseSsaAdjacentUseUse`.
|
||||
*/
|
||||
RValue getAFirstUse() { firstUse(this, result) }
|
||||
VarRead getAFirstUse() { firstUse(this, result) }
|
||||
|
||||
/** Holds if this SSA variable is live at the end of `b`. */
|
||||
predicate isLiveAtEndOfBlock(BasicBlock b) { ssaDefReachesEndOfBlock(_, this, b) }
|
||||
|
||||
@@ -184,13 +184,13 @@ private predicate taintPreservingQualifierToMethod(Method m) {
|
||||
m.(MapMethod).hasName(["elements", "search", "searchEntries", "searchValues"])
|
||||
}
|
||||
|
||||
private predicate qualifierToMethodStep(Expr tracked, MethodAccess sink) {
|
||||
private predicate qualifierToMethodStep(Expr tracked, MethodCall sink) {
|
||||
taintPreservingQualifierToMethod(sink.getMethod()) and
|
||||
tracked = sink.getQualifier()
|
||||
}
|
||||
|
||||
private predicate qualifierToArgumentStep(Expr tracked, Expr sink) {
|
||||
exists(MethodAccess ma, CollectionMethod method |
|
||||
exists(MethodCall ma, CollectionMethod method |
|
||||
method = ma.getMethod() and
|
||||
(
|
||||
// java.util.Vector
|
||||
@@ -350,7 +350,7 @@ private predicate taintPreservingArgToArg(Method method, int input, int output)
|
||||
}
|
||||
|
||||
private predicate argToQualifierStep(Expr tracked, Expr sink) {
|
||||
exists(Method m, int i, MethodAccess ma |
|
||||
exists(Method m, int i, MethodCall ma |
|
||||
taintPreservingArgumentToQualifier(m, i) and
|
||||
ma.getMethod() = m and
|
||||
tracked = ma.getArgument(i) and
|
||||
@@ -359,7 +359,7 @@ private predicate argToQualifierStep(Expr tracked, Expr sink) {
|
||||
}
|
||||
|
||||
/** Access to a method that passes taint from an argument. */
|
||||
private predicate argToMethodStep(Expr tracked, MethodAccess sink) {
|
||||
private predicate argToMethodStep(Expr tracked, MethodCall sink) {
|
||||
exists(Method m |
|
||||
m = sink.getMethod() and
|
||||
(
|
||||
@@ -383,7 +383,7 @@ private predicate argToMethodStep(Expr tracked, MethodAccess sink) {
|
||||
* between arguments.
|
||||
*/
|
||||
private predicate argToArgStep(Expr tracked, Expr sink) {
|
||||
exists(MethodAccess ma, Method method, int input, int output |
|
||||
exists(MethodCall ma, Method method, int input, int output |
|
||||
ma.getMethod() = method and
|
||||
ma.getArgument(input) = tracked and
|
||||
ma.getArgument(output) = sink and
|
||||
|
||||
@@ -38,7 +38,7 @@ private module DispatchImpl {
|
||||
* might be improved by knowing the call context. This is the case if the
|
||||
* qualifier is the `i`th parameter of the enclosing callable `c`.
|
||||
*/
|
||||
private predicate mayBenefitFromCallContext(MethodAccess ma, Callable c, int i) {
|
||||
private predicate mayBenefitFromCallContext(MethodCall ma, Callable c, int i) {
|
||||
exists(Parameter p |
|
||||
2 <= strictcount(sourceDispatch(ma)) and
|
||||
ma.getQualifier().(VarAccess).getVariable() = p and
|
||||
@@ -58,7 +58,7 @@ private module DispatchImpl {
|
||||
|
||||
/**
|
||||
* Holds if the call `ctx` might act as a context that improves the set of
|
||||
* dispatch targets of a `MethodAccess` that occurs in a viable target of
|
||||
* dispatch targets of a `MethodCall` that occurs in a viable target of
|
||||
* `ctx`.
|
||||
*/
|
||||
pragma[nomagic]
|
||||
@@ -128,7 +128,7 @@ private module DispatchImpl {
|
||||
*/
|
||||
DataFlowCallable viableImplInCallContext(DataFlowCall call, DataFlowCall ctx) {
|
||||
result = viableCallable(call) and
|
||||
exists(int i, Callable c, Method def, RefType t, boolean exact, MethodAccess ma |
|
||||
exists(int i, Callable c, Method def, RefType t, boolean exact, MethodCall ma |
|
||||
ma = call.asCall() and
|
||||
mayBenefitFromCallContext(ma, c, i) and
|
||||
c = viableCallable(ctx).asCallable() and
|
||||
|
||||
@@ -84,7 +84,7 @@ private module Cached {
|
||||
import Cached
|
||||
|
||||
private predicate explicitInstanceArgument(Call call, Expr instarg) {
|
||||
call instanceof MethodAccess and
|
||||
call instanceof MethodCall and
|
||||
instarg = call.getQualifier() and
|
||||
not call.getCallee().isStatic()
|
||||
}
|
||||
@@ -463,7 +463,7 @@ module Private {
|
||||
/** A data flow node that represents the output of a call. */
|
||||
class OutNode extends Node {
|
||||
OutNode() {
|
||||
this.asExpr() instanceof MethodAccess
|
||||
this.asExpr() instanceof MethodCall
|
||||
or
|
||||
this.(FlowSummaryNode).isOut(_)
|
||||
}
|
||||
|
||||
@@ -114,7 +114,7 @@ private module CaptureInput implements VariableCapture::InputSig {
|
||||
CapturedVariable getVariable() { result = v }
|
||||
}
|
||||
|
||||
class VariableRead extends Expr instanceof RValue {
|
||||
class VariableRead extends Expr instanceof VarRead {
|
||||
CapturedVariable v;
|
||||
|
||||
VariableRead() { super.getVariable() = v }
|
||||
@@ -246,7 +246,7 @@ predicate readStep(Node node1, ContentSet f, Node node2) {
|
||||
fr = node2.asExpr()
|
||||
)
|
||||
or
|
||||
exists(Record r, Method getter, Field recf, MethodAccess get |
|
||||
exists(Record r, Method getter, Field recf, MethodCall get |
|
||||
getter.getDeclaringType() = r and
|
||||
recf.getDeclaringType() = r and
|
||||
getter.getNumberOfParameters() = 0 and
|
||||
|
||||
@@ -169,7 +169,7 @@ predicate localMustFlowStep(Node node1, Node node2) {
|
||||
import Cached
|
||||
|
||||
private predicate capturedVariableRead(Node n) {
|
||||
n.asExpr().(RValue).getVariable() instanceof CapturedVariable
|
||||
n.asExpr().(VarRead).getVariable() instanceof CapturedVariable
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -225,7 +225,7 @@ private predicate simpleLocalFlowStep0(Node node1, Node node2) {
|
||||
or
|
||||
simpleAstFlowStep(node1.asExpr(), node2.asExpr())
|
||||
or
|
||||
exists(MethodAccess ma, ValuePreservingMethod m, int argNo |
|
||||
exists(MethodCall ma, ValuePreservingMethod m, int argNo |
|
||||
ma.getCallee().getSourceDeclaration() = m and m.returnsValue(argNo)
|
||||
|
|
||||
node2.asExpr() = ma and
|
||||
@@ -379,7 +379,7 @@ signature predicate guardChecksSig(Guard g, Expr e, boolean branch);
|
||||
module BarrierGuard<guardChecksSig/3 guardChecks> {
|
||||
/** Gets a node that is safely guarded by the given guard check. */
|
||||
Node getABarrierNode() {
|
||||
exists(Guard g, SsaVariable v, boolean branch, RValue use |
|
||||
exists(Guard g, SsaVariable v, boolean branch, VarRead use |
|
||||
guardChecks(g, v.getAUse(), branch) and
|
||||
use = v.getAUse() and
|
||||
g.controls(use.getBasicBlock(), branch) and
|
||||
|
||||
@@ -333,7 +333,7 @@ predicate interpretInputSpecific(string c, InterpretNode mid, InterpretNode n) {
|
||||
exists(FieldWrite fw |
|
||||
c = "" and
|
||||
fw.getField() = mid.asElement() and
|
||||
n.asNode().asExpr() = fw.getRhs()
|
||||
n.asNode().asExpr() = fw.getASource()
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -53,10 +53,16 @@ private predicate isJdkInternal(CompilationUnit cu) {
|
||||
cu.getPackage().getName() = ""
|
||||
}
|
||||
|
||||
/** Holds if the given compilation unit's package is internal. */
|
||||
private predicate isInternal(CompilationUnit cu) {
|
||||
isJdkInternal(cu) or
|
||||
cu.getPackage().getName().matches("%internal%")
|
||||
}
|
||||
|
||||
/** Holds if the given callable is not worth modeling. */
|
||||
predicate isUninterestingForModels(Callable c) {
|
||||
isInTestFile(c.getCompilationUnit().getFile()) or
|
||||
isJdkInternal(c.getCompilationUnit()) or
|
||||
isInternal(c.getCompilationUnit()) or
|
||||
c instanceof MainMethod or
|
||||
c instanceof StaticInitializer or
|
||||
exists(FunctionalExpr funcExpr | c = funcExpr.asMethod()) or
|
||||
|
||||
@@ -290,7 +290,7 @@ private int argToParam(Call call, int argIdx) {
|
||||
|
||||
/** Access to a method that passes taint from qualifier to argument. */
|
||||
private predicate qualifierToArgumentStep(Expr tracked, Expr sink) {
|
||||
exists(MethodAccess ma, int arg |
|
||||
exists(MethodCall ma, int arg |
|
||||
ma.getMethod().(TaintPreservingCallable).transfersTaint(-1, argToParam(ma, arg)) and
|
||||
tracked = ma.getQualifier() and
|
||||
sink = ma.getArgument(arg)
|
||||
@@ -298,7 +298,7 @@ private predicate qualifierToArgumentStep(Expr tracked, Expr sink) {
|
||||
}
|
||||
|
||||
/** Access to a method that passes taint from the qualifier. */
|
||||
private predicate qualifierToMethodStep(Expr tracked, MethodAccess sink) {
|
||||
private predicate qualifierToMethodStep(Expr tracked, MethodCall sink) {
|
||||
taintPreservingQualifierToMethod(sink.getMethod()) and
|
||||
tracked = sink.getQualifier()
|
||||
}
|
||||
@@ -331,7 +331,7 @@ private predicate taintPreservingQualifierToMethod(Method m) {
|
||||
}
|
||||
|
||||
/** Access to a method that passes taint from an argument. */
|
||||
private predicate argToMethodStep(Expr tracked, MethodAccess sink) {
|
||||
private predicate argToMethodStep(Expr tracked, MethodCall sink) {
|
||||
exists(Method m, int i |
|
||||
m = sink.getMethod() and
|
||||
taintPreservingArgumentToMethod(m, argToParam(sink, i)) and
|
||||
@@ -375,7 +375,7 @@ private predicate taintPreservingArgumentToMethod(Method method, int arg) {
|
||||
* between arguments.
|
||||
*/
|
||||
private predicate argToArgStep(Expr tracked, Expr sink) {
|
||||
exists(MethodAccess ma, Method method, int input, int output |
|
||||
exists(MethodCall ma, Method method, int input, int output |
|
||||
method.(TaintPreservingCallable).transfersTaint(argToParam(ma, input), argToParam(ma, output)) and
|
||||
ma.getMethod() = method and
|
||||
ma.getArgument(input) = tracked and
|
||||
@@ -388,7 +388,7 @@ private predicate argToArgStep(Expr tracked, Expr sink) {
|
||||
* from the argument to the qualifier and `sink` is the qualifier.
|
||||
*/
|
||||
private predicate argToQualifierStep(Expr tracked, Expr sink) {
|
||||
exists(Method m, int i, MethodAccess ma |
|
||||
exists(Method m, int i, MethodCall ma |
|
||||
taintPreservingArgumentToQualifier(m, argToParam(ma, i)) and
|
||||
ma.getMethod() = m and
|
||||
tracked = ma.getArgument(i) and
|
||||
@@ -412,7 +412,7 @@ private predicate comparisonStep(Expr tracked, Expr sink) {
|
||||
e.hasOperands(tracked, other)
|
||||
)
|
||||
or
|
||||
exists(MethodAccess m | m.getMethod() instanceof EqualsMethod |
|
||||
exists(MethodCall m | m.getMethod() instanceof EqualsMethod |
|
||||
m = sink and
|
||||
(
|
||||
m.getQualifier() = tracked and m.getArgument(0) = other
|
||||
@@ -429,13 +429,13 @@ private predicate comparisonStep(Expr tracked, Expr sink) {
|
||||
private predicate serializationStep(Expr tracked, Expr sink) {
|
||||
exists(ObjectOutputStreamVar v, VariableAssign def |
|
||||
def = v.getADef() and
|
||||
exists(MethodAccess ma, RValue use |
|
||||
exists(MethodCall ma, VarRead use |
|
||||
ma.getArgument(0) = tracked and
|
||||
ma = v.getAWriteObjectMethodAccess() and
|
||||
ma = v.getAWriteObjectMethodCall() and
|
||||
use = ma.getQualifier() and
|
||||
defUsePair(def, use)
|
||||
) and
|
||||
exists(RValue outputstream, ClassInstanceExpr cie |
|
||||
exists(VarRead outputstream, ClassInstanceExpr cie |
|
||||
cie = def.getSource() and
|
||||
outputstream = cie.getArgument(0) and
|
||||
adjacentUseUse(outputstream, sink)
|
||||
@@ -460,23 +460,27 @@ class ObjectOutputStreamVar extends LocalVariableDecl {
|
||||
result.getDestVar() = this
|
||||
}
|
||||
|
||||
MethodAccess getAWriteObjectMethodAccess() {
|
||||
/** Gets a call to `writeObject` called against this variable. */
|
||||
MethodCall getAWriteObjectMethodCall() {
|
||||
result.getQualifier() = this.getAnAccess() and
|
||||
result.getMethod().hasName("writeObject")
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for `getAWriteObjectMethodCall`. */
|
||||
deprecated MethodCall getAWriteObjectMethodAccess() { result = this.getAWriteObjectMethodCall() }
|
||||
}
|
||||
|
||||
/** Flow through string formatting. */
|
||||
private predicate formatStep(Expr tracked, Expr sink) {
|
||||
exists(FormatterVar v, VariableAssign def |
|
||||
def = v.getADef() and
|
||||
exists(MethodAccess ma, RValue use |
|
||||
exists(MethodCall ma, VarRead use |
|
||||
ma.getAnArgument() = tracked and
|
||||
ma = v.getAFormatMethodAccess() and
|
||||
ma = v.getAFormatMethodCall() and
|
||||
use = ma.getQualifier() and
|
||||
defUsePair(def, use)
|
||||
) and
|
||||
exists(RValue output, ClassInstanceExpr cie |
|
||||
exists(VarRead output, ClassInstanceExpr cie |
|
||||
cie = def.getSource() and
|
||||
output = cie.getArgument(0) and
|
||||
adjacentUseUse(output, sink) and
|
||||
@@ -505,7 +509,7 @@ private class FormatterVar extends LocalVariableDecl {
|
||||
result.getDestVar() = this
|
||||
}
|
||||
|
||||
MethodAccess getAFormatMethodAccess() {
|
||||
MethodCall getAFormatMethodCall() {
|
||||
result.getQualifier() = this.getAnAccess() and
|
||||
result.getMethod().hasName("format")
|
||||
}
|
||||
@@ -555,7 +559,7 @@ module StringBuilderVarModule {
|
||||
/**
|
||||
* Gets a call that adds something to this string builder, from the argument at the given index.
|
||||
*/
|
||||
MethodAccess getAnInput(int arg) {
|
||||
MethodCall getAnInput(int arg) {
|
||||
result.getQualifier() = this.getAChainedReference() and
|
||||
(
|
||||
result.getMethod().getName() = "append" and arg = 0
|
||||
@@ -569,19 +573,19 @@ module StringBuilderVarModule {
|
||||
/**
|
||||
* Gets a call that appends something to this string builder.
|
||||
*/
|
||||
MethodAccess getAnAppend() {
|
||||
MethodCall getAnAppend() {
|
||||
result.getQualifier() = this.getAChainedReference() and
|
||||
result.getMethod().getName() = "append"
|
||||
}
|
||||
|
||||
MethodAccess getNextAppend(MethodAccess append) {
|
||||
MethodCall getNextAppend(MethodCall append) {
|
||||
result = this.getAnAppend() and
|
||||
append = this.getAnAppend() and
|
||||
(
|
||||
result.getQualifier() = append
|
||||
or
|
||||
not exists(MethodAccess chainAccess | chainAccess.getQualifier() = append) and
|
||||
exists(RValue sbva1, RValue sbva2 |
|
||||
not exists(MethodCall chainAccess | chainAccess.getQualifier() = append) and
|
||||
exists(VarRead sbva1, VarRead sbva2 |
|
||||
adjacentUseUse(sbva1, sbva2) and
|
||||
append.getQualifier() = this.getAChainedReference(sbva1) and
|
||||
result.getQualifier() = sbva2
|
||||
@@ -592,7 +596,7 @@ module StringBuilderVarModule {
|
||||
/**
|
||||
* Gets a call that converts this string builder to a string.
|
||||
*/
|
||||
MethodAccess getToStringCall() {
|
||||
MethodCall getToStringCall() {
|
||||
result.getQualifier() = this.getAChainedReference() and
|
||||
result.getMethod().getName() = "toString"
|
||||
}
|
||||
@@ -612,7 +616,7 @@ module StringBuilderVarModule {
|
||||
}
|
||||
}
|
||||
|
||||
private MethodAccess callReturningSameType(Expr ref) {
|
||||
private MethodCall callReturningSameType(Expr ref) {
|
||||
ref = result.getQualifier() and
|
||||
result.getMethod().getReturnType() = ref.getType()
|
||||
}
|
||||
|
||||
@@ -10,6 +10,8 @@ class SsaVariable = Ssa::SsaVariable;
|
||||
|
||||
class Expr = J::Expr;
|
||||
|
||||
class Location = J::Location;
|
||||
|
||||
class IntegralType = J::IntegralType;
|
||||
|
||||
class ConstantIntegerExpr = RU::ConstantIntegerExpr;
|
||||
|
||||
@@ -200,11 +200,11 @@ private module Impl {
|
||||
* `Collection`).
|
||||
*/
|
||||
predicate containerSizeAccess(Expr e) {
|
||||
e.(MethodAccess).getMethod() instanceof StringLengthMethod
|
||||
e.(MethodCall).getMethod() instanceof StringLengthMethod
|
||||
or
|
||||
e.(MethodAccess).getMethod() instanceof CollectionSizeMethod
|
||||
e.(MethodCall).getMethod() instanceof CollectionSizeMethod
|
||||
or
|
||||
e.(MethodAccess).getMethod() instanceof MapSizeMethod
|
||||
e.(MethodCall).getMethod() instanceof MapSizeMethod
|
||||
}
|
||||
|
||||
/** Holds if `e` is by definition strictly positive. */
|
||||
@@ -218,7 +218,7 @@ private module Impl {
|
||||
// types handled in `specificSubExprSign`.
|
||||
e instanceof ArrayAccess and e.getType() instanceof NumericOrCharType
|
||||
or
|
||||
e instanceof MethodAccess and e.getType() instanceof NumericOrCharType
|
||||
e instanceof MethodCall and e.getType() instanceof NumericOrCharType
|
||||
or
|
||||
e instanceof ClassInstanceExpr and e.getType() instanceof NumericOrCharType
|
||||
}
|
||||
@@ -267,7 +267,7 @@ private module Impl {
|
||||
|
||||
/** Holds if `f` can have any sign. */
|
||||
predicate fieldWithUnknownSign(Field f) {
|
||||
exists(ReflectiveFieldAccess rfa | rfa.inferAccessedField() = f)
|
||||
exists(ReflectiveGetFieldCall rfa | rfa.inferAccessedField() = f)
|
||||
}
|
||||
|
||||
/** Holds if `f` is accessed in an increment operation. */
|
||||
|
||||
@@ -173,9 +173,9 @@ class LiveClass extends SourceClassOrInterface {
|
||||
exists(NestedType r | r.getEnclosingType() = this | r instanceof LiveClass)
|
||||
or
|
||||
// An annotation on the class is reflectively accessed.
|
||||
exists(ReflectiveAnnotationAccess reflectiveAnnotationAccess |
|
||||
this = reflectiveAnnotationAccess.getInferredClassType() and
|
||||
isLive(reflectiveAnnotationAccess.getEnclosingCallable())
|
||||
exists(ReflectiveGetAnnotationCall reflectiveAnnotationCall |
|
||||
this = reflectiveAnnotationCall.getInferredClassType() and
|
||||
isLive(reflectiveAnnotationCall.getEnclosingCallable())
|
||||
)
|
||||
or
|
||||
this instanceof AnonymousClass
|
||||
|
||||
@@ -19,7 +19,7 @@ VarAccess valueAccess(EnumConstant e) {
|
||||
(
|
||||
exists(Call c |
|
||||
c.getAnArgument() = valueFlow+(result) or
|
||||
c.(MethodAccess).getQualifier() = valueFlow+(result)
|
||||
c.(MethodCall).getQualifier() = valueFlow+(result)
|
||||
)
|
||||
or
|
||||
exists(Assignment a | a.getSource() = valueFlow+(result))
|
||||
@@ -47,14 +47,14 @@ predicate exception(EnumConstant e) {
|
||||
)
|
||||
or
|
||||
// A method iterates over the values of an enum.
|
||||
exists(MethodAccess values | values.getMethod().getDeclaringType() = t |
|
||||
exists(MethodCall values | values.getMethod().getDeclaringType() = t |
|
||||
values.getParent() instanceof EnhancedForStmt or
|
||||
values.getParent().(MethodAccess).getMethod().hasName("findThisIn")
|
||||
values.getParent().(MethodCall).getMethod().hasName("findThisIn")
|
||||
)
|
||||
or
|
||||
// The `valueOf` method is called, meaning that depending on the string any constant
|
||||
// could be retrieved.
|
||||
exists(MethodAccess valueOf | valueOf.getMethod().getDeclaringType() = t |
|
||||
exists(MethodCall valueOf | valueOf.getMethod().getDeclaringType() = t |
|
||||
valueOf.getMethod().hasName("valueOf")
|
||||
)
|
||||
or
|
||||
|
||||
@@ -130,7 +130,7 @@ class JUnitAnnotatedField extends ReflectivelyReadField {
|
||||
*/
|
||||
class ClassReflectivelyReadField extends ReflectivelyReadField {
|
||||
ClassReflectivelyReadField() {
|
||||
exists(ReflectiveFieldAccess fieldAccess | this = fieldAccess.inferAccessedField())
|
||||
exists(ReflectiveGetFieldCall fieldAccess | this = fieldAccess.inferAccessedField())
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -142,7 +142,7 @@ deprecated class JAXAnnotationReflectivelyConstructedClass =
|
||||
class DeserializedClass extends ReflectivelyConstructedClass {
|
||||
DeserializedClass() {
|
||||
exists(CastingExpr cast, ReadObjectMethod readObject |
|
||||
cast.getExpr().(MethodAccess).getMethod() = readObject
|
||||
cast.getExpr().(MethodCall).getMethod() = readObject
|
||||
|
|
||||
hasDescendant(cast.getType(), this)
|
||||
)
|
||||
@@ -164,7 +164,7 @@ class NewInstanceCall extends EntryPoint, NewInstance {
|
||||
/**
|
||||
* A call to either `Class.getMethod(...)` or `Class.getDeclaredMethod(...)`.
|
||||
*/
|
||||
class ReflectiveMethodAccessEntryPoint extends EntryPoint, ReflectiveMethodAccess {
|
||||
class ReflectiveGetMethodCallEntryPoint extends EntryPoint, ReflectiveGetMethodCall {
|
||||
override Method getALiveCallable() {
|
||||
result = this.inferAccessedMethod() and
|
||||
// The `getMethod(...)` call must be used in a live context.
|
||||
@@ -172,6 +172,9 @@ class ReflectiveMethodAccessEntryPoint extends EntryPoint, ReflectiveMethodAcces
|
||||
}
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for `ReflectiveGetMethodCallEntryPoint`. */
|
||||
deprecated class ReflectiveMethodAccessEntryPoint = ReflectiveGetMethodCallEntryPoint;
|
||||
|
||||
/**
|
||||
* Classes that are entry points recognised by annotations.
|
||||
*/
|
||||
|
||||
@@ -19,7 +19,7 @@ private import codeql.typetracking.TypeTracking
|
||||
/**
|
||||
* Gets a viable dispatch target for `ma`. This is the input dispatch relation.
|
||||
*/
|
||||
private Method viableImpl_inp(MethodAccess ma) { result = viableImpl_v2(ma) }
|
||||
private Method viableImpl_inp(MethodCall ma) { result = viableImpl_v2(ma) }
|
||||
|
||||
private Callable dispatchCand(Call c) {
|
||||
c instanceof ConstructorCall and result = c.getCallee().getSourceDeclaration()
|
||||
@@ -99,7 +99,7 @@ private predicate trackedMethodOnType(Method m, SrcRefType t) {
|
||||
* by the type constructed by `cie`. Thus the dispatch from `ma` to `m` will
|
||||
* only be included if `cie` flows to the qualifier of `ma`.
|
||||
*/
|
||||
private predicate dispatchOrigin(ClassInstanceExpr cie, MethodAccess ma, Method m) {
|
||||
private predicate dispatchOrigin(ClassInstanceExpr cie, MethodCall ma, Method m) {
|
||||
m = viableImpl_inp(ma) and
|
||||
not m = ma.getMethod().getSourceDeclaration() and
|
||||
trackedMethodOnType(m, cie.getConstructedType().getSourceDeclaration())
|
||||
@@ -133,7 +133,7 @@ private module TypeTrackingSteps {
|
||||
class LocalSourceNode extends RelevantNode {
|
||||
LocalSourceNode() {
|
||||
this.asExpr() instanceof Call or
|
||||
this.asExpr() instanceof RValue or
|
||||
this.asExpr() instanceof VarRead or
|
||||
this instanceof DataFlow::ParameterNode or
|
||||
this instanceof DataFlow::ImplicitVarargsArray or
|
||||
this.asExpr() instanceof ArrayInit or
|
||||
@@ -197,10 +197,10 @@ private module TypeTrackingSteps {
|
||||
enum.getAnEnumConstant().getAnAssignedValue() = n1.asExpr() and
|
||||
getValue.getDeclaringType() = enum and
|
||||
getValue.hasName("valueOf") and
|
||||
n2.asExpr().(MethodAccess).getMethod() = getValue
|
||||
n2.asExpr().(MethodCall).getMethod() = getValue
|
||||
)
|
||||
or
|
||||
exists(Variable v, MethodAccess put, MethodAccess get |
|
||||
exists(Variable v, MethodCall put, MethodCall get |
|
||||
put.getArgument(1) = n1.asExpr() and
|
||||
put.getMethod().(MapMethod).hasName("put") and
|
||||
put.getQualifier() = v.getAnAccess() and
|
||||
@@ -209,12 +209,12 @@ private module TypeTrackingSteps {
|
||||
n2.asExpr() = get
|
||||
)
|
||||
or
|
||||
exists(Variable v, MethodAccess add |
|
||||
exists(Variable v, MethodCall add |
|
||||
add.getAnArgument() = n1.asExpr() and
|
||||
add.getMethod().(CollectionMethod).hasName("add") and
|
||||
add.getQualifier() = v.getAnAccess()
|
||||
|
|
||||
exists(MethodAccess get |
|
||||
exists(MethodCall get |
|
||||
get.getQualifier() = v.getAnAccess() and
|
||||
get.getMethod().(CollectionMethod).hasName("get") and
|
||||
n2.asExpr() = get
|
||||
@@ -236,7 +236,7 @@ private module TypeTrackingSteps {
|
||||
enum.getAnEnumConstant().getAnAssignedValue() = n1.asExpr() and
|
||||
getValue.getDeclaringType() = enum and
|
||||
getValue.hasName("values") and
|
||||
n2.asExpr().(MethodAccess).getMethod() = getValue and
|
||||
n2.asExpr().(MethodCall).getMethod() = getValue and
|
||||
f = ContentArray()
|
||||
)
|
||||
or
|
||||
@@ -253,7 +253,7 @@ private module TypeTrackingSteps {
|
||||
exists(AssignExpr a, Variable v |
|
||||
a.getSource() = n1.asExpr() and
|
||||
a.getDest().(ArrayAccess).getArray() = v.getAnAccess() and
|
||||
n2.asExpr() = v.getAnAccess().(RValue) and
|
||||
n2.asExpr() = v.getAnAccess().(VarRead) and
|
||||
f = ContentArray()
|
||||
)
|
||||
}
|
||||
@@ -300,10 +300,10 @@ private module TypeTrackingSteps {
|
||||
private predicate lambdaSource(RelevantNode n) { dispatchOrigin(n.asExpr(), _, _) }
|
||||
|
||||
private predicate lambdaSink(RelevantNode n) {
|
||||
exists(MethodAccess ma | dispatchOrigin(_, ma, _) | n = DataFlow::getInstanceArgument(ma))
|
||||
exists(MethodCall ma | dispatchOrigin(_, ma, _) | n = DataFlow::getInstanceArgument(ma))
|
||||
}
|
||||
|
||||
private signature Method methodDispatchSig(MethodAccess ma);
|
||||
private signature Method methodDispatchSig(MethodCall ma);
|
||||
|
||||
private module TrackLambda<methodDispatchSig/1 lambdaDispatch0> {
|
||||
private Callable dispatch(Call c) {
|
||||
@@ -352,7 +352,7 @@ private module TrackLambda<methodDispatchSig/1 lambdaDispatch0> {
|
||||
|
||||
private predicate edgePlus(PathNode n1, PathNode n2) = fastTC(edges/2)(n1, n2)
|
||||
|
||||
private predicate pairCand(PathNode p1, PathNode p2, Method m, MethodAccess ma) {
|
||||
private predicate pairCand(PathNode p1, PathNode p2, Method m, MethodCall ma) {
|
||||
exists(ClassInstanceExpr cie |
|
||||
dispatchOrigin(cie, ma, m) and
|
||||
p1.getNode() = DataFlow::exprNode(cie) and
|
||||
@@ -367,7 +367,7 @@ private module TrackLambda<methodDispatchSig/1 lambdaDispatch0> {
|
||||
* declares or inherits the tracked method `result` to the qualifier of `ma` such
|
||||
* that `ma` may dispatch to `result`.
|
||||
*/
|
||||
Method lambdaDispatch(MethodAccess ma) {
|
||||
Method lambdaDispatch(MethodCall ma) {
|
||||
exists(PathNode p1, PathNode p2 |
|
||||
(p1 = p2 or edgePlus(p1, p2)) and
|
||||
pairCand(p1, p2, result, ma)
|
||||
@@ -375,30 +375,30 @@ private module TrackLambda<methodDispatchSig/1 lambdaDispatch0> {
|
||||
}
|
||||
}
|
||||
|
||||
private Method noDisp(MethodAccess ma) { none() }
|
||||
private Method noDisp(MethodCall ma) { none() }
|
||||
|
||||
pragma[nomagic]
|
||||
private Method d1(MethodAccess ma) { result = TrackLambda<noDisp/1>::lambdaDispatch(ma) }
|
||||
private Method d1(MethodCall ma) { result = TrackLambda<noDisp/1>::lambdaDispatch(ma) }
|
||||
|
||||
pragma[nomagic]
|
||||
private Method d2(MethodAccess ma) { result = TrackLambda<d1/1>::lambdaDispatch(ma) }
|
||||
private Method d2(MethodCall ma) { result = TrackLambda<d1/1>::lambdaDispatch(ma) }
|
||||
|
||||
pragma[nomagic]
|
||||
private Method d3(MethodAccess ma) { result = TrackLambda<d2/1>::lambdaDispatch(ma) }
|
||||
private Method d3(MethodCall ma) { result = TrackLambda<d2/1>::lambdaDispatch(ma) }
|
||||
|
||||
pragma[nomagic]
|
||||
private Method d4(MethodAccess ma) { result = TrackLambda<d3/1>::lambdaDispatch(ma) }
|
||||
private Method d4(MethodCall ma) { result = TrackLambda<d3/1>::lambdaDispatch(ma) }
|
||||
|
||||
pragma[nomagic]
|
||||
private Method d5(MethodAccess ma) { result = TrackLambda<d4/1>::lambdaDispatch(ma) }
|
||||
private Method d5(MethodCall ma) { result = TrackLambda<d4/1>::lambdaDispatch(ma) }
|
||||
|
||||
pragma[nomagic]
|
||||
private Method d6(MethodAccess ma) { result = TrackLambda<d5/1>::lambdaDispatch(ma) }
|
||||
private Method d6(MethodCall ma) { result = TrackLambda<d5/1>::lambdaDispatch(ma) }
|
||||
|
||||
/**
|
||||
* Gets a viable dispatch target for `ma`. This is the output dispatch relation.
|
||||
*/
|
||||
Method viableImpl_out(MethodAccess ma) {
|
||||
Method viableImpl_out(MethodCall ma) {
|
||||
result = viableImpl_inp(ma) and
|
||||
(result = d6(ma) or not dispatchOrigin(_, ma, result))
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ private import semmle.code.java.dispatch.internal.Unification
|
||||
/**
|
||||
* Gets a viable dispatch target for `ma`. This is the input dispatch relation.
|
||||
*/
|
||||
private Method viableImpl_inp(MethodAccess ma) { result = viableImpl_v3(ma) }
|
||||
private Method viableImpl_inp(MethodCall ma) { result = viableImpl_v3(ma) }
|
||||
|
||||
private Callable dispatchCand(Call c) {
|
||||
c instanceof ConstructorCall and result = c.getCallee().getSourceDeclaration()
|
||||
@@ -118,7 +118,7 @@ private predicate step(Node n1, Node n2) {
|
||||
exists(AssignExpr a, Field v |
|
||||
a.getSource() = n1.asExpr() and
|
||||
a.getDest().(ArrayAccess).getArray() = v.getAnAccess() and
|
||||
n2.asExpr() = v.getAnAccess().(RValue)
|
||||
n2.asExpr() = v.getAnAccess().(VarRead)
|
||||
)
|
||||
or
|
||||
exists(AssignExpr a |
|
||||
@@ -193,7 +193,7 @@ private predicate source(RefType t, ObjNode n) {
|
||||
* Holds if `n` is the qualifier of an `Object.toString()` call.
|
||||
*/
|
||||
private predicate sink(ObjNode n) {
|
||||
exists(MethodAccess toString |
|
||||
exists(MethodCall toString |
|
||||
toString.getQualifier() = n.asExpr() and
|
||||
toString.getMethod() instanceof ToStringMethod
|
||||
) and
|
||||
@@ -231,7 +231,7 @@ private predicate objType(ObjNode n, RefType t) {
|
||||
)
|
||||
}
|
||||
|
||||
private VirtualMethodAccess objectToString(ObjNode n) {
|
||||
private VirtualMethodCall objectToString(ObjNode n) {
|
||||
result.getQualifier() = n.asExpr() and sink(n)
|
||||
}
|
||||
|
||||
@@ -239,16 +239,16 @@ private VirtualMethodAccess objectToString(ObjNode n) {
|
||||
* Holds if `ma` is an `Object.toString()` call taking possibly improved type
|
||||
* bounds into account.
|
||||
*/
|
||||
predicate objectToStringCall(VirtualMethodAccess ma) { ma = objectToString(_) }
|
||||
predicate objectToStringCall(VirtualMethodCall ma) { ma = objectToString(_) }
|
||||
|
||||
/**
|
||||
* Holds if the qualifier of the `Object.toString()` call `ma` might have type `t`.
|
||||
*/
|
||||
private predicate objectToStringQualType(MethodAccess ma, RefType t) {
|
||||
private predicate objectToStringQualType(MethodCall ma, RefType t) {
|
||||
exists(ObjNode n | ma = objectToString(n) and objType(n, t))
|
||||
}
|
||||
|
||||
private Method viableImplObjectToString(MethodAccess ma) {
|
||||
private Method viableImplObjectToString(MethodCall ma) {
|
||||
exists(Method def, RefType t |
|
||||
objectToStringQualType(ma, t) and
|
||||
def = ma.getMethod() and
|
||||
@@ -265,7 +265,7 @@ private Method viableImplObjectToString(MethodAccess ma) {
|
||||
* The set of dispatch targets for `Object.toString()` calls are reduced based
|
||||
* on possible data flow from objects of more specific types to the qualifier.
|
||||
*/
|
||||
Method viableImpl_out(MethodAccess ma) {
|
||||
Method viableImpl_out(MethodCall ma) {
|
||||
result = viableImpl_inp(ma) and
|
||||
(
|
||||
result = viableImplObjectToString(ma) or
|
||||
|
||||
@@ -15,7 +15,7 @@ private import semmle.code.java.dispatch.internal.Unification
|
||||
* A conservative analysis that returns a single method - if we can establish
|
||||
* one - that will be the target of the virtual dispatch.
|
||||
*/
|
||||
Method exactVirtualMethod(MethodAccess c) {
|
||||
Method exactVirtualMethod(MethodCall c) {
|
||||
// If there are multiple potential implementations, return nothing.
|
||||
implCount(c, 1) and
|
||||
result = viableImpl(c)
|
||||
@@ -31,7 +31,7 @@ Callable exactCallable(Call c) {
|
||||
c instanceof ConstructorCall and result = c.getCallee()
|
||||
}
|
||||
|
||||
private predicate implCount(MethodAccess m, int c) { strictcount(viableImpl(m)) = c }
|
||||
private predicate implCount(MethodCall m, int c) { strictcount(viableImpl(m)) = c }
|
||||
|
||||
/** Gets a viable implementation of the target of the given `Call`. */
|
||||
Callable viableCallable(Call c) {
|
||||
@@ -44,7 +44,7 @@ Callable viableCallable(Call c) {
|
||||
class VirtCalledSrcMethod extends SrcMethod {
|
||||
pragma[nomagic]
|
||||
VirtCalledSrcMethod() {
|
||||
exists(VirtualMethodAccess ma | ma.getMethod().getSourceDeclaration() = this)
|
||||
exists(VirtualMethodCall ma | ma.getMethod().getSourceDeclaration() = this)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ cached
|
||||
private module Dispatch {
|
||||
/** Gets a viable implementation of the method called in the given method access. */
|
||||
cached
|
||||
Method viableImpl(MethodAccess ma) { result = ObjFlow::viableImpl_out(ma) }
|
||||
Method viableImpl(MethodCall ma) { result = ObjFlow::viableImpl_out(ma) }
|
||||
|
||||
/**
|
||||
* Holds if `m` is a viable implementation of the method called in `ma` for
|
||||
@@ -60,7 +60,7 @@ private module Dispatch {
|
||||
* the dispatch type is likely to yield implausible dispatch targets.
|
||||
*/
|
||||
cached
|
||||
predicate lowConfidenceDispatchTarget(MethodAccess ma, Method m) {
|
||||
predicate lowConfidenceDispatchTarget(MethodCall ma, Method m) {
|
||||
m = viableImpl(ma) and lowConfidenceDispatch(ma)
|
||||
}
|
||||
|
||||
@@ -70,13 +70,13 @@ private module Dispatch {
|
||||
* Gets a viable implementation of the method called in the given method access.
|
||||
*/
|
||||
cached
|
||||
Method viableImpl_v3(MethodAccess ma) { result = DispatchFlow::viableImpl_out(ma) }
|
||||
Method viableImpl_v3(MethodCall ma) { result = DispatchFlow::viableImpl_out(ma) }
|
||||
|
||||
/**
|
||||
* Holds if the best type bounds for the qualifier of `ma` are likely to
|
||||
* contain implausible dispatch targets.
|
||||
*/
|
||||
private predicate lowConfidenceDispatch(VirtualMethodAccess ma) {
|
||||
private predicate lowConfidenceDispatch(VirtualMethodCall ma) {
|
||||
exists(RefType t | hasQualifierType(ma, t, false) |
|
||||
lowConfidenceDispatchType(t.getSourceDeclaration())
|
||||
) and
|
||||
@@ -121,7 +121,7 @@ private module Dispatch {
|
||||
* Gets a viable implementation of the method called in the given method access.
|
||||
*/
|
||||
cached
|
||||
Method viableImpl_v2(MethodAccess ma) {
|
||||
Method viableImpl_v2(MethodCall ma) {
|
||||
result = viableImpl_v2_cand(pragma[only_bind_into](ma)) and
|
||||
exists(Method def, RefType t, boolean exact |
|
||||
qualUnionType(pragma[only_bind_into](ma), pragma[only_bind_into](t),
|
||||
@@ -141,7 +141,7 @@ private module Dispatch {
|
||||
not qualUnionType(ma, _, _)
|
||||
}
|
||||
|
||||
private predicate qualUnionType(VirtualMethodAccess ma, RefType t, boolean exact) {
|
||||
private predicate qualUnionType(VirtualMethodCall ma, RefType t, boolean exact) {
|
||||
exprUnionTypeFlow(ma.getQualifier(), t, exact)
|
||||
}
|
||||
|
||||
@@ -150,7 +150,7 @@ private module Dispatch {
|
||||
private module Unification_v2 =
|
||||
MkUnification<unificationTargetLeft_v2/1, unificationTargetRight/1>;
|
||||
|
||||
private Method viableImpl_v2_cand(MethodAccess ma) {
|
||||
private Method viableImpl_v2_cand(MethodCall ma) {
|
||||
result = viableImpl_v1(ma) and
|
||||
(
|
||||
exists(Method def, RefType t, boolean exact |
|
||||
@@ -170,7 +170,7 @@ private module Dispatch {
|
||||
)
|
||||
}
|
||||
|
||||
private predicate qualType(VirtualMethodAccess ma, RefType t, boolean exact) {
|
||||
private predicate qualType(VirtualMethodCall ma, RefType t, boolean exact) {
|
||||
exprTypeFlow(ma.getQualifier(), t, exact)
|
||||
}
|
||||
|
||||
@@ -185,7 +185,7 @@ private module Dispatch {
|
||||
* Gets a viable implementation of the method called in the given method access.
|
||||
*/
|
||||
cached
|
||||
Method viableImpl_v1(MethodAccess source) {
|
||||
Method viableImpl_v1(MethodCall source) {
|
||||
result = viableImpl_v1_cand(source) and
|
||||
not impossibleDispatchTarget(source, result)
|
||||
}
|
||||
@@ -193,7 +193,7 @@ private module Dispatch {
|
||||
/**
|
||||
* Holds if `source` cannot dispatch to `tgt` due to a negative `instanceof` guard.
|
||||
*/
|
||||
private predicate impossibleDispatchTarget(MethodAccess source, Method tgt) {
|
||||
private predicate impossibleDispatchTarget(MethodCall source, Method tgt) {
|
||||
tgt = viableImpl_v1_cand(source) and
|
||||
exists(InstanceOfExpr ioe, BaseSsaVariable v, Expr q, RefType t |
|
||||
source.getQualifier() = q and
|
||||
@@ -208,9 +208,9 @@ private module Dispatch {
|
||||
/**
|
||||
* Gets a viable implementation of the method called in the given method access.
|
||||
*/
|
||||
private Method viableImpl_v1_cand(MethodAccess source) {
|
||||
private Method viableImpl_v1_cand(MethodCall source) {
|
||||
not result.isAbstract() and
|
||||
if source instanceof VirtualMethodAccess
|
||||
if source instanceof VirtualMethodCall
|
||||
then
|
||||
exists(VirtCalledSrcMethod def, RefType t, boolean exact |
|
||||
source.getMethod().getSourceDeclaration() = def and
|
||||
@@ -242,7 +242,7 @@ private module Dispatch {
|
||||
not e instanceof FunctionalExpr and result = e.getType()
|
||||
}
|
||||
|
||||
private predicate hasQualifierType(VirtualMethodAccess ma, RefType t, boolean exact) {
|
||||
private predicate hasQualifierType(VirtualMethodCall ma, RefType t, boolean exact) {
|
||||
exists(Expr src | src = ma.getQualifier() |
|
||||
// If we have a qualifier, then we take its type.
|
||||
exists(RefType srctype | srctype = getPreciseType(src) |
|
||||
@@ -264,9 +264,9 @@ private module Dispatch {
|
||||
not exists(ma.getQualifier()) and
|
||||
exact = false and
|
||||
(
|
||||
ma.isOwnMethodAccess() and t = ma.getEnclosingCallable().getDeclaringType()
|
||||
ma.isOwnMethodCall() and t = ma.getEnclosingCallable().getDeclaringType()
|
||||
or
|
||||
ma.isEnclosingMethodAccess(t)
|
||||
ma.isEnclosingMethodCall(t)
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ private predicate runner(Method m, int n, Method runmethod) {
|
||||
(
|
||||
m.isNative()
|
||||
or
|
||||
exists(Parameter p, MethodAccess ma, int j |
|
||||
exists(Parameter p, MethodCall ma, int j |
|
||||
p = m.getParameter(n) and
|
||||
ma.getEnclosingCallable() = m and
|
||||
runner(pragma[only_bind_into](ma.getMethod().getSourceDeclaration()),
|
||||
@@ -31,7 +31,7 @@ private predicate runner(Method m, int n, Method runmethod) {
|
||||
* through a functional interface. The argument is traced backwards through
|
||||
* casts and variable assignments.
|
||||
*/
|
||||
private Expr getRunnerArgument(MethodAccess ma, Method runmethod) {
|
||||
private Expr getRunnerArgument(MethodCall ma, Method runmethod) {
|
||||
exists(Method runner, int param |
|
||||
runner(runner, param, runmethod) and
|
||||
viableImpl_v2(ma) = runner and
|
||||
@@ -50,7 +50,7 @@ private Expr getRunnerArgument(MethodAccess ma, Method runmethod) {
|
||||
* Gets a method that can be invoked through a functional interface as an
|
||||
* argument to `ma`.
|
||||
*/
|
||||
Method getRunnerTarget(MethodAccess ma) {
|
||||
Method getRunnerTarget(MethodCall ma) {
|
||||
exists(Expr action, Method runmethod | action = getRunnerArgument(ma, runmethod) |
|
||||
action.(FunctionalExpr).asMethod().getSourceDeclaration() = result
|
||||
or
|
||||
|
||||
@@ -23,8 +23,8 @@ Expr getSystemProperty(string propertyName) {
|
||||
result = getSystemPropertyFromSpringProperties(propertyName)
|
||||
}
|
||||
|
||||
private MethodAccess getSystemPropertyFromSystem(string propertyName) {
|
||||
result.(MethodAccessSystemGetProperty).hasCompileTimeConstantGetPropertyName(propertyName)
|
||||
private MethodCall getSystemPropertyFromSystem(string propertyName) {
|
||||
result.(MethodCallSystemGetProperty).hasCompileTimeConstantGetPropertyName(propertyName)
|
||||
or
|
||||
result.getMethod().hasName("lineSeparator") and propertyName = "line.separator"
|
||||
}
|
||||
@@ -34,7 +34,7 @@ private MethodAccess getSystemPropertyFromSystem(string propertyName) {
|
||||
* - `System.getProperties().getProperty(...)`
|
||||
* - `System.getProperties().get(...)`
|
||||
*/
|
||||
private MethodAccess getSystemPropertyFromSystemGetProperties(string propertyName) {
|
||||
private MethodCall getSystemPropertyFromSystemGetProperties(string propertyName) {
|
||||
exists(Method getMethod |
|
||||
getMethod instanceof PropertiesGetMethod
|
||||
or
|
||||
@@ -42,7 +42,7 @@ private MethodAccess getSystemPropertyFromSystemGetProperties(string propertyNam
|
||||
result.getMethod() = getMethod
|
||||
) and
|
||||
result.getArgument(0).(CompileTimeConstantExpr).getStringValue() = propertyName and
|
||||
localExprFlowPlusInitializers(any(MethodAccess m |
|
||||
localExprFlowPlusInitializers(any(MethodCall m |
|
||||
m.getMethod().getDeclaringType() instanceof TypeSystem and
|
||||
m.getMethod().hasName("getProperties")
|
||||
), result.getQualifier())
|
||||
@@ -156,7 +156,7 @@ private FieldAccess getSystemPropertyFromApacheSystemUtils(string propertyName)
|
||||
)
|
||||
}
|
||||
|
||||
private MethodAccess getSystemPropertyFromApacheFileUtils(string propertyName) {
|
||||
private MethodCall getSystemPropertyFromApacheFileUtils(string propertyName) {
|
||||
exists(Method m |
|
||||
result.getMethod() = m and
|
||||
m.getDeclaringType().hasQualifiedName("org.apache.commons.io", "FileUtils")
|
||||
@@ -167,7 +167,7 @@ private MethodAccess getSystemPropertyFromApacheFileUtils(string propertyName) {
|
||||
)
|
||||
}
|
||||
|
||||
private MethodAccess getSystemPropertyFromGuava(string propertyName) {
|
||||
private MethodCall getSystemPropertyFromGuava(string propertyName) {
|
||||
exists(EnumConstant ec |
|
||||
ec.getDeclaringType().hasQualifiedName("com.google.common.base", "StandardSystemProperty") and
|
||||
// Example: `StandardSystemProperty.JAVA_IO_TMPDIR.value()`
|
||||
@@ -177,10 +177,10 @@ private MethodAccess getSystemPropertyFromGuava(string propertyName) {
|
||||
)
|
||||
or
|
||||
// Example: `System.getProperty(StandardSystemProperty.JAVA_IO_TMPDIR.key())`
|
||||
exists(MethodAccess keyMa |
|
||||
exists(MethodCall keyMa |
|
||||
localExprFlowPlusInitializers(ec.getAnAccess(), keyMa.getQualifier()) and
|
||||
keyMa.getMethod().hasName("key") and
|
||||
localExprFlowPlusInitializers(keyMa, result.(MethodAccessSystemGetProperty).getArgument(0))
|
||||
localExprFlowPlusInitializers(keyMa, result.(MethodCallSystemGetProperty).getArgument(0))
|
||||
)
|
||||
|
|
||||
ec.hasName("JAVA_VERSION") and propertyName = "java.version"
|
||||
@@ -241,7 +241,7 @@ private MethodAccess getSystemPropertyFromGuava(string propertyName) {
|
||||
)
|
||||
}
|
||||
|
||||
private MethodAccess getSystemPropertyFromOperatingSystemMXBean(string propertyName) {
|
||||
private MethodCall getSystemPropertyFromOperatingSystemMXBean(string propertyName) {
|
||||
exists(Method m |
|
||||
m = result.getMethod() and
|
||||
m.getDeclaringType().hasQualifiedName("java.lang.management", "OperatingSystemMXBean")
|
||||
@@ -254,7 +254,7 @@ private MethodAccess getSystemPropertyFromOperatingSystemMXBean(string propertyN
|
||||
)
|
||||
}
|
||||
|
||||
private MethodAccess getSystemPropertyFromSpringProperties(string propertyName) {
|
||||
private MethodCall getSystemPropertyFromSpringProperties(string propertyName) {
|
||||
exists(Method m |
|
||||
m = result.getMethod() and
|
||||
m.getDeclaringType().hasQualifiedName("org.springframework.core", "SpringProperties") and
|
||||
|
||||
@@ -60,10 +60,10 @@ class AssertionMethod extends Method {
|
||||
AssertionMethod() { assertionMethod(this, _) }
|
||||
|
||||
/** Gets a call to the assertion method. */
|
||||
MethodAccess getACheck() { result.getMethod().getSourceDeclaration() = this }
|
||||
MethodCall getACheck() { result.getMethod().getSourceDeclaration() = this }
|
||||
|
||||
/** Gets a call to the assertion method with `checkedArg` as argument. */
|
||||
MethodAccess getACheck(Expr checkedArg) {
|
||||
MethodCall getACheck(Expr checkedArg) {
|
||||
result = this.getACheck() and checkedArg = result.getAnArgument()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ class FastJsonParseMethod extends Method {
|
||||
/**
|
||||
* A call to `ParserConfig.setSafeMode`.
|
||||
*/
|
||||
class FastJsonSetSafeMode extends MethodAccess {
|
||||
class FastJsonSetSafeMode extends MethodCall {
|
||||
FastJsonSetSafeMode() {
|
||||
exists(Method m |
|
||||
this.getMethod() = m and
|
||||
|
||||
@@ -44,7 +44,7 @@ class ObjectMapperReadMethod extends Method {
|
||||
}
|
||||
|
||||
/** A call that enables the default typing in `ObjectMapper`. */
|
||||
class EnableJacksonDefaultTyping extends MethodAccess {
|
||||
class EnableJacksonDefaultTyping extends MethodCall {
|
||||
EnableJacksonDefaultTyping() {
|
||||
this.getMethod().getDeclaringType() instanceof ObjectMapper and
|
||||
this.getMethod().hasName("enableDefaultTyping")
|
||||
@@ -54,7 +54,7 @@ class EnableJacksonDefaultTyping extends MethodAccess {
|
||||
/** A qualifier of a call to one of the methods in `ObjectMapper` that deserialize data. */
|
||||
class ObjectMapperReadQualifier extends DataFlow::ExprNode {
|
||||
ObjectMapperReadQualifier() {
|
||||
exists(MethodAccess ma | ma.getQualifier() = this.asExpr() |
|
||||
exists(MethodCall ma | ma.getQualifier() = this.asExpr() |
|
||||
ma.getMethod() instanceof ObjectMapperReadMethod
|
||||
)
|
||||
}
|
||||
@@ -63,7 +63,7 @@ class ObjectMapperReadQualifier extends DataFlow::ExprNode {
|
||||
/** A source that sets a type validator. */
|
||||
class SetPolymorphicTypeValidatorSource extends DataFlow::ExprNode {
|
||||
SetPolymorphicTypeValidatorSource() {
|
||||
exists(MethodAccess ma, Method m | m = ma.getMethod() |
|
||||
exists(MethodCall ma, Method m | m = ma.getMethod() |
|
||||
(
|
||||
m.getDeclaringType() instanceof ObjectMapper and
|
||||
m.hasName("setPolymorphicTypeValidator")
|
||||
@@ -83,7 +83,7 @@ class SetPolymorphicTypeValidatorSource extends DataFlow::ExprNode {
|
||||
* if passed to an unsafely-configured `ObjectMapper`'s `readValue` method.
|
||||
*/
|
||||
predicate createJacksonJsonParserStep(DataFlow::Node fromNode, DataFlow::Node toNode) {
|
||||
exists(MethodAccess ma, Method m | m = ma.getMethod() |
|
||||
exists(MethodCall ma, Method m | m = ma.getMethod() |
|
||||
(m.getDeclaringType() instanceof ObjectMapper or m.getDeclaringType() instanceof JsonFactory) and
|
||||
m.hasName("createParser") and
|
||||
ma.getArgument(0) = fromNode.asExpr() and
|
||||
@@ -98,14 +98,14 @@ predicate createJacksonJsonParserStep(DataFlow::Node fromNode, DataFlow::Node to
|
||||
* if passed to an unsafely-configured `ObjectMapper`'s `treeToValue` method.
|
||||
*/
|
||||
predicate createJacksonTreeNodeStep(DataFlow::Node fromNode, DataFlow::Node toNode) {
|
||||
exists(MethodAccess ma, Method m | m = ma.getMethod() |
|
||||
exists(MethodCall ma, Method m | m = ma.getMethod() |
|
||||
m.getDeclaringType() instanceof ObjectMapper and
|
||||
m.hasName("readTree") and
|
||||
ma.getArgument(0) = fromNode.asExpr() and
|
||||
ma = toNode.asExpr()
|
||||
)
|
||||
or
|
||||
exists(MethodAccess ma, Method m | m = ma.getMethod() |
|
||||
exists(MethodCall ma, Method m | m = ma.getMethod() |
|
||||
m.getDeclaringType() instanceof JsonParser and
|
||||
m.hasName("readValueAsTree") and
|
||||
ma.getQualifier() = fromNode.asExpr() and
|
||||
@@ -138,7 +138,7 @@ private predicate hasFieldWithJsonTypeAnnotation(RefType type) {
|
||||
* Holds if `call` is a method call to a Jackson deserialization method such as `ObjectMapper.readValue(String, Class)`,
|
||||
* and the target deserialized class has a field with a `JsonTypeInfo` annotation that enables polymorphic typing.
|
||||
*/
|
||||
predicate hasArgumentWithUnsafeJacksonAnnotation(MethodAccess call) {
|
||||
predicate hasArgumentWithUnsafeJacksonAnnotation(MethodCall call) {
|
||||
call.getMethod() instanceof ObjectMapperReadMethod and
|
||||
exists(RefType argType, int i | i > 0 and argType = call.getArgument(i).getType() |
|
||||
hasJsonTypeInfoAnnotation(argType.(ParameterizedType).getATypeArgument())
|
||||
|
||||
@@ -437,7 +437,7 @@ private predicate isXssSafeContentTypeExpr(Expr e) { isXssSafeContentType(getCon
|
||||
private DataFlow::Node getABuilderWithExplicitContentType(Expr contentType) {
|
||||
// Base case: ResponseBuilder.type(contentType)
|
||||
result.asExpr() =
|
||||
any(MethodAccess ma |
|
||||
any(MethodCall ma |
|
||||
ma.getCallee().hasQualifiedName(getAJaxRsPackage("core"), "Response$ResponseBuilder", "type") and
|
||||
contentType = ma.getArgument(0)
|
||||
)
|
||||
@@ -451,7 +451,7 @@ private DataFlow::Node getABuilderWithExplicitContentType(Expr contentType) {
|
||||
or
|
||||
// Base case: Variant[.VariantListBuilder].mediaTypes(...)
|
||||
result.asExpr() =
|
||||
any(MethodAccess ma |
|
||||
any(MethodCall ma |
|
||||
ma.getCallee()
|
||||
.hasQualifiedName(getAJaxRsPackage("core"), ["Variant", "Variant$VariantListBuilder"],
|
||||
"mediaTypes") and
|
||||
@@ -460,7 +460,7 @@ private DataFlow::Node getABuilderWithExplicitContentType(Expr contentType) {
|
||||
or
|
||||
// Recursive case: propagate through variant list building:
|
||||
result.asExpr() =
|
||||
any(MethodAccess ma |
|
||||
any(MethodCall ma |
|
||||
(
|
||||
ma.getType()
|
||||
.(RefType)
|
||||
@@ -475,14 +475,14 @@ private DataFlow::Node getABuilderWithExplicitContentType(Expr contentType) {
|
||||
or
|
||||
// Recursive case: propagate through a List.get operation
|
||||
result.asExpr() =
|
||||
any(MethodAccess ma |
|
||||
any(MethodCall ma |
|
||||
ma.getMethod().hasQualifiedName("java.util", "List<Variant>", "get") and
|
||||
ma.getQualifier() = getABuilderWithExplicitContentType(contentType).asExpr()
|
||||
)
|
||||
or
|
||||
// Recursive case: propagate through Response.ResponseBuilder operations, including the `variant(...)` operation.
|
||||
result.asExpr() =
|
||||
any(MethodAccess ma |
|
||||
any(MethodCall ma |
|
||||
ma.getType().(RefType).hasQualifiedName(getAJaxRsPackage("core"), "Response$ResponseBuilder") and
|
||||
[ma.getQualifier(), ma.getArgument(0)] =
|
||||
getABuilderWithExplicitContentType(contentType).asExpr()
|
||||
@@ -518,7 +518,7 @@ private class SanitizedResponseBuilder extends XssSanitizer {
|
||||
this = getASanitizedBuilder()
|
||||
or
|
||||
this.asExpr() =
|
||||
any(MethodAccess ma |
|
||||
any(MethodCall ma |
|
||||
ma.getMethod().hasQualifiedName(getAJaxRsPackage("core"), "Response", "ok") and
|
||||
(
|
||||
// e.g. Response.ok(sanitizeMe, new Variant("application/json", ...))
|
||||
@@ -542,19 +542,19 @@ private class SanitizedResponseBuilder extends XssSanitizer {
|
||||
private class VulnerableEntity extends XssSinkBarrier {
|
||||
VulnerableEntity() {
|
||||
this.asExpr() =
|
||||
any(MethodAccess ma |
|
||||
any(MethodCall ma |
|
||||
(
|
||||
// Vulnerable content-type already set:
|
||||
ma.getQualifier() = getAVulnerableBuilder().asExpr()
|
||||
or
|
||||
// Vulnerable content-type set in the future:
|
||||
getAVulnerableBuilder().asExpr().(MethodAccess).getQualifier*() = ma
|
||||
getAVulnerableBuilder().asExpr().(MethodCall).getQualifier*() = ma
|
||||
) and
|
||||
ma.getMethod().hasName("entity")
|
||||
).getArgument(0)
|
||||
or
|
||||
this.asExpr() =
|
||||
any(MethodAccess ma |
|
||||
any(MethodCall ma |
|
||||
(
|
||||
isXssVulnerableContentTypeExpr(ma.getArgument(1))
|
||||
or
|
||||
|
||||
@@ -33,7 +33,7 @@ class JsonIoReadObjectMethod extends Method {
|
||||
/**
|
||||
* A call to `Map.put` method, set the value of the `USE_MAPS` key to `true`.
|
||||
*/
|
||||
class JsonIoUseMapsSetter extends MethodAccess {
|
||||
class JsonIoUseMapsSetter extends MethodCall {
|
||||
JsonIoUseMapsSetter() {
|
||||
this.getMethod().getDeclaringType().getASourceSupertype*() instanceof MapType and
|
||||
this.getMethod().hasName("put") and
|
||||
@@ -51,14 +51,14 @@ deprecated class SafeJsonIoConfig extends DataFlow2::Configuration {
|
||||
SafeJsonIoConfig() { this = "UnsafeDeserialization::SafeJsonIoConfig" }
|
||||
|
||||
override predicate isSource(DataFlow::Node src) {
|
||||
exists(MethodAccess ma |
|
||||
exists(MethodCall ma |
|
||||
ma instanceof JsonIoUseMapsSetter and
|
||||
src.asExpr() = ma.getQualifier()
|
||||
)
|
||||
}
|
||||
|
||||
override predicate isSink(DataFlow::Node sink) {
|
||||
exists(MethodAccess ma |
|
||||
exists(MethodCall ma |
|
||||
ma.getMethod() instanceof JsonIoJsonToJavaMethod and
|
||||
sink.asExpr() = ma.getArgument(1)
|
||||
)
|
||||
@@ -75,14 +75,14 @@ deprecated class SafeJsonIoConfig extends DataFlow2::Configuration {
|
||||
*/
|
||||
module SafeJsonIoConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node src) {
|
||||
exists(MethodAccess ma |
|
||||
exists(MethodCall ma |
|
||||
ma instanceof JsonIoUseMapsSetter and
|
||||
src.asExpr() = ma.getQualifier()
|
||||
)
|
||||
}
|
||||
|
||||
predicate isSink(DataFlow::Node sink) {
|
||||
exists(MethodAccess ma |
|
||||
exists(MethodCall ma |
|
||||
ma.getMethod() instanceof JsonIoJsonToJavaMethod and
|
||||
sink.asExpr() = ma.getArgument(1)
|
||||
)
|
||||
|
||||
@@ -76,7 +76,7 @@ class KryoReadObjectMethod extends Method {
|
||||
/**
|
||||
* A call to `Kryo.setRegistrationRequired` that enables white-listing.
|
||||
*/
|
||||
class KryoEnableWhiteListing extends MethodAccess {
|
||||
class KryoEnableWhiteListing extends MethodCall {
|
||||
KryoEnableWhiteListing() {
|
||||
exists(Method m |
|
||||
m = this.getMethod() and
|
||||
|
||||
@@ -17,14 +17,17 @@ class MockitoVerifyMethod extends Method {
|
||||
}
|
||||
|
||||
/**
|
||||
* A MethodAccess which is called as part of a Mockito verification setup.
|
||||
* A MethodCall which is called as part of a Mockito verification setup.
|
||||
*/
|
||||
class MockitoVerifiedMethodAccess extends MethodAccess {
|
||||
MockitoVerifiedMethodAccess() {
|
||||
this.getQualifier().(MethodAccess).getMethod() instanceof MockitoVerifyMethod
|
||||
class MockitoVerifiedMethodCall extends MethodCall {
|
||||
MockitoVerifiedMethodCall() {
|
||||
this.getQualifier().(MethodCall).getMethod() instanceof MockitoVerifyMethod
|
||||
}
|
||||
}
|
||||
|
||||
/** DEPRECATED: Alias for `MockitoVerifiedMethodCall`. */
|
||||
deprecated class MockitoVerifiedMethodAccess = MockitoVerifiedMethodCall;
|
||||
|
||||
/**
|
||||
* A type that can be mocked by Mockito.
|
||||
*/
|
||||
@@ -75,9 +78,7 @@ class MockitoInitedTest extends Class {
|
||||
m.calls*(initMocks)
|
||||
)
|
||||
or
|
||||
exists(MethodAccess call | call.getCallee() = initMocks |
|
||||
call.getArgument(0).getType() = this
|
||||
)
|
||||
exists(MethodCall call | call.getCallee() = initMocks | call.getArgument(0).getType() = this)
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -383,12 +384,12 @@ class MockitoMockMethod extends Method {
|
||||
|
||||
class MockitoMockedObject extends Expr {
|
||||
MockitoMockedObject() {
|
||||
this.(MethodAccess).getMethod() instanceof MockitoMockMethod
|
||||
this.(MethodCall).getMethod() instanceof MockitoMockMethod
|
||||
or
|
||||
this.(VarAccess).getVariable().getAnAssignedValue() instanceof MockitoMockedObject
|
||||
or
|
||||
exists(ReturnStmt ret |
|
||||
this.(MethodAccess).getMethod() = ret.getEnclosingCallable() and
|
||||
this.(MethodCall).getMethod() = ret.getEnclosingCallable() and
|
||||
ret.getResult() instanceof MockitoMockedObject
|
||||
)
|
||||
}
|
||||
|
||||
@@ -114,7 +114,7 @@ class MyBatisInjectionSink extends DataFlow::Node {
|
||||
|
||||
private class MyBatisProviderStep extends TaintTracking::AdditionalValueStep {
|
||||
override predicate step(DataFlow::Node n1, DataFlow::Node n2) {
|
||||
exists(MethodAccess ma, Annotation a, Method providerMethod |
|
||||
exists(MethodCall ma, Annotation a, Method providerMethod |
|
||||
exists(int i |
|
||||
ma.getArgument(pragma[only_bind_into](i)) = n1.asExpr() and
|
||||
providerMethod.getParameter(pragma[only_bind_into](i)) = n2.asParameter()
|
||||
|
||||
@@ -16,7 +16,7 @@ class SeleniumPageFactory extends Class {
|
||||
/**
|
||||
* A call to the Selenium `PageFactory.initElements` method, to construct a page object.
|
||||
*/
|
||||
class SeleniumInitElementsAccess extends MethodAccess {
|
||||
class SeleniumInitElementsAccess extends MethodCall {
|
||||
SeleniumInitElementsAccess() {
|
||||
this.getMethod().getDeclaringType() instanceof SeleniumPageFactory and
|
||||
this.getMethod().hasName("initElements")
|
||||
|
||||
@@ -345,7 +345,7 @@ predicate isServletRequestMethod(Method m) {
|
||||
}
|
||||
|
||||
/** Holds if `ma` is a call that gets a request parameter. */
|
||||
predicate isRequestGetParamMethod(MethodAccess ma) {
|
||||
predicate isRequestGetParamMethod(MethodCall ma) {
|
||||
ma.getMethod() instanceof ServletRequestGetParameterMethod or
|
||||
ma.getMethod() instanceof ServletRequestGetParameterMapMethod or
|
||||
ma.getMethod() instanceof HttpServletRequestGetQueryStringMethod
|
||||
|
||||
@@ -53,7 +53,7 @@ private class SafeYaml extends ClassInstanceExpr {
|
||||
}
|
||||
|
||||
/** A call to a parse method of `Yaml`. */
|
||||
private class SnakeYamlParse extends MethodAccess {
|
||||
private class SnakeYamlParse extends MethodCall {
|
||||
SnakeYamlParse() {
|
||||
exists(Method m |
|
||||
m.getDeclaringType() instanceof Yaml and
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
private import semmle.code.java.dataflow.FlowSummary
|
||||
|
||||
private class CollectCall extends MethodAccess {
|
||||
private class CollectCall extends MethodCall {
|
||||
CollectCall() {
|
||||
this.getMethod()
|
||||
.getSourceDeclaration()
|
||||
@@ -10,7 +10,7 @@ private class CollectCall extends MethodAccess {
|
||||
}
|
||||
}
|
||||
|
||||
private class Collector extends MethodAccess {
|
||||
private class Collector extends MethodCall {
|
||||
Collector() {
|
||||
this.getMethod().getDeclaringType().hasQualifiedName("java.util.stream", "Collectors")
|
||||
}
|
||||
|
||||
@@ -27,7 +27,7 @@ class XStreamReadObjectMethod extends Method {
|
||||
/**
|
||||
* A call to `XStream.addPermission(NoTypePermission.NONE)`, which enables white-listing.
|
||||
*/
|
||||
class XStreamEnableWhiteListing extends MethodAccess {
|
||||
class XStreamEnableWhiteListing extends MethodCall {
|
||||
XStreamEnableWhiteListing() {
|
||||
exists(Method m |
|
||||
m = this.getMethod() and
|
||||
|
||||
@@ -15,7 +15,7 @@ private import semmle.code.java.dataflow.FlowSteps
|
||||
*/
|
||||
private class AsyncTaskExecuteAdditionalValueStep extends AdditionalTaintStep {
|
||||
override predicate step(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
exists(ExecuteAsyncTaskMethodAccess ma, AsyncTaskRunInBackgroundMethod m |
|
||||
exists(ExecuteAsyncTaskMethodCall ma, AsyncTaskRunInBackgroundMethod m |
|
||||
DataFlow::getInstanceArgument(ma).getType() = m.getDeclaringType()
|
||||
|
|
||||
node1.asExpr() = ma.getParamsArgument() and
|
||||
@@ -76,8 +76,8 @@ private class AsyncTaskInit extends Callable {
|
||||
}
|
||||
|
||||
/** A call to the `execute` or `executeOnExecutor` methods of the `android.os.AsyncTask` class. */
|
||||
private class ExecuteAsyncTaskMethodAccess extends MethodAccess {
|
||||
ExecuteAsyncTaskMethodAccess() {
|
||||
private class ExecuteAsyncTaskMethodCall extends MethodCall {
|
||||
ExecuteAsyncTaskMethodCall() {
|
||||
this.getMethod().hasName(["execute", "executeOnExecutor"]) and
|
||||
this.getMethod().getDeclaringType().getSourceDeclaration().getASourceSupertype*() instanceof
|
||||
AsyncTask
|
||||
|
||||
@@ -8,7 +8,7 @@ import java
|
||||
* A call to a live literal method.
|
||||
* This always returns a constant expression and can be considered as such.
|
||||
*/
|
||||
class LiveLiteral extends MethodAccess {
|
||||
class LiveLiteral extends MethodCall {
|
||||
LiveLiteral() {
|
||||
this.getMethod() instanceof LiveLiteralMethod and
|
||||
not this.getEnclosingCallable() instanceof LiveLiteralMethod
|
||||
@@ -25,7 +25,7 @@ class LiveLiteral extends MethodAccess {
|
||||
* This predicate gets the constant value held by the private field.
|
||||
*/
|
||||
CompileTimeConstantExpr getValue() {
|
||||
exists(MethodAccess getterCall, VarAccess va |
|
||||
exists(MethodCall getterCall, VarAccess va |
|
||||
methodReturns(this.getMethod(), getterCall) and
|
||||
methodReturns(getterCall.getMethod(), va) and
|
||||
result = va.getVariable().getInitializer()
|
||||
|
||||
@@ -154,7 +154,7 @@ class AndroidBundle extends Class {
|
||||
*/
|
||||
class ExplicitIntent extends Expr {
|
||||
ExplicitIntent() {
|
||||
exists(MethodAccess ma, Method m |
|
||||
exists(MethodCall ma, Method m |
|
||||
ma.getMethod() = m and
|
||||
m.getDeclaringType() instanceof TypeIntent and
|
||||
m.hasName(["setPackage", "setClass", "setClassName", "setComponent"]) and
|
||||
@@ -237,8 +237,8 @@ private class NewIntent extends ClassInstanceExpr {
|
||||
}
|
||||
|
||||
/** A call to a method that starts an Android component. */
|
||||
private class StartComponentMethodAccess extends MethodAccess {
|
||||
StartComponentMethodAccess() {
|
||||
private class StartComponentMethodCall extends MethodCall {
|
||||
StartComponentMethodCall() {
|
||||
this.getMethod().overrides*(any(StartActivityMethod m)) or
|
||||
this.getMethod().overrides*(any(StartServiceMethod m)) or
|
||||
this.getMethod().overrides*(any(SendBroadcastMethod m))
|
||||
@@ -263,11 +263,11 @@ private class StartComponentMethodAccess extends MethodAccess {
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `src` reaches the intent argument `arg` of `StartComponentMethodAccess`
|
||||
* Holds if `src` reaches the intent argument `arg` of `StartComponentMethodCall`
|
||||
* through intra-procedural steps.
|
||||
*/
|
||||
private predicate reaches(Expr src, Argument arg) {
|
||||
any(StartComponentMethodAccess ma).getIntentArg() = arg and
|
||||
any(StartComponentMethodCall ma).getIntentArg() = arg and
|
||||
src = arg
|
||||
or
|
||||
exists(Expr mid, BaseSsa::BaseSsaVariable ssa, BaseSsa::BaseSsaUpdate upd |
|
||||
@@ -298,7 +298,7 @@ private predicate reaches(Expr src, Argument arg) {
|
||||
*/
|
||||
private class StartActivityIntentStep extends AdditionalValueStep {
|
||||
override predicate step(DataFlow::Node n1, DataFlow::Node n2) {
|
||||
exists(StartComponentMethodAccess startActivity, MethodAccess getIntent |
|
||||
exists(StartComponentMethodCall startActivity, MethodCall getIntent |
|
||||
startActivity.getMethod().overrides*(any(StartActivityMethod m)) and
|
||||
getIntent.getMethod().overrides*(any(AndroidGetIntentMethod m)) and
|
||||
startActivity.targetsComponentType(getIntent.getReceiverType()) and
|
||||
@@ -309,11 +309,11 @@ private class StartActivityIntentStep extends AdditionalValueStep {
|
||||
}
|
||||
|
||||
/**
|
||||
* Holds if `targetType` is targeted by an existing `StartComponentMethodAccess` call
|
||||
* Holds if `targetType` is targeted by an existing `StartComponentMethodCall` call
|
||||
* and it's identified by `id`.
|
||||
*/
|
||||
private predicate isTargetableType(AndroidComponent targetType, string id) {
|
||||
exists(StartComponentMethodAccess ma | ma.targetsComponentType(targetType)) and
|
||||
exists(StartComponentMethodCall ma | ma.targetsComponentType(targetType)) and
|
||||
targetType.getQualifiedName() = id
|
||||
}
|
||||
|
||||
@@ -327,7 +327,7 @@ private class StartActivitiesSyntheticCallable extends SyntheticCallable {
|
||||
)
|
||||
}
|
||||
|
||||
override StartComponentMethodAccess getACall() {
|
||||
override StartComponentMethodCall getACall() {
|
||||
result.getMethod().hasName("startActivities") and
|
||||
result.targetsComponentType(targetType)
|
||||
}
|
||||
@@ -396,7 +396,7 @@ private class RequiredComponentStackForStartActivities extends RequiredSummaryCo
|
||||
*/
|
||||
private class SendBroadcastReceiverIntentStep extends AdditionalValueStep {
|
||||
override predicate step(DataFlow::Node n1, DataFlow::Node n2) {
|
||||
exists(StartComponentMethodAccess sendBroadcast, Method onReceive |
|
||||
exists(StartComponentMethodCall sendBroadcast, Method onReceive |
|
||||
sendBroadcast.getMethod().overrides*(any(SendBroadcastMethod m)) and
|
||||
onReceive.overrides*(any(AndroidReceiveIntentMethod m)) and
|
||||
sendBroadcast.targetsComponentType(onReceive.getDeclaringType()) and
|
||||
@@ -413,7 +413,7 @@ private class SendBroadcastReceiverIntentStep extends AdditionalValueStep {
|
||||
*/
|
||||
private class StartServiceIntentStep extends AdditionalValueStep {
|
||||
override predicate step(DataFlow::Node n1, DataFlow::Node n2) {
|
||||
exists(StartComponentMethodAccess startService, Method serviceIntent |
|
||||
exists(StartComponentMethodCall startService, Method serviceIntent |
|
||||
startService.getMethod().overrides*(any(StartServiceMethod m)) and
|
||||
serviceIntent.overrides*(any(AndroidServiceIntentMethod m)) and
|
||||
startService.targetsComponentType(serviceIntent.getDeclaringType()) and
|
||||
|
||||
@@ -37,7 +37,7 @@ class OnActivityResultIncomingIntent extends DataFlow::Node {
|
||||
or
|
||||
// A fragment calls `startActivityForResult`
|
||||
// and the activity it belongs to defines `onActivityResult`.
|
||||
exists(MethodAccess ma |
|
||||
exists(MethodCall ma |
|
||||
ma.getMethod().hasName(["add", "attach", "replace"]) and
|
||||
ma.getMethod()
|
||||
.getDeclaringType()
|
||||
@@ -71,7 +71,7 @@ private module ImplicitStartActivityForResultConfig implements DataFlow::ConfigS
|
||||
}
|
||||
|
||||
predicate isSink(DataFlow::Node sink) {
|
||||
exists(MethodAccess startActivityForResult |
|
||||
exists(MethodCall startActivityForResult |
|
||||
startActivityForResult.getMethod().hasName("startActivityForResult") and
|
||||
startActivityForResult.getMethod().getDeclaringType().getAnAncestor() instanceof
|
||||
ActivityOrFragment and
|
||||
@@ -83,7 +83,7 @@ private module ImplicitStartActivityForResultConfig implements DataFlow::ConfigS
|
||||
|
||||
predicate isAdditionalFlowStep(DataFlow::Node node1, DataFlow::Node node2) {
|
||||
// Wrapping the Intent in a chooser
|
||||
exists(MethodAccess ma, Method m |
|
||||
exists(MethodCall ma, Method m |
|
||||
ma.getMethod() = m and
|
||||
m.hasName("createChooser") and
|
||||
m.getDeclaringType() instanceof TypeIntent
|
||||
|
||||
@@ -8,7 +8,7 @@ class PendingIntent extends Class {
|
||||
}
|
||||
|
||||
/** A call to a method that creates a `PendingIntent`. */
|
||||
class PendingIntentCreation extends MethodAccess {
|
||||
class PendingIntentCreation extends MethodCall {
|
||||
PendingIntentCreation() {
|
||||
exists(Method m |
|
||||
this.getMethod() = m and
|
||||
|
||||
@@ -6,7 +6,7 @@ private import semmle.code.java.dataflow.FlowSources
|
||||
|
||||
private class EditableToStringStep extends AdditionalTaintStep {
|
||||
override predicate step(DataFlow::Node n1, DataFlow::Node n2) {
|
||||
exists(MethodAccess ma |
|
||||
exists(MethodCall ma |
|
||||
ma.getMethod().hasName("toString") and
|
||||
ma.getReceiverType().getASourceSupertype*().hasQualifiedName("android.text", "Editable") and
|
||||
n1.asExpr() = ma.getQualifier() and
|
||||
|
||||
@@ -79,7 +79,7 @@ private module SafeDigesterFlowConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node src) { src.asExpr() instanceof SafeDigester }
|
||||
|
||||
predicate isSink(DataFlow::Node sink) {
|
||||
exists(MethodAccess ma |
|
||||
exists(MethodCall ma |
|
||||
sink.asExpr() = ma.getQualifier() and ma.getMethod().getDeclaringType() instanceof Digester
|
||||
)
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ import semmle.code.java.frameworks.spring.Spring
|
||||
/**
|
||||
* A method call to a ProcessorDefinition element.
|
||||
*/
|
||||
class ProcessorDefinitionElement extends MethodAccess {
|
||||
class ProcessorDefinitionElement extends MethodCall {
|
||||
ProcessorDefinitionElement() {
|
||||
this.getMethod()
|
||||
.getDeclaringType()
|
||||
@@ -114,7 +114,7 @@ deprecated class CamelJavaDSLBeanRefDecl = CamelJavaDslBeanRefDecl;
|
||||
*
|
||||
* An expression that represents a call to a bean, or particular method on a bean.
|
||||
*/
|
||||
class CamelJavaDslMethodDecl extends MethodAccess {
|
||||
class CamelJavaDslMethodDecl extends MethodCall {
|
||||
CamelJavaDslMethodDecl() {
|
||||
this.getMethod()
|
||||
.getDeclaringType()
|
||||
|
||||
@@ -14,7 +14,7 @@ private module TypeLiteralToParseAsFlowConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node source) { source.asExpr() instanceof TypeLiteral }
|
||||
|
||||
predicate isSink(DataFlow::Node sink) {
|
||||
exists(MethodAccess ma |
|
||||
exists(MethodCall ma |
|
||||
ma.getAnArgument() = sink.asExpr() and
|
||||
ma.getMethod() instanceof ParseAsMethod
|
||||
)
|
||||
|
||||
@@ -26,7 +26,7 @@ class GsonDeserializeMethod extends Method {
|
||||
* where `T` is a concrete type implementing `Parcelable`.
|
||||
*/
|
||||
predicate intentFlowsToParcel(DataFlow::Node intentNode, DataFlow::Node parcelNode) {
|
||||
exists(MethodAccess getParcelableExtraCall, CreateFromParcelMethod cfpm, Type createdType |
|
||||
exists(MethodCall getParcelableExtraCall, CreateFromParcelMethod cfpm, Type createdType |
|
||||
intentNode.asExpr() = getParcelableExtraCall.getQualifier() and
|
||||
getParcelableExtraCall.getMethod() instanceof IntentGetParcelableExtraMethod and
|
||||
DataFlow::localExprFlow(getParcelableExtraCall, any(Expr e | e.getType() = createdType)) and
|
||||
|
||||
@@ -22,7 +22,7 @@ abstract class GsonDeserializableType extends Type { }
|
||||
/** A type whose values are explicitly deserialized in a call to a Gson method. */
|
||||
private class ExplicitlyReadGsonDeserializableType extends GsonDeserializableType {
|
||||
ExplicitlyReadGsonDeserializableType() {
|
||||
exists(MethodAccess ma |
|
||||
exists(MethodCall ma |
|
||||
// A call to a Gson read method...
|
||||
ma.getMethod() instanceof GsonReadValueMethod and
|
||||
// ...where `this` is used in the final argument, indicating that this type will be deserialized.
|
||||
|
||||
@@ -16,7 +16,7 @@ class HudsonWebMethod extends Method {
|
||||
private class HudsonUtilXssSanitizer extends XssSanitizer {
|
||||
HudsonUtilXssSanitizer() {
|
||||
this.asExpr()
|
||||
.(MethodAccess)
|
||||
.(MethodCall)
|
||||
.getMethod()
|
||||
// Not including xmlEscape because it only accounts for >, <, and &.
|
||||
// It does not account for ", or ', which makes it an incomplete XSS sanitizer.
|
||||
|
||||
@@ -68,7 +68,7 @@ private class JacksonReadValueMethod extends Method, TaintPreservingCallable {
|
||||
/** A type whose values are explicitly serialized in a call to a Jackson method. */
|
||||
private class ExplicitlyWrittenJacksonSerializableType extends JacksonSerializableType {
|
||||
ExplicitlyWrittenJacksonSerializableType() {
|
||||
exists(MethodAccess ma |
|
||||
exists(MethodCall ma |
|
||||
// A call to a Jackson write method...
|
||||
ma.getMethod() instanceof JacksonWriteValueMethod and
|
||||
// ...where `this` is used in the final argument, indicating that this type will be serialized.
|
||||
@@ -91,7 +91,7 @@ private module TypeLiteralToJacksonDatabindFlowConfig implements DataFlow::Confi
|
||||
predicate isSource(DataFlow::Node source) { source.asExpr() instanceof TypeLiteral }
|
||||
|
||||
predicate isSink(DataFlow::Node sink) {
|
||||
exists(MethodAccess ma, Method m, int i |
|
||||
exists(MethodCall ma, Method m, int i |
|
||||
ma.getArgument(i) = sink.asExpr() and
|
||||
m = ma.getMethod() and
|
||||
m.getParameterType(i) instanceof TypeClass and
|
||||
@@ -116,7 +116,7 @@ private class ExplicitlyReadJacksonDeserializableType extends JacksonDeserializa
|
||||
ExplicitlyReadJacksonDeserializableType() {
|
||||
usesType(getSourceWithFlowToJacksonDatabind().getReferencedType(), this)
|
||||
or
|
||||
exists(MethodAccess ma |
|
||||
exists(MethodCall ma |
|
||||
// A call to a Jackson read method...
|
||||
ma.getMethod() instanceof JacksonReadValueMethod and
|
||||
// ...where `this` is used in the final argument, indicating that this type will be deserialized.
|
||||
@@ -177,7 +177,7 @@ private class JacksonDeserializedTaintStep extends AdditionalTaintStep {
|
||||
* This informs Jackson to treat the annotations on the second class argument as if they were on
|
||||
* the first class argument. This allows adding annotations to library classes, for example.
|
||||
*/
|
||||
class JacksonAddMixinCall extends MethodAccess {
|
||||
class JacksonAddMixinCall extends MethodCall {
|
||||
JacksonAddMixinCall() {
|
||||
exists(Method m |
|
||||
m = this.getMethod() and
|
||||
|
||||
@@ -52,7 +52,7 @@ private module SafeValidatorFlowConfig implements DataFlow::ConfigSig {
|
||||
predicate isSource(DataFlow::Node src) { src.asExpr() instanceof SafeValidator }
|
||||
|
||||
predicate isSink(DataFlow::Node sink) {
|
||||
exists(MethodAccess ma |
|
||||
exists(MethodCall ma |
|
||||
sink.asExpr() = ma.getQualifier() and
|
||||
ma.getMethod().getDeclaringType() instanceof Validator
|
||||
)
|
||||
|
||||
@@ -135,7 +135,7 @@ class ForbiddenThisCallable extends ForbiddenCallable {
|
||||
ThisAccess forbiddenThisUse(Callable c) {
|
||||
result.getEnclosingCallable() = c and
|
||||
(
|
||||
exists(MethodAccess ma | ma.getAnArgument() = result) or
|
||||
exists(MethodCall ma | ma.getAnArgument() = result) or
|
||||
exists(ReturnStmt rs | rs.getResult() = result)
|
||||
)
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
import java
|
||||
|
||||
/** A call to Kotlin's `apply` method. */
|
||||
class KotlinApply extends MethodAccess {
|
||||
class KotlinApply extends MethodCall {
|
||||
ExtensionMethod m;
|
||||
|
||||
KotlinApply() {
|
||||
|
||||
@@ -8,7 +8,7 @@ class StringsKt extends RefType {
|
||||
}
|
||||
|
||||
/** A call to the extension method `String.toRegex` from `kotlin.text`. */
|
||||
class KtToRegex extends MethodAccess {
|
||||
class KtToRegex extends MethodCall {
|
||||
KtToRegex() {
|
||||
this.getMethod().getDeclaringType() instanceof StringsKt and
|
||||
this.getMethod().hasName("toRegex")
|
||||
|
||||
@@ -126,7 +126,7 @@ class PlayMvcHttpRequestHeaderMethods extends Method {
|
||||
/**
|
||||
* Gets a reference to the `getQueryString` method.
|
||||
*/
|
||||
MethodAccess getAQueryStringAccess() {
|
||||
MethodCall getAQueryStringAccess() {
|
||||
this.hasName("getQueryString") and result = this.getAReference()
|
||||
}
|
||||
}
|
||||
@@ -140,10 +140,10 @@ class PlayMvcResultsMethods extends Method {
|
||||
/**
|
||||
* Gets a reference to the `play.mvc.Results.ok` method.
|
||||
*/
|
||||
MethodAccess getAnOkAccess() { this.hasName("ok") and result = this.getAReference() }
|
||||
MethodCall getAnOkAccess() { this.hasName("ok") and result = this.getAReference() }
|
||||
|
||||
/**
|
||||
* Gets a reference to the `play.mvc.Results.redirect` method.
|
||||
*/
|
||||
MethodAccess getARedirectAccess() { this.hasName("redirect") and result = this.getAReference() }
|
||||
MethodCall getARedirectAccess() { this.hasName("redirect") and result = this.getAReference() }
|
||||
}
|
||||
|
||||
@@ -307,7 +307,7 @@ class SpringModelPlainMap extends SpringModel {
|
||||
SpringModelPlainMap() { this.getType() instanceof MapType }
|
||||
|
||||
override RefType getATypeInModel() {
|
||||
exists(MethodAccess methodCall |
|
||||
exists(MethodCall methodCall |
|
||||
methodCall.getQualifier() = this.getAnAccess() and
|
||||
methodCall.getCallee().hasName("put")
|
||||
|
|
||||
@@ -327,7 +327,7 @@ class SpringModelModel extends SpringModel {
|
||||
}
|
||||
|
||||
override RefType getATypeInModel() {
|
||||
exists(MethodAccess methodCall |
|
||||
exists(MethodCall methodCall |
|
||||
methodCall.getQualifier() = this.getAnAccess() and
|
||||
methodCall.getCallee().hasName("addAttribute")
|
||||
|
|
||||
|
||||
@@ -164,14 +164,14 @@ private predicate isXssSafeContentTypeExpr(Expr e) {
|
||||
|
||||
private DataFlow::Node getABodyBuilderWithExplicitContentType(Expr contentType) {
|
||||
result.asExpr() =
|
||||
any(MethodAccess ma |
|
||||
any(MethodCall ma |
|
||||
ma.getCallee()
|
||||
.hasQualifiedName("org.springframework.http", "ResponseEntity$BodyBuilder", "contentType") and
|
||||
contentType = ma.getArgument(0)
|
||||
)
|
||||
or
|
||||
result.asExpr() =
|
||||
any(MethodAccess ma |
|
||||
any(MethodCall ma |
|
||||
ma.getQualifier() = getABodyBuilderWithExplicitContentType(contentType).asExpr() and
|
||||
ma.getType()
|
||||
.(RefType)
|
||||
@@ -192,7 +192,7 @@ private DataFlow::Node getAVulnerableBodyBuilder() {
|
||||
private class SanitizedBodyCall extends XSS::XssSanitizer {
|
||||
SanitizedBodyCall() {
|
||||
this.asExpr() =
|
||||
any(MethodAccess ma |
|
||||
any(MethodCall ma |
|
||||
ma.getQualifier() = getASanitizedBodyBuilder().asExpr() and
|
||||
ma.getCallee().hasName("body")
|
||||
).getArgument(0)
|
||||
@@ -210,7 +210,7 @@ private class SanitizedBodyCall extends XSS::XssSanitizer {
|
||||
private class ExplicitlyVulnerableBodyArgument extends XSS::XssSinkBarrier {
|
||||
ExplicitlyVulnerableBodyArgument() {
|
||||
this.asExpr() =
|
||||
any(MethodAccess ma |
|
||||
any(MethodCall ma |
|
||||
ma.getQualifier() = getAVulnerableBodyBuilder().asExpr() and
|
||||
ma.getCallee().hasName("body")
|
||||
).getArgument(0)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user