mirror of
https://github.com/github/codeql.git
synced 2026-07-04 02:55:30 +02:00
Compare commits
77 Commits
codeql-cli
...
andersfugm
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b82ec0e0f9 | ||
|
|
bc2d7108f1 | ||
|
|
ccfd99a2be | ||
|
|
73e69c6466 | ||
|
|
0196150c51 | ||
|
|
a3dbdcd01a | ||
|
|
f1cc1e5c47 | ||
|
|
041a8e6adc | ||
|
|
fb424020af | ||
|
|
bda8e7dae1 | ||
|
|
37c8111c18 | ||
|
|
807bb51df7 | ||
|
|
b6abfe6e5c | ||
|
|
b3dc7009a4 | ||
|
|
e59f646870 | ||
|
|
cc3c232631 | ||
|
|
9a5cc3c5e3 | ||
|
|
3983e4db29 | ||
|
|
3058198c0d | ||
|
|
2ef06c9f96 | ||
|
|
1842382e23 | ||
|
|
db449dca6a | ||
|
|
7216d12b9a | ||
|
|
c4b4fde0d7 | ||
|
|
46382cbc8e | ||
|
|
da3d0cf977 | ||
|
|
93439db87b | ||
|
|
70ca7af04c | ||
|
|
664f0125b9 | ||
|
|
1b7f589000 | ||
|
|
eb7f8cc43d | ||
|
|
2767b8dbbf | ||
|
|
b1f60acf2c | ||
|
|
2b2613de4e | ||
|
|
14acc7fcab | ||
|
|
37ce885b0c | ||
|
|
52acaec03d | ||
|
|
d6e8555f8b | ||
|
|
b5ef15c70f | ||
|
|
5735ac330d | ||
|
|
5348c7d07c | ||
|
|
f89f304e50 | ||
|
|
ff7dc297d5 | ||
|
|
cacdc467de | ||
|
|
7b800b1dd6 | ||
|
|
1b6ff24642 | ||
|
|
3d1b6b64ed | ||
|
|
ac618e1cb2 | ||
|
|
221a54d22e | ||
|
|
5fcaac7cb2 | ||
|
|
cc215858e4 | ||
|
|
56a1b12c9e | ||
|
|
688213056c | ||
|
|
1c37688ec1 | ||
|
|
336df3ccf4 | ||
|
|
587f9c24ed | ||
|
|
456e33773b | ||
|
|
af7ae8c4cb | ||
|
|
1c4552edb0 | ||
|
|
5136d872ae | ||
|
|
474bcd4dd1 | ||
|
|
199489a225 | ||
|
|
ae4ccc651c | ||
|
|
0d845c2ea9 | ||
|
|
6d138c2bd4 | ||
|
|
85c39c04e0 | ||
|
|
1ee142d8bd | ||
|
|
a523c7f47f | ||
|
|
5f73754b95 | ||
|
|
e0fa6cf785 | ||
|
|
d1d9df7729 | ||
|
|
9bffcf81b5 | ||
|
|
f7c4e61956 | ||
|
|
575ece6ae2 | ||
|
|
f6ed5c19be | ||
|
|
4298b70f1c | ||
|
|
e88b8c53f3 |
@@ -28,7 +28,6 @@
|
|||||||
/swift/extractor/ @github/codeql-swift @github/code-scanning-language-coverage
|
/swift/extractor/ @github/codeql-swift @github/code-scanning-language-coverage
|
||||||
/misc/codegen/ @github/codeql-swift
|
/misc/codegen/ @github/codeql-swift
|
||||||
/java/kotlin-extractor/ @github/codeql-kotlin @github/code-scanning-language-coverage
|
/java/kotlin-extractor/ @github/codeql-kotlin @github/code-scanning-language-coverage
|
||||||
/java/ql/test-kotlin1/ @github/codeql-kotlin
|
|
||||||
/java/ql/test-kotlin2/ @github/codeql-kotlin
|
/java/ql/test-kotlin2/ @github/codeql-kotlin
|
||||||
|
|
||||||
# Experimental CodeQL cryptography
|
# Experimental CodeQL cryptography
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
name: codeql/actions-all
|
name: codeql/actions-all
|
||||||
version: 0.4.38
|
version: 0.4.39-dev
|
||||||
library: true
|
library: true
|
||||||
warnOnImplicitThis: true
|
warnOnImplicitThis: true
|
||||||
dependencies:
|
dependencies:
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
name: codeql/actions-queries
|
name: codeql/actions-queries
|
||||||
version: 0.6.30
|
version: 0.6.31-dev
|
||||||
library: false
|
library: false
|
||||||
warnOnImplicitThis: true
|
warnOnImplicitThis: true
|
||||||
groups: [actions, queries]
|
groups: [actions, queries]
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
name: codeql/cpp-all
|
name: codeql/cpp-all
|
||||||
version: 11.0.0
|
version: 11.0.1-dev
|
||||||
groups: cpp
|
groups: cpp
|
||||||
dbscheme: semmlecode.cpp.dbscheme
|
dbscheme: semmlecode.cpp.dbscheme
|
||||||
extractor: cpp
|
extractor: cpp
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
name: codeql/cpp-queries
|
name: codeql/cpp-queries
|
||||||
version: 1.6.5
|
version: 1.6.6-dev
|
||||||
groups:
|
groups:
|
||||||
- cpp
|
- cpp
|
||||||
- queries
|
- queries
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
name: codeql/csharp-solorigate-all
|
name: codeql/csharp-solorigate-all
|
||||||
version: 1.7.69
|
version: 1.7.70-dev
|
||||||
groups:
|
groups:
|
||||||
- csharp
|
- csharp
|
||||||
- solorigate
|
- solorigate
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
name: codeql/csharp-solorigate-queries
|
name: codeql/csharp-solorigate-queries
|
||||||
version: 1.7.69
|
version: 1.7.70-dev
|
||||||
groups:
|
groups:
|
||||||
- csharp
|
- csharp
|
||||||
- solorigate
|
- solorigate
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
name: codeql/csharp-all
|
name: codeql/csharp-all
|
||||||
version: 7.0.0
|
version: 7.0.1-dev
|
||||||
groups: csharp
|
groups: csharp
|
||||||
dbscheme: semmlecode.csharp.dbscheme
|
dbscheme: semmlecode.csharp.dbscheme
|
||||||
extractor: csharp
|
extractor: csharp
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
name: codeql/csharp-queries
|
name: codeql/csharp-queries
|
||||||
version: 1.7.5
|
version: 1.7.6-dev
|
||||||
groups:
|
groups:
|
||||||
- csharp
|
- csharp
|
||||||
- queries
|
- queries
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ toolchain go1.26.4
|
|||||||
// bazel mod tidy
|
// bazel mod tidy
|
||||||
require (
|
require (
|
||||||
golang.org/x/mod v0.37.0
|
golang.org/x/mod v0.37.0
|
||||||
golang.org/x/tools v0.46.0
|
golang.org/x/tools v0.47.0
|
||||||
)
|
)
|
||||||
|
|
||||||
require github.com/stretchr/testify v1.11.1
|
require github.com/stretchr/testify v1.11.1
|
||||||
|
|||||||
@@ -10,8 +10,8 @@ golang.org/x/mod v0.37.0 h1:vF1DjpVEshcIqoEaauuHebaLk1O1forxjxBaVn884JQ=
|
|||||||
golang.org/x/mod v0.37.0/go.mod h1:m8S8VeM9r4dzDwjrKO0a1sZP3YjeMamRRlD+fmR2Q/0=
|
golang.org/x/mod v0.37.0/go.mod h1:m8S8VeM9r4dzDwjrKO0a1sZP3YjeMamRRlD+fmR2Q/0=
|
||||||
golang.org/x/sync v0.21.0 h1:HLII4xRRTtCRkxYp4HNFF0Js/Og6q2i++KXbg0gHCwM=
|
golang.org/x/sync v0.21.0 h1:HLII4xRRTtCRkxYp4HNFF0Js/Og6q2i++KXbg0gHCwM=
|
||||||
golang.org/x/sync v0.21.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
|
golang.org/x/sync v0.21.0/go.mod h1:9xrNwdLfx4jkKbNva9FpL6vEN7evnE43NNNJQ2LF3+0=
|
||||||
golang.org/x/tools v0.46.0 h1:7jTurBkPZu4moS/Uy4OQT1M+QBlsj3wejyZwsT8Z7rk=
|
golang.org/x/tools v0.47.0 h1:7Kn5x/d1svx/PzryTsqeoZN4TZwqeH5pGWjefhLi/1Q=
|
||||||
golang.org/x/tools v0.46.0/go.mod h1:FrD85F8l+NWL+9XWBSyVSHO6Ne4jutsfIFba7AWQ5Ys=
|
golang.org/x/tools v0.47.0/go.mod h1:dFHnyTvFWY212G+h7ZY4Vsp/K3U4/7W9TyVaAul8uCA=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
name: codeql-go-consistency-queries
|
name: codeql-go-consistency-queries
|
||||||
version: 1.0.52
|
version: 1.0.53-dev
|
||||||
groups:
|
groups:
|
||||||
- go
|
- go
|
||||||
- queries
|
- queries
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
name: codeql/go-all
|
name: codeql/go-all
|
||||||
version: 7.2.0
|
version: 7.2.1-dev
|
||||||
groups: go
|
groups: go
|
||||||
dbscheme: go.dbscheme
|
dbscheme: go.dbscheme
|
||||||
extractor: go
|
extractor: go
|
||||||
|
|||||||
@@ -33,9 +33,11 @@ module StoredXss {
|
|||||||
walkFn.getACall().getArgument(1) = f.getASuccessor*()
|
walkFn.getACall().getArgument(1) = f.getASuccessor*()
|
||||||
)
|
)
|
||||||
or
|
or
|
||||||
// A call to os.FileInfo.Name
|
// The return value of a call to `os.DirEntry.Name`, `os.FileInfo.Name`
|
||||||
exists(Method m | m.implements("io/fs", "FileInfo", "Name") |
|
// or `os.File.ReadDirNames`.
|
||||||
m = this.(DataFlow::CallNode).getTarget()
|
exists(DataFlow::CallNode cn, Method m | m = cn.getTarget() and this = cn.getResult(0) |
|
||||||
|
m.implements("io/fs", ["DirEntry", "FileInfo"], "Name") or
|
||||||
|
m.hasQualifiedName("os", "File", "ReadDirNames")
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
name: codeql/go-queries
|
name: codeql/go-queries
|
||||||
version: 1.6.5
|
version: 1.6.6-dev
|
||||||
groups:
|
groups:
|
||||||
- go
|
- go
|
||||||
- queries
|
- queries
|
||||||
|
|||||||
@@ -156,12 +156,3 @@ nodes
|
|||||||
| websocketXss.go:54:3:54:38 | ... := ...[1] | semmle.label | ... := ...[1] |
|
| websocketXss.go:54:3:54:38 | ... := ...[1] | semmle.label | ... := ...[1] |
|
||||||
| websocketXss.go:55:24:55:31 | gorilla3 | semmle.label | gorilla3 |
|
| websocketXss.go:55:24:55:31 | gorilla3 | semmle.label | gorilla3 |
|
||||||
subpaths
|
subpaths
|
||||||
testFailures
|
|
||||||
| websocketXss.go:30:32:30:60 | comment | Missing result: Source[go/reflected-xss] |
|
|
||||||
| websocketXss.go:31:11:31:14 | xnet [postupdate] | Unexpected result: Source |
|
|
||||||
| websocketXss.go:34:30:34:58 | comment | Missing result: Source[go/reflected-xss] |
|
|
||||||
| websocketXss.go:35:21:35:25 | xnet2 [postupdate] | Unexpected result: Source |
|
|
||||||
| websocketXss.go:46:38:46:66 | comment | Missing result: Source[go/reflected-xss] |
|
|
||||||
| websocketXss.go:47:26:47:35 | gorillaMsg [postupdate] | Unexpected result: Source |
|
|
||||||
| websocketXss.go:50:33:50:61 | comment | Missing result: Source[go/reflected-xss] |
|
|
||||||
| websocketXss.go:51:17:51:24 | gorilla2 [postupdate] | Unexpected result: Source |
|
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
#select
|
#select
|
||||||
|
| StoredXss.go:13:21:13:36 | ...+... | StoredXss.go:13:21:13:31 | call to Name | StoredXss.go:13:21:13:36 | ...+... | Stored cross-site scripting vulnerability due to $@. | StoredXss.go:13:21:13:31 | call to Name | stored value |
|
||||||
| stored.go:30:22:30:25 | name | stored.go:18:3:18:28 | ... := ...[0] | stored.go:30:22:30:25 | name | Stored cross-site scripting vulnerability due to $@. | stored.go:18:3:18:28 | ... := ...[0] | stored value |
|
| stored.go:30:22:30:25 | name | stored.go:18:3:18:28 | ... := ...[0] | stored.go:30:22:30:25 | name | Stored cross-site scripting vulnerability due to $@. | stored.go:18:3:18:28 | ... := ...[0] | stored value |
|
||||||
| stored.go:61:22:61:25 | path | stored.go:59:30:59:33 | SSA def(path) | stored.go:61:22:61:25 | path | Stored cross-site scripting vulnerability due to $@. | stored.go:59:30:59:33 | SSA def(path) | stored value |
|
| stored.go:61:22:61:25 | path | stored.go:59:30:59:33 | SSA def(path) | stored.go:61:22:61:25 | path | Stored cross-site scripting vulnerability due to $@. | stored.go:59:30:59:33 | SSA def(path) | stored value |
|
||||||
edges
|
edges
|
||||||
|
| StoredXss.go:13:21:13:31 | call to Name | StoredXss.go:13:21:13:36 | ...+... | provenance | |
|
||||||
| stored.go:18:3:18:28 | ... := ...[0] | stored.go:25:14:25:17 | rows | provenance | Src:MaD:1 |
|
| stored.go:18:3:18:28 | ... := ...[0] | stored.go:25:14:25:17 | rows | provenance | Src:MaD:1 |
|
||||||
| stored.go:25:14:25:17 | rows | stored.go:25:29:25:33 | &... [postupdate] | provenance | FunctionModel |
|
| stored.go:25:14:25:17 | rows | stored.go:25:29:25:33 | &... [postupdate] | provenance | FunctionModel |
|
||||||
| stored.go:25:29:25:33 | &... [postupdate] | stored.go:30:22:30:25 | name | provenance | |
|
| stored.go:25:29:25:33 | &... [postupdate] | stored.go:30:22:30:25 | name | provenance | |
|
||||||
@@ -9,6 +11,8 @@ edges
|
|||||||
models
|
models
|
||||||
| 1 | Source: database/sql; DB; true; Query; ; ; ReturnValue[0]; database; manual |
|
| 1 | Source: database/sql; DB; true; Query; ; ; ReturnValue[0]; database; manual |
|
||||||
nodes
|
nodes
|
||||||
|
| StoredXss.go:13:21:13:31 | call to Name | semmle.label | call to Name |
|
||||||
|
| StoredXss.go:13:21:13:36 | ...+... | semmle.label | ...+... |
|
||||||
| stored.go:18:3:18:28 | ... := ...[0] | semmle.label | ... := ...[0] |
|
| stored.go:18:3:18:28 | ... := ...[0] | semmle.label | ... := ...[0] |
|
||||||
| stored.go:25:14:25:17 | rows | semmle.label | rows |
|
| stored.go:25:14:25:17 | rows | semmle.label | rows |
|
||||||
| stored.go:25:29:25:33 | &... [postupdate] | semmle.label | &... [postupdate] |
|
| stored.go:25:29:25:33 | &... [postupdate] | semmle.label | &... [postupdate] |
|
||||||
@@ -16,5 +20,3 @@ nodes
|
|||||||
| stored.go:59:30:59:33 | SSA def(path) | semmle.label | SSA def(path) |
|
| stored.go:59:30:59:33 | SSA def(path) | semmle.label | SSA def(path) |
|
||||||
| stored.go:61:22:61:25 | path | semmle.label | path |
|
| stored.go:61:22:61:25 | path | semmle.label | path |
|
||||||
subpaths
|
subpaths
|
||||||
testFailures
|
|
||||||
| StoredXss.go:13:39:13:63 | comment | Missing result: Alert[go/stored-xss] |
|
|
||||||
|
|||||||
@@ -27,12 +27,12 @@ func xss(w http.ResponseWriter, r *http.Request) {
|
|||||||
origin := "test"
|
origin := "test"
|
||||||
{
|
{
|
||||||
ws, _ := websocket.Dial(uri, "", origin)
|
ws, _ := websocket.Dial(uri, "", origin)
|
||||||
var xnet = make([]byte, 512) // $ Source[go/reflected-xss]
|
var xnet = make([]byte, 512)
|
||||||
ws.Read(xnet)
|
ws.Read(xnet) // $ Source[go/reflected-xss]
|
||||||
fmt.Fprintf(w, "%v", xnet) // $ Alert[go/reflected-xss]
|
fmt.Fprintf(w, "%v", xnet) // $ Alert[go/reflected-xss]
|
||||||
codec := &websocket.Codec{Marshal: marshal, Unmarshal: unmarshal}
|
codec := &websocket.Codec{Marshal: marshal, Unmarshal: unmarshal}
|
||||||
xnet2 := make([]byte, 512) // $ Source[go/reflected-xss]
|
xnet2 := make([]byte, 512)
|
||||||
codec.Receive(ws, xnet2)
|
codec.Receive(ws, xnet2) // $ Source[go/reflected-xss]
|
||||||
fmt.Fprintf(w, "%v", xnet2) // $ Alert[go/reflected-xss]
|
fmt.Fprintf(w, "%v", xnet2) // $ Alert[go/reflected-xss]
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
@@ -43,12 +43,12 @@ func xss(w http.ResponseWriter, r *http.Request) {
|
|||||||
{
|
{
|
||||||
dialer := gorilla.Dialer{}
|
dialer := gorilla.Dialer{}
|
||||||
conn, _, _ := dialer.Dial(uri, nil)
|
conn, _, _ := dialer.Dial(uri, nil)
|
||||||
var gorillaMsg = make([]byte, 512) // $ Source[go/reflected-xss]
|
var gorillaMsg = make([]byte, 512)
|
||||||
gorilla.ReadJSON(conn, gorillaMsg)
|
gorilla.ReadJSON(conn, gorillaMsg) // $ Source[go/reflected-xss]
|
||||||
fmt.Fprintf(w, "%v", gorillaMsg) // $ Alert[go/reflected-xss]
|
fmt.Fprintf(w, "%v", gorillaMsg) // $ Alert[go/reflected-xss]
|
||||||
|
|
||||||
gorilla2 := make([]byte, 512) // $ Source[go/reflected-xss]
|
gorilla2 := make([]byte, 512)
|
||||||
conn.ReadJSON(gorilla2)
|
conn.ReadJSON(gorilla2) // $ Source[go/reflected-xss]
|
||||||
fmt.Fprintf(w, "%v", gorilla2) // $ Alert[go/reflected-xss]
|
fmt.Fprintf(w, "%v", gorilla2) // $ Alert[go/reflected-xss]
|
||||||
|
|
||||||
_, gorilla3, _ := conn.ReadMessage() // $ Source[go/reflected-xss]
|
_, gorilla3, _ := conn.ReadMessage() // $ Source[go/reflected-xss]
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import com.github.codeql.utils.*
|
|||||||
import com.github.codeql.utils.versions.*
|
import com.github.codeql.utils.versions.*
|
||||||
import com.semmle.extractor.java.OdasaOutput
|
import com.semmle.extractor.java.OdasaOutput
|
||||||
import java.io.Closeable
|
import java.io.Closeable
|
||||||
|
import java.nio.file.Files
|
||||||
|
import java.nio.file.Path
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.collections.ArrayList
|
import kotlin.collections.ArrayList
|
||||||
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
|
import org.jetbrains.kotlin.backend.common.extensions.IrPluginContext
|
||||||
@@ -50,6 +52,7 @@ import org.jetbrains.kotlin.load.java.structure.JavaMethod
|
|||||||
import org.jetbrains.kotlin.load.java.structure.JavaTypeParameter
|
import org.jetbrains.kotlin.load.java.structure.JavaTypeParameter
|
||||||
import org.jetbrains.kotlin.load.java.structure.JavaTypeParameterListOwner
|
import org.jetbrains.kotlin.load.java.structure.JavaTypeParameterListOwner
|
||||||
import org.jetbrains.kotlin.load.java.structure.impl.classFiles.BinaryJavaClass
|
import org.jetbrains.kotlin.load.java.structure.impl.classFiles.BinaryJavaClass
|
||||||
|
import org.jetbrains.kotlin.fir.java.VirtualFileBasedSourceElement
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.types.Variance
|
import org.jetbrains.kotlin.types.Variance
|
||||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||||
@@ -161,11 +164,60 @@ open class KotlinFileExtractor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun javaBinaryDeclaresMethod(c: IrClass, name: String) =
|
private fun javaBinaryDeclaresMethod(c: IrClass, name: String): Boolean? {
|
||||||
((c.source as? JavaSourceElement)?.javaElement as? BinaryJavaClass)?.methods?.any {
|
// K1 path: source is JavaSourceElement wrapping a BinaryJavaClass - inspect class metadata
|
||||||
it.name.asString() == name
|
val binaryJavaClass = (c.source as? JavaSourceElement)?.javaElement as? BinaryJavaClass
|
||||||
|
if (binaryJavaClass != null) {
|
||||||
|
return binaryJavaClass.methods.any { it.name.asString() == name }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// K2 path: binary Java classes use VirtualFileBasedSourceElement instead of
|
||||||
|
// JavaSourceElement. The BinaryJavaClass is not stored in the source element, so we parse
|
||||||
|
// the class bytes directly using ASM to check if the method is explicitly declared.
|
||||||
|
val virtualFile = (c.source as? VirtualFileBasedSourceElement)?.virtualFile
|
||||||
|
if (virtualFile != null) {
|
||||||
|
if (!virtualFile.name.endsWith(".class")) return null
|
||||||
|
return try {
|
||||||
|
val bytes = virtualFile.contentsToByteArray()
|
||||||
|
var found = false
|
||||||
|
var hasKotlinMetadata = false
|
||||||
|
val reader = org.jetbrains.org.objectweb.asm.ClassReader(bytes)
|
||||||
|
reader.accept(
|
||||||
|
object : org.jetbrains.org.objectweb.asm.ClassVisitor(
|
||||||
|
org.jetbrains.org.objectweb.asm.Opcodes.ASM9
|
||||||
|
) {
|
||||||
|
override fun visitAnnotation(
|
||||||
|
descriptor: String,
|
||||||
|
visible: Boolean
|
||||||
|
): org.jetbrains.org.objectweb.asm.AnnotationVisitor? {
|
||||||
|
if (descriptor == "Lkotlin/Metadata;") hasKotlinMetadata = true
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun visitMethod(
|
||||||
|
access: Int,
|
||||||
|
methodName: String,
|
||||||
|
descriptor: String,
|
||||||
|
signature: String?,
|
||||||
|
exceptions: Array<String>?
|
||||||
|
): org.jetbrains.org.objectweb.asm.MethodVisitor? {
|
||||||
|
if (methodName == name) found = true
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
org.jetbrains.org.objectweb.asm.ClassReader.SKIP_CODE or
|
||||||
|
org.jetbrains.org.objectweb.asm.ClassReader.SKIP_DEBUG or
|
||||||
|
org.jetbrains.org.objectweb.asm.ClassReader.SKIP_FRAMES
|
||||||
|
)
|
||||||
|
if (hasKotlinMetadata) false else found
|
||||||
|
} catch (e: Exception) {
|
||||||
|
logger.warn("Failed to check binary class methods for ${c.fqNameWhenAvailable}: $e")
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
private fun isJavaBinaryDeclaration(f: IrFunction) =
|
private fun isJavaBinaryDeclaration(f: IrFunction) =
|
||||||
f.parentClassOrNull?.let { javaBinaryDeclaresMethod(it, f.name.asString()) } ?: false
|
f.parentClassOrNull?.let { javaBinaryDeclaresMethod(it, f.name.asString()) } ?: false
|
||||||
|
|
||||||
@@ -175,7 +227,14 @@ open class KotlinFileExtractor(
|
|||||||
when (d.name.asString()) {
|
when (d.name.asString()) {
|
||||||
"toString" -> d.codeQlValueParameters.isEmpty()
|
"toString" -> d.codeQlValueParameters.isEmpty()
|
||||||
"hashCode" -> d.codeQlValueParameters.isEmpty()
|
"hashCode" -> d.codeQlValueParameters.isEmpty()
|
||||||
"equals" -> d.codeQlValueParameters.singleOrNull()?.type?.isNullableAny() ?: false
|
// Under K2 (language version 2.0+), the Object.equals(Object) parameter is
|
||||||
|
// typed as Any (non-nullable) rather than Any? (nullable). Under K1 it is Any?.
|
||||||
|
// Accept both so the redeclaration is recovered consistently across compilers.
|
||||||
|
"equals" ->
|
||||||
|
d.codeQlValueParameters
|
||||||
|
.singleOrNull()
|
||||||
|
?.type
|
||||||
|
?.let { it.isNullableAny() || it.isAny() } ?: false
|
||||||
else -> false
|
else -> false
|
||||||
} && isJavaBinaryDeclaration(d)
|
} && isJavaBinaryDeclaration(d)
|
||||||
else -> false
|
else -> false
|
||||||
@@ -1312,27 +1371,28 @@ open class KotlinFileExtractor(
|
|||||||
): TypeResults {
|
): TypeResults {
|
||||||
with("value parameter", vp) {
|
with("value parameter", vp) {
|
||||||
val location = locOverride ?: getLocation(vp, classTypeArgsIncludingOuterClasses)
|
val location = locOverride ?: getLocation(vp, classTypeArgsIncludingOuterClasses)
|
||||||
|
val parentFunction = vp.parent as? IrFunction
|
||||||
|
val javaCallable = parentFunction?.let { getJavaCallable(it) }
|
||||||
val maybeAlteredType =
|
val maybeAlteredType =
|
||||||
(vp.parent as? IrFunction)?.let {
|
parentFunction?.let {
|
||||||
if (overridesCollectionsMethodWithAlteredParameterTypes(it))
|
if (overridesCollectionsMethodWithAlteredParameterTypes(it))
|
||||||
eraseCollectionsMethodParameterType(vp.type, it.name.asString(), idx)
|
eraseCollectionsMethodParameterType(vp.type, it.name.asString(), idx)
|
||||||
else if (
|
else if (
|
||||||
(vp.parent as? IrConstructor)?.parentClassOrNull?.kind ==
|
(parentFunction as? IrConstructor)?.parentClassOrNull?.kind ==
|
||||||
ClassKind.ANNOTATION_CLASS
|
ClassKind.ANNOTATION_CLASS
|
||||||
)
|
)
|
||||||
kClassToJavaClass(vp.type)
|
kClassToJavaClass(vp.type)
|
||||||
else null
|
else null
|
||||||
} ?: vp.type
|
} ?: vp.type
|
||||||
val javaType =
|
val javaType = javaCallable?.let { jCallable -> getJavaValueParameterType(jCallable, idx) }
|
||||||
(vp.parent as? IrFunction)?.let {
|
val addParameterWildcardsByDefault =
|
||||||
getJavaCallable(it)?.let { jCallable ->
|
!getInnermostWildcardSupppressionAnnotation(vp) &&
|
||||||
getJavaValueParameterType(jCallable, idx)
|
!(javaCallable == null &&
|
||||||
}
|
parentFunction?.origin == IrDeclarationOrigin.IR_EXTERNAL_JAVA_DECLARATION_STUB)
|
||||||
}
|
|
||||||
val typeWithWildcards =
|
val typeWithWildcards =
|
||||||
addJavaLoweringWildcards(
|
addJavaLoweringWildcards(
|
||||||
maybeAlteredType,
|
maybeAlteredType,
|
||||||
!getInnermostWildcardSupppressionAnnotation(vp),
|
addParameterWildcardsByDefault,
|
||||||
javaType
|
javaType
|
||||||
)
|
)
|
||||||
val substitutedType =
|
val substitutedType =
|
||||||
@@ -1346,9 +1406,9 @@ open class KotlinFileExtractor(
|
|||||||
vp.origin == IrDeclarationOrigin.UNDERSCORE_PARAMETER ||
|
vp.origin == IrDeclarationOrigin.UNDERSCORE_PARAMETER ||
|
||||||
((vp.parent as? IrFunction)?.let { hasSynthesizedParameterNames(it) } ?: true)
|
((vp.parent as? IrFunction)?.let { hasSynthesizedParameterNames(it) } ?: true)
|
||||||
val javaParameter =
|
val javaParameter =
|
||||||
when (val callable = (vp.parent as? IrFunction)?.let { getJavaCallable(it) }) {
|
when (javaCallable) {
|
||||||
is JavaConstructor -> callable.valueParameters.getOrNull(idx)
|
is JavaConstructor -> javaCallable.valueParameters.getOrNull(idx)
|
||||||
is JavaMethod -> callable.valueParameters.getOrNull(idx)
|
is JavaMethod -> javaCallable.valueParameters.getOrNull(idx)
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
val extraAnnotations =
|
val extraAnnotations =
|
||||||
@@ -2874,6 +2934,52 @@ open class KotlinFileExtractor(
|
|||||||
return v
|
return v
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val sourceTextCache = mutableMapOf<String, String?>()
|
||||||
|
|
||||||
|
private fun getCurrentFileSourceText() =
|
||||||
|
sourceTextCache.getOrPut(filePath) {
|
||||||
|
runCatching { Files.readString(Path.of(filePath)) }.getOrNull()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getVariableNameLocation(v: IrVariable): Label<DbLocation>? {
|
||||||
|
if (v.startOffset < 0 || v.endOffset < v.startOffset) return null
|
||||||
|
|
||||||
|
val source = getCurrentFileSourceText() ?: return null
|
||||||
|
if (v.startOffset >= source.length) return null
|
||||||
|
|
||||||
|
val name = v.name.asString()
|
||||||
|
if (name.isEmpty()) return null
|
||||||
|
|
||||||
|
val endExclusive = minOf(v.endOffset + 1, source.length)
|
||||||
|
val declarationText = source.substring(v.startOffset, endExclusive)
|
||||||
|
val nameOffsetInDeclaration = declarationText.indexOf(name)
|
||||||
|
if (nameOffsetInDeclaration < 0) return null
|
||||||
|
|
||||||
|
val nameStartOffset = v.startOffset + nameOffsetInDeclaration
|
||||||
|
// getLocation treats the end offset as exclusive (matching IR's getEndOffset), so the
|
||||||
|
// identifier span is [nameStartOffset, nameStartOffset + name.length).
|
||||||
|
val nameEndOffset = nameStartOffset + name.length
|
||||||
|
return tw.getLocation(nameStartOffset, nameEndOffset)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun shouldUseVariableNameLocation(v: IrVariable): Boolean {
|
||||||
|
// For a variable initialised by an IMPLICIT_NOTNULL coercion (a platform-type not-null
|
||||||
|
// assertion), the K2 frontend widens the IrVariable span to cover the coercion, which would
|
||||||
|
// shift the location away from the identifier. Anchor those to the name token instead.
|
||||||
|
// Variables without this coercion keep the location-provider span, which already points at
|
||||||
|
// the identifier.
|
||||||
|
val initializer = v.initializer
|
||||||
|
return initializer is IrTypeOperatorCall && initializer.operator == IrTypeOperator.IMPLICIT_NOTNULL
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getVariableLocation(v: IrVariable): Label<DbLocation> {
|
||||||
|
if (shouldUseVariableNameLocation(v)) {
|
||||||
|
val nameLocation = getVariableNameLocation(v)
|
||||||
|
if (nameLocation != null) return nameLocation
|
||||||
|
}
|
||||||
|
return tw.getLocation(getVariableLocationProvider(v))
|
||||||
|
}
|
||||||
|
|
||||||
private fun extractVariable(
|
private fun extractVariable(
|
||||||
v: IrVariable,
|
v: IrVariable,
|
||||||
callable: Label<out DbCallable>,
|
callable: Label<out DbCallable>,
|
||||||
@@ -2882,7 +2988,7 @@ open class KotlinFileExtractor(
|
|||||||
) {
|
) {
|
||||||
with("variable", v) {
|
with("variable", v) {
|
||||||
val stmtId = tw.getFreshIdLabel<DbLocalvariabledeclstmt>()
|
val stmtId = tw.getFreshIdLabel<DbLocalvariabledeclstmt>()
|
||||||
val locId = tw.getLocation(getVariableLocationProvider(v))
|
val locId = getVariableLocation(v)
|
||||||
tw.writeStmts_localvariabledeclstmt(stmtId, parent, idx, callable)
|
tw.writeStmts_localvariabledeclstmt(stmtId, parent, idx, callable)
|
||||||
tw.writeHasLocation(stmtId, locId)
|
tw.writeHasLocation(stmtId, locId)
|
||||||
extractVariableExpr(v, callable, stmtId, 1, stmtId)
|
extractVariableExpr(v, callable, stmtId, 1, stmtId)
|
||||||
@@ -2900,7 +3006,7 @@ open class KotlinFileExtractor(
|
|||||||
with("variable expr", v) {
|
with("variable expr", v) {
|
||||||
val varId = useVariable(v)
|
val varId = useVariable(v)
|
||||||
val exprId = tw.getFreshIdLabel<DbLocalvariabledeclexpr>()
|
val exprId = tw.getFreshIdLabel<DbLocalvariabledeclexpr>()
|
||||||
val locId = tw.getLocation(getVariableLocationProvider(v))
|
val locId = getVariableLocation(v)
|
||||||
val type = useType(v.type)
|
val type = useType(v.type)
|
||||||
tw.writeLocalvars(varId, v.name.asString(), type.javaResult.id, exprId)
|
tw.writeLocalvars(varId, v.name.asString(), type.javaResult.id, exprId)
|
||||||
tw.writeLocalvarsKotlinType(varId, type.kotlinResult.id)
|
tw.writeLocalvarsKotlinType(varId, type.kotlinResult.id)
|
||||||
@@ -4066,6 +4172,28 @@ open class KotlinFileExtractor(
|
|||||||
else -> false
|
else -> false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun getCallResultType(c: IrCall, syntacticCallTarget: IrFunction): IrType {
|
||||||
|
if (syntacticCallTarget.origin != IrDeclarationOrigin.IR_EXTERNAL_JAVA_DECLARATION_STUB) {
|
||||||
|
return c.type
|
||||||
|
}
|
||||||
|
|
||||||
|
val primitiveInfo =
|
||||||
|
(c.type as? IrSimpleType)?.let { primitiveTypeMapping.getPrimitiveInfo(it) } ?: return c.type
|
||||||
|
val parentClass = syntacticCallTarget.parentClassOrNull ?: return c.type
|
||||||
|
val returnIsClassifier =
|
||||||
|
javaBinaryMethodReturnIsClassifierType(
|
||||||
|
parentClass,
|
||||||
|
getFunctionShortName(syntacticCallTarget).nameInDB,
|
||||||
|
syntacticCallTarget.codeQlValueParameters.size,
|
||||||
|
syntacticCallTarget is IrConstructor
|
||||||
|
)
|
||||||
|
return if (returnIsClassifier == true) {
|
||||||
|
primitiveInfo.javaClass.symbol.typeWith()
|
||||||
|
} else {
|
||||||
|
c.type
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun isGenericArrayType(typeName: String) =
|
private fun isGenericArrayType(typeName: String) =
|
||||||
when (typeName) {
|
when (typeName) {
|
||||||
"Array" -> true
|
"Array" -> true
|
||||||
@@ -4111,7 +4239,7 @@ open class KotlinFileExtractor(
|
|||||||
extractRawMethodAccess(
|
extractRawMethodAccess(
|
||||||
syntacticCallTarget,
|
syntacticCallTarget,
|
||||||
c,
|
c,
|
||||||
c.type,
|
getCallResultType(c, syntacticCallTarget),
|
||||||
callable,
|
callable,
|
||||||
parent,
|
parent,
|
||||||
idx,
|
idx,
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ import org.jetbrains.kotlin.load.java.BuiltinMethodsWithSpecialGenericSignature
|
|||||||
import org.jetbrains.kotlin.load.java.JvmAbi
|
import org.jetbrains.kotlin.load.java.JvmAbi
|
||||||
import org.jetbrains.kotlin.load.java.sources.JavaSourceElement
|
import org.jetbrains.kotlin.load.java.sources.JavaSourceElement
|
||||||
import org.jetbrains.kotlin.load.java.structure.*
|
import org.jetbrains.kotlin.load.java.structure.*
|
||||||
|
import org.jetbrains.kotlin.load.java.structure.impl.classFiles.BinaryJavaClass
|
||||||
import org.jetbrains.kotlin.load.java.typeEnhancement.hasEnhancedNullability
|
import org.jetbrains.kotlin.load.java.typeEnhancement.hasEnhancedNullability
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
import org.jetbrains.kotlin.name.NameUtils
|
import org.jetbrains.kotlin.name.NameUtils
|
||||||
@@ -996,7 +997,20 @@ open class KotlinUsesExtractor(
|
|||||||
)
|
)
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
return extractFileClass(fqName)
|
val fileClassId = extractFileClass(fqName)
|
||||||
|
// Under K2, external file class members sit directly under IrExternalPackageFragment
|
||||||
|
// rather than under their IrClass parent. In that case the file class entity won't
|
||||||
|
// get a location set through the normal extractClassSource path.
|
||||||
|
if (d is IrMemberWithContainerSource && tw.lm.externalFileClassLocationsExtracted.add(fqName)) {
|
||||||
|
val binaryPath =
|
||||||
|
getContainerSourceBinaryPath(d.containerSource)
|
||||||
|
?.let { normalizeExternalFileClassBinaryPath(it, fqName) }
|
||||||
|
if (binaryPath != null && shouldUseConcreteExternalFileClassLocation(binaryPath)) {
|
||||||
|
val fileId = tw.mkFileId(binaryPath, true)
|
||||||
|
tw.writeHasLocation(fileClassId, tw.getWholeFileLocation(fileId))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return fileClassId
|
||||||
}
|
}
|
||||||
return useDeclarationParent(parent, canBeTopLevel, classTypeArguments, inReceiverContext)
|
return useDeclarationParent(parent, canBeTopLevel, classTypeArguments, inReceiverContext)
|
||||||
}
|
}
|
||||||
@@ -1371,8 +1385,13 @@ open class KotlinUsesExtractor(
|
|||||||
parentId: Label<out DbElement>,
|
parentId: Label<out DbElement>,
|
||||||
classTypeArgsIncludingOuterClasses: List<IrTypeArgument>?,
|
classTypeArgsIncludingOuterClasses: List<IrTypeArgument>?,
|
||||||
maybeParameterList: List<IrValueParameter>? = null
|
maybeParameterList: List<IrValueParameter>? = null
|
||||||
): String =
|
): String {
|
||||||
getFunctionLabel(
|
val javaCallable = getJavaCallable(f)
|
||||||
|
val addParameterWildcardsByDefault =
|
||||||
|
!getInnermostWildcardSupppressionAnnotation(f) &&
|
||||||
|
!(javaCallable == null && f.origin == IrDeclarationOrigin.IR_EXTERNAL_JAVA_DECLARATION_STUB)
|
||||||
|
|
||||||
|
return getFunctionLabel(
|
||||||
f.parent,
|
f.parent,
|
||||||
parentId,
|
parentId,
|
||||||
getFunctionShortName(f).nameInDB,
|
getFunctionShortName(f).nameInDB,
|
||||||
@@ -1382,9 +1401,10 @@ open class KotlinUsesExtractor(
|
|||||||
getFunctionTypeParameters(f),
|
getFunctionTypeParameters(f),
|
||||||
classTypeArgsIncludingOuterClasses,
|
classTypeArgsIncludingOuterClasses,
|
||||||
overridesCollectionsMethodWithAlteredParameterTypes(f),
|
overridesCollectionsMethodWithAlteredParameterTypes(f),
|
||||||
getJavaCallable(f),
|
javaCallable,
|
||||||
!getInnermostWildcardSupppressionAnnotation(f)
|
addParameterWildcardsByDefault
|
||||||
)
|
)
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* This function actually generates the label for a function.
|
* This function actually generates the label for a function.
|
||||||
@@ -1471,15 +1491,41 @@ open class KotlinUsesExtractor(
|
|||||||
// Finally, mimic the Java extractor's behaviour by naming functions with type
|
// Finally, mimic the Java extractor's behaviour by naming functions with type
|
||||||
// parameters for their erased types;
|
// parameters for their erased types;
|
||||||
// those without type parameters are named for the generic type.
|
// those without type parameters are named for the generic type.
|
||||||
val maybeErased =
|
var maybeErased =
|
||||||
if (functionTypeParameters.isEmpty()) maybeSubbed else erase(maybeSubbed)
|
if (functionTypeParameters.isEmpty()) maybeSubbed else erase(maybeSubbed)
|
||||||
|
// K2 compatibility: under K2, Java @NotNull reference types such as @NotNull Integer
|
||||||
|
// are enhanced to Kotlin primitives (e.g. kotlin.Int). But the Java extractor uses
|
||||||
|
// the original reference type (java.lang.Integer) in callable labels. When we detect
|
||||||
|
// that the original Java parameter type is a reference (classifier) type but the
|
||||||
|
// Kotlin IR type is a primitive, revert to the boxed Java class so both extractors
|
||||||
|
// produce matching callable IDs.
|
||||||
|
if (functionTypeParameters.isEmpty()) {
|
||||||
|
val primitiveInfo = (maybeErased as? IrSimpleType)?.let {
|
||||||
|
primitiveTypeMapping.getPrimitiveInfo(it)
|
||||||
|
}
|
||||||
|
if (primitiveInfo != null) {
|
||||||
|
val parentClass = parent as? IrClass
|
||||||
|
if (parentClass != null) {
|
||||||
|
val isClassifierType = javaBinaryMethodParamIsClassifierType(
|
||||||
|
parentClass,
|
||||||
|
name,
|
||||||
|
allParamTypes.size,
|
||||||
|
name == "<init>",
|
||||||
|
it.index
|
||||||
|
)
|
||||||
|
if (isClassifierType == true) {
|
||||||
|
maybeErased = primitiveInfo.javaClass.symbol.typeWith()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
"{${useType(maybeErased).javaResult.id}}"
|
"{${useType(maybeErased).javaResult.id}}"
|
||||||
}
|
}
|
||||||
val paramTypeIds =
|
val paramTypeIds =
|
||||||
allParamTypes
|
allParamTypes
|
||||||
.withIndex()
|
.withIndex()
|
||||||
.joinToString(separator = ",", transform = getIdForFunctionLabel)
|
.joinToString(separator = ",", transform = getIdForFunctionLabel)
|
||||||
val labelReturnType =
|
var labelReturnType =
|
||||||
if (name == "<init>") pluginContext.irBuiltIns.unitType
|
if (name == "<init>") pluginContext.irBuiltIns.unitType
|
||||||
else
|
else
|
||||||
erase(
|
erase(
|
||||||
@@ -1489,6 +1535,28 @@ open class KotlinUsesExtractor(
|
|||||||
pluginContext
|
pluginContext
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
// K2 compatibility: same as for parameters, if the Java binary method return type is a
|
||||||
|
// reference type but K2 enhanced it to a Kotlin primitive, use the boxed Java class.
|
||||||
|
if (functionTypeParameters.isEmpty() && name != "<init>") {
|
||||||
|
val primitiveInfo = (labelReturnType as? IrSimpleType)?.let {
|
||||||
|
primitiveTypeMapping.getPrimitiveInfo(it)
|
||||||
|
}
|
||||||
|
if (primitiveInfo != null) {
|
||||||
|
val parentClass = parent as? IrClass
|
||||||
|
if (parentClass != null) {
|
||||||
|
val returnIsClassifier =
|
||||||
|
javaBinaryMethodReturnIsClassifierType(
|
||||||
|
parentClass,
|
||||||
|
name,
|
||||||
|
allParamTypes.size,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
if (returnIsClassifier == true) {
|
||||||
|
labelReturnType = primitiveInfo.javaClass.symbol.typeWith()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
// Note that `addJavaLoweringWildcards` is not required here because the return type used to
|
// Note that `addJavaLoweringWildcards` is not required here because the return type used to
|
||||||
// form the function
|
// form the function
|
||||||
// label is always erased.
|
// label is always erased.
|
||||||
@@ -1594,9 +1662,23 @@ open class KotlinUsesExtractor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
@OptIn(ObsoleteDescriptorBasedAPI::class)
|
@OptIn(ObsoleteDescriptorBasedAPI::class)
|
||||||
fun getJavaCallable(f: IrFunction) =
|
fun getJavaCallable(f: IrFunction): JavaMember? {
|
||||||
(f.descriptor.source as? JavaSourceElement)?.javaElement as? JavaMember
|
val fromDescriptor = (f.descriptor.source as? JavaSourceElement)?.javaElement as? JavaMember
|
||||||
|
if (fromDescriptor != null) return fromDescriptor
|
||||||
|
|
||||||
|
// K2 fallback: under K2, descriptor.source may not carry JavaSourceElement for binary Java
|
||||||
|
// methods. Try to get the JavaMember from the parent class's binary class directly.
|
||||||
|
val parentClass = f.parentClassOrNull ?: return null
|
||||||
|
val binaryJavaClass = (parentClass.source as? JavaSourceElement)?.javaElement as? BinaryJavaClass
|
||||||
|
?: return null
|
||||||
|
val name = getFunctionShortName(f).nameInDB
|
||||||
|
val nParams = f.codeQlValueParameters.size
|
||||||
|
return if (f is IrConstructor) {
|
||||||
|
binaryJavaClass.constructors.find { it.valueParameters.size == nParams }
|
||||||
|
} else {
|
||||||
|
binaryJavaClass.methods.find { it.name.asString() == name && it.valueParameters.size == nParams }
|
||||||
|
}
|
||||||
|
}
|
||||||
fun getJavaValueParameterType(m: JavaMember, idx: Int) =
|
fun getJavaValueParameterType(m: JavaMember, idx: Int) =
|
||||||
when (m) {
|
when (m) {
|
||||||
is JavaMethod -> m.valueParameters[idx].type
|
is JavaMethod -> m.valueParameters[idx].type
|
||||||
|
|||||||
@@ -51,6 +51,13 @@ class TrapLabelManager {
|
|||||||
* to avoid duplication.
|
* to avoid duplication.
|
||||||
*/
|
*/
|
||||||
val fileClassLocationsExtracted = HashSet<IrFile>()
|
val fileClassLocationsExtracted = HashSet<IrFile>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tracks external file classes (by FqName) whose location has been set from a binary path.
|
||||||
|
* Used to avoid writing duplicate hasLocation facts for external file class entities extracted
|
||||||
|
* through the K2 code path where declarations sit directly under IrExternalPackageFragment.
|
||||||
|
*/
|
||||||
|
val externalFileClassLocationsExtracted = HashSet<org.jetbrains.kotlin.name.FqName>()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import org.jetbrains.kotlin.load.kotlin.JvmPackagePartSource
|
|||||||
import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinarySourceElement
|
import org.jetbrains.kotlin.load.kotlin.KotlinJvmBinarySourceElement
|
||||||
import org.jetbrains.kotlin.load.kotlin.VirtualFileKotlinClass
|
import org.jetbrains.kotlin.load.kotlin.VirtualFileKotlinClass
|
||||||
import org.jetbrains.kotlin.name.FqName
|
import org.jetbrains.kotlin.name.FqName
|
||||||
|
import org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource
|
||||||
|
|
||||||
// Adapted from Kotlin's interpreter/Utils.kt function 'internalName'
|
// Adapted from Kotlin's interpreter/Utils.kt function 'internalName'
|
||||||
// Translates class names into their JLS section 13.1 binary name,
|
// Translates class names into their JLS section 13.1 binary name,
|
||||||
@@ -176,15 +177,238 @@ fun getIrDeclarationBinaryPath(d: IrDeclaration): String? {
|
|||||||
// This is in a file class.
|
// This is in a file class.
|
||||||
val fqName = getFileClassFqName(d)
|
val fqName = getFileClassFqName(d)
|
||||||
if (fqName != null) {
|
if (fqName != null) {
|
||||||
|
if (d is IrMemberWithContainerSource) {
|
||||||
|
val containerBinaryPath = getContainerSourceBinaryPath(d.containerSource)
|
||||||
|
if (containerBinaryPath != null) {
|
||||||
|
return normalizeExternalFileClassBinaryPath(containerBinaryPath, fqName)
|
||||||
|
}
|
||||||
|
}
|
||||||
return getUnknownBinaryLocation(fqName.asString())
|
return getUnknownBinaryLocation(fqName.asString())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempts to get the binary file path from a container source (typically a
|
||||||
|
* [JvmPackagePartSource]). Returns null if the path is unavailable.
|
||||||
|
*/
|
||||||
|
fun getContainerSourceBinaryPath(containerSource: org.jetbrains.kotlin.serialization.deserialization.descriptors.DeserializedContainerSource?): String? {
|
||||||
|
if (containerSource !is JvmPackagePartSource) return null
|
||||||
|
val binaryClass = containerSource.knownJvmBinaryClass ?: return null
|
||||||
|
return when (binaryClass) {
|
||||||
|
is VirtualFileKotlinClass -> {
|
||||||
|
val vf = binaryClass.file
|
||||||
|
val path = vf.path
|
||||||
|
if (vf.fileSystem.protocol == StandardFileSystems.JRT_PROTOCOL)
|
||||||
|
"/${path.split("!/", limit = 2)[1]}"
|
||||||
|
else path
|
||||||
|
}
|
||||||
|
else -> binaryClass.location.takeIf { it.isNotEmpty() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun getUnknownBinaryLocation(s: String): String {
|
private fun getUnknownBinaryLocation(s: String): String {
|
||||||
return "/!unknown-binary-location/${s.replace(".", "/")}.class"
|
return "/!unknown-binary-location/${s.replace(".", "/")}.class"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun normalizeExternalFileClassBinaryPath(path: String, fqName: FqName): String {
|
||||||
|
if (path.contains(".kotlinc_installed")) {
|
||||||
|
return getUnknownBinaryLocation(fqName.asString())
|
||||||
|
}
|
||||||
|
val normalizedPath = path.replace('\\', '/')
|
||||||
|
val classInternalPath = "${fqName.asString().replace(".", "/")}.class"
|
||||||
|
val classSuffix = "/$classInternalPath"
|
||||||
|
if (normalizedPath.endsWith(classSuffix)) {
|
||||||
|
val classpathRoot = normalizedPath.removeSuffix(classSuffix).substringAfterLast('/')
|
||||||
|
if (classpathRoot.isNotEmpty()) {
|
||||||
|
return "$classpathRoot/$classInternalPath"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return path
|
||||||
|
}
|
||||||
|
|
||||||
|
fun shouldUseConcreteExternalFileClassLocation(path: String): Boolean {
|
||||||
|
val normalizedPath = path.replace('\\', '/')
|
||||||
|
return normalizedPath.contains("/") &&
|
||||||
|
!normalizedPath.startsWith("/!unknown-binary-location/")
|
||||||
|
}
|
||||||
|
|
||||||
fun getJavaEquivalentClassId(c: IrClass) =
|
fun getJavaEquivalentClassId(c: IrClass) =
|
||||||
c.fqNameWhenAvailable?.toUnsafe()?.let { JavaToKotlinClassMap.mapKotlinToJava(it) }
|
c.fqNameWhenAvailable?.toUnsafe()?.let { JavaToKotlinClassMap.mapKotlinToJava(it) }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether a specific parameter of a Java binary method (identified by [methodName] and
|
||||||
|
* [paramIndex]) is a reference type (as opposed to a Java primitive). This is used to detect
|
||||||
|
* cases where K2 FIR has enhanced a reference type parameter (e.g. `@NotNull Integer`) to a
|
||||||
|
* Kotlin primitive (e.g. `kotlin.Int`), so that callable labels can use the original reference
|
||||||
|
* type and remain compatible with the Java extractor's callable IDs.
|
||||||
|
*
|
||||||
|
* Under K1, binary Java classes use [JavaSourceElement] and we can check [BinaryJavaClass.methods]
|
||||||
|
* directly. Under K2, they use [VirtualFileBasedSourceElement] and we fall back to reading the
|
||||||
|
* class bytes with ASM.
|
||||||
|
*
|
||||||
|
* Returns `null` if the information cannot be determined.
|
||||||
|
*/
|
||||||
|
fun javaBinaryMethodParamIsClassifierType(
|
||||||
|
parentClass: IrClass,
|
||||||
|
methodName: String,
|
||||||
|
nParams: Int,
|
||||||
|
isConstructor: Boolean,
|
||||||
|
paramIndex: Int
|
||||||
|
): Boolean? {
|
||||||
|
// K1 path: binary Java class has JavaSourceElement with a BinaryJavaClass.
|
||||||
|
val k1ParamKinds =
|
||||||
|
((parentClass.source as? JavaSourceElement)?.javaElement as? BinaryJavaClass)?.let {
|
||||||
|
binaryJavaClass ->
|
||||||
|
if (isConstructor)
|
||||||
|
binaryJavaClass.constructors
|
||||||
|
.asSequence()
|
||||||
|
.filter { it.valueParameters.size == nParams }
|
||||||
|
.mapNotNull { it.valueParameters.getOrNull(paramIndex)?.type }
|
||||||
|
.map { it is org.jetbrains.kotlin.load.java.structure.JavaClassifierType }
|
||||||
|
.toSet()
|
||||||
|
else
|
||||||
|
binaryJavaClass.methods
|
||||||
|
.asSequence()
|
||||||
|
.filter { it.name.asString() == methodName && it.valueParameters.size == nParams }
|
||||||
|
.mapNotNull { it.valueParameters.getOrNull(paramIndex)?.type }
|
||||||
|
.map { it is org.jetbrains.kotlin.load.java.structure.JavaClassifierType }
|
||||||
|
.toSet()
|
||||||
|
}
|
||||||
|
if (k1ParamKinds != null && k1ParamKinds.isNotEmpty()) {
|
||||||
|
return k1ParamKinds.singleOrNull()
|
||||||
|
}
|
||||||
|
|
||||||
|
// K2 path: binary Java class has VirtualFileBasedSourceElement
|
||||||
|
val k2Source = parentClass.source as? VirtualFileBasedSourceElement ?: return null
|
||||||
|
val vf = k2Source.virtualFile
|
||||||
|
if (!vf.name.endsWith(".class")) return null
|
||||||
|
|
||||||
|
return try {
|
||||||
|
val bytes = vf.contentsToByteArray()
|
||||||
|
val expectedMethodName = if (isConstructor) "<init>" else methodName
|
||||||
|
val descriptorKinds = mutableSetOf<Boolean>()
|
||||||
|
val reader = org.jetbrains.org.objectweb.asm.ClassReader(bytes)
|
||||||
|
reader.accept(
|
||||||
|
object : org.jetbrains.org.objectweb.asm.ClassVisitor(
|
||||||
|
org.jetbrains.org.objectweb.asm.Opcodes.ASM9
|
||||||
|
) {
|
||||||
|
override fun visitMethod(
|
||||||
|
access: Int,
|
||||||
|
name: String,
|
||||||
|
descriptor: String,
|
||||||
|
signature: String?,
|
||||||
|
exceptions: Array<String>?
|
||||||
|
): org.jetbrains.org.objectweb.asm.MethodVisitor? {
|
||||||
|
if (name != expectedMethodName) return null
|
||||||
|
val paramDescriptors = parseAsmMethodDescriptorParams(descriptor)
|
||||||
|
if (paramDescriptors.size != nParams) return null
|
||||||
|
val paramDesc = paramDescriptors.getOrNull(paramIndex) ?: return null
|
||||||
|
// Reference types start with 'L' or '['; Java primitives are single chars
|
||||||
|
descriptorKinds.add(paramDesc.startsWith("L") || paramDesc.startsWith("["))
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
org.jetbrains.org.objectweb.asm.ClassReader.SKIP_CODE or
|
||||||
|
org.jetbrains.org.objectweb.asm.ClassReader.SKIP_DEBUG or
|
||||||
|
org.jetbrains.org.objectweb.asm.ClassReader.SKIP_FRAMES
|
||||||
|
)
|
||||||
|
descriptorKinds.singleOrNull()
|
||||||
|
} catch (e: Exception) {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether the return type of a Java binary method (identified by [methodName] and
|
||||||
|
* [nParams]) is a reference type (as opposed to a Java primitive).
|
||||||
|
*
|
||||||
|
* Returns `null` if the information cannot be determined.
|
||||||
|
*/
|
||||||
|
fun javaBinaryMethodReturnIsClassifierType(
|
||||||
|
parentClass: IrClass,
|
||||||
|
methodName: String,
|
||||||
|
nParams: Int,
|
||||||
|
isConstructor: Boolean
|
||||||
|
): Boolean? {
|
||||||
|
if (isConstructor) return false
|
||||||
|
|
||||||
|
// K1 path: binary Java class has JavaSourceElement with a BinaryJavaClass.
|
||||||
|
val k1ReturnKinds =
|
||||||
|
((parentClass.source as? JavaSourceElement)?.javaElement as? BinaryJavaClass)?.methods
|
||||||
|
?.asSequence()
|
||||||
|
?.filter { it.name.asString() == methodName && it.valueParameters.size == nParams }
|
||||||
|
?.map { it.returnType is org.jetbrains.kotlin.load.java.structure.JavaClassifierType }
|
||||||
|
?.toSet()
|
||||||
|
if (k1ReturnKinds != null && k1ReturnKinds.isNotEmpty()) {
|
||||||
|
return k1ReturnKinds.singleOrNull()
|
||||||
|
}
|
||||||
|
|
||||||
|
// K2 path: binary Java class has VirtualFileBasedSourceElement
|
||||||
|
val k2Source = parentClass.source as? VirtualFileBasedSourceElement ?: return null
|
||||||
|
val vf = k2Source.virtualFile
|
||||||
|
if (!vf.name.endsWith(".class")) return null
|
||||||
|
|
||||||
|
return try {
|
||||||
|
val bytes = vf.contentsToByteArray()
|
||||||
|
val returnKinds = mutableSetOf<Boolean>()
|
||||||
|
val reader = org.jetbrains.org.objectweb.asm.ClassReader(bytes)
|
||||||
|
reader.accept(
|
||||||
|
object : org.jetbrains.org.objectweb.asm.ClassVisitor(
|
||||||
|
org.jetbrains.org.objectweb.asm.Opcodes.ASM9
|
||||||
|
) {
|
||||||
|
override fun visitMethod(
|
||||||
|
access: Int,
|
||||||
|
name: String,
|
||||||
|
descriptor: String,
|
||||||
|
signature: String?,
|
||||||
|
exceptions: Array<String>?
|
||||||
|
): org.jetbrains.org.objectweb.asm.MethodVisitor? {
|
||||||
|
if (name != methodName) return null
|
||||||
|
if (parseAsmMethodDescriptorParams(descriptor).size != nParams) return null
|
||||||
|
val returnDescriptor = descriptor.substring(descriptor.lastIndexOf(')') + 1)
|
||||||
|
returnKinds.add(
|
||||||
|
returnDescriptor.startsWith("L") || returnDescriptor.startsWith("[")
|
||||||
|
)
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
org.jetbrains.org.objectweb.asm.ClassReader.SKIP_CODE or
|
||||||
|
org.jetbrains.org.objectweb.asm.ClassReader.SKIP_DEBUG or
|
||||||
|
org.jetbrains.org.objectweb.asm.ClassReader.SKIP_FRAMES
|
||||||
|
)
|
||||||
|
returnKinds.singleOrNull()
|
||||||
|
} catch (e: Exception) {
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun parseAsmMethodDescriptorParams(descriptor: String): List<String> {
|
||||||
|
val params = mutableListOf<String>()
|
||||||
|
var i = descriptor.indexOf('(') + 1
|
||||||
|
val end = descriptor.lastIndexOf(')')
|
||||||
|
while (i < end) {
|
||||||
|
when (val c = descriptor[i]) {
|
||||||
|
'L' -> {
|
||||||
|
val semi = descriptor.indexOf(';', i)
|
||||||
|
params.add(descriptor.substring(i, semi + 1))
|
||||||
|
i = semi + 1
|
||||||
|
}
|
||||||
|
'[' -> {
|
||||||
|
var j = i + 1
|
||||||
|
while (j < end && descriptor[j] == '[') j++
|
||||||
|
if (descriptor[j] == 'L') {
|
||||||
|
val semi = descriptor.indexOf(';', j)
|
||||||
|
params.add(descriptor.substring(i, semi + 1))
|
||||||
|
i = semi + 1
|
||||||
|
} else {
|
||||||
|
params.add(descriptor.substring(i, j + 1))
|
||||||
|
i = j + 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else -> { params.add(c.toString()); i++ }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return params
|
||||||
|
}
|
||||||
|
|||||||
@@ -14,7 +14,9 @@ pluginManagement {
|
|||||||
repositories {
|
repositories {
|
||||||
gradlePluginPortal()
|
gradlePluginPortal()
|
||||||
google()
|
google()
|
||||||
mavenCentral()
|
maven {
|
||||||
|
url = 'https://maven-central.storage-download.googleapis.com/maven2/'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dependencyResolutionManagement {
|
dependencyResolutionManagement {
|
||||||
@@ -33,7 +35,9 @@ dependencyResolutionManagement {
|
|||||||
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
|
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
|
||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
mavenCentral()
|
maven {
|
||||||
|
url = 'https://maven-central.storage-download.googleapis.com/maven2/'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rootProject.name = "Android Sample"
|
rootProject.name = "Android Sample"
|
||||||
|
|||||||
@@ -14,7 +14,9 @@ pluginManagement {
|
|||||||
repositories {
|
repositories {
|
||||||
gradlePluginPortal()
|
gradlePluginPortal()
|
||||||
google()
|
google()
|
||||||
mavenCentral()
|
maven {
|
||||||
|
url = uri("https://maven-central.storage-download.googleapis.com/maven2/")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dependencyResolutionManagement {
|
dependencyResolutionManagement {
|
||||||
@@ -33,7 +35,9 @@ dependencyResolutionManagement {
|
|||||||
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
|
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
|
||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
mavenCentral()
|
maven {
|
||||||
|
url = uri("https://maven-central.storage-download.googleapis.com/maven2/")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rootProject.name = "Android Sample"
|
rootProject.name = "Android Sample"
|
||||||
|
|||||||
@@ -14,7 +14,9 @@ pluginManagement {
|
|||||||
repositories {
|
repositories {
|
||||||
gradlePluginPortal()
|
gradlePluginPortal()
|
||||||
google()
|
google()
|
||||||
mavenCentral()
|
maven {
|
||||||
|
url = uri("https://maven-central.storage-download.googleapis.com/maven2/")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dependencyResolutionManagement {
|
dependencyResolutionManagement {
|
||||||
@@ -33,7 +35,9 @@ dependencyResolutionManagement {
|
|||||||
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
|
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
|
||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
mavenCentral()
|
maven {
|
||||||
|
url = uri("https://maven-central.storage-download.googleapis.com/maven2/")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rootProject.name = "Android Sample"
|
rootProject.name = "Android Sample"
|
||||||
|
|||||||
@@ -14,7 +14,9 @@ pluginManagement {
|
|||||||
repositories {
|
repositories {
|
||||||
gradlePluginPortal()
|
gradlePluginPortal()
|
||||||
google()
|
google()
|
||||||
mavenCentral()
|
maven {
|
||||||
|
url = 'https://maven-central.storage-download.googleapis.com/maven2/'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dependencyResolutionManagement {
|
dependencyResolutionManagement {
|
||||||
@@ -33,7 +35,9 @@ dependencyResolutionManagement {
|
|||||||
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
|
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
|
||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
mavenCentral()
|
maven {
|
||||||
|
url = 'https://maven-central.storage-download.googleapis.com/maven2/'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rootProject.name = "Android Sample"
|
rootProject.name = "Android Sample"
|
||||||
|
|||||||
@@ -13,7 +13,9 @@ buildscript {
|
|||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
jcenter()
|
maven {
|
||||||
|
url = uri("https://maven-central.storage-download.googleapis.com/maven2/")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -39,6 +41,8 @@ buildscript {
|
|||||||
allprojects {
|
allprojects {
|
||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
jcenter()
|
maven {
|
||||||
|
url = uri("https://maven-central.storage-download.googleapis.com/maven2/")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,9 @@ buildscript {
|
|||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
jcenter()
|
maven {
|
||||||
|
url = uri("https://maven-central.storage-download.googleapis.com/maven2/")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -39,6 +41,8 @@ buildscript {
|
|||||||
allprojects {
|
allprojects {
|
||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
jcenter()
|
maven {
|
||||||
|
url = uri("https://maven-central.storage-download.googleapis.com/maven2/")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,9 @@ buildscript {
|
|||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
jcenter()
|
maven {
|
||||||
|
url = 'https://maven-central.storage-download.googleapis.com/maven2/'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -39,6 +41,8 @@ buildscript {
|
|||||||
allprojects {
|
allprojects {
|
||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
jcenter()
|
maven {
|
||||||
|
url = 'https://maven-central.storage-download.googleapis.com/maven2/'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,9 @@ buildscript {
|
|||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
jcenter()
|
maven {
|
||||||
|
url = 'https://maven-central.storage-download.googleapis.com/maven2/'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -32,13 +34,15 @@ buildscript {
|
|||||||
* dependencies used by all modules in your project, such as third-party plugins
|
* dependencies used by all modules in your project, such as third-party plugins
|
||||||
* or libraries. However, you should configure module-specific dependencies in
|
* or libraries. However, you should configure module-specific dependencies in
|
||||||
* each module-level build.gradle file. For new projects, Android Studio
|
* each module-level build.gradle file. For new projects, Android Studio
|
||||||
* includes JCenter and Google's Maven repository by default, but it does not
|
* includes Maven Central and Google's Maven repository by default, but it does not
|
||||||
* configure any dependencies (unless you select a template that requires some).
|
* configure any dependencies (unless you select a template that requires some).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
allprojects {
|
allprojects {
|
||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
jcenter()
|
maven {
|
||||||
|
url = 'https://maven-central.storage-download.googleapis.com/maven2/'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,9 @@ pluginManagement {
|
|||||||
repositories {
|
repositories {
|
||||||
gradlePluginPortal()
|
gradlePluginPortal()
|
||||||
google()
|
google()
|
||||||
mavenCentral()
|
maven {
|
||||||
|
url = 'https://maven-central.storage-download.googleapis.com/maven2/'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dependencyResolutionManagement {
|
dependencyResolutionManagement {
|
||||||
@@ -33,7 +35,9 @@ dependencyResolutionManagement {
|
|||||||
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
|
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
|
||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
mavenCentral()
|
maven {
|
||||||
|
url = 'https://maven-central.storage-download.googleapis.com/maven2/'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rootProject.name = "Android Sample"
|
rootProject.name = "Android Sample"
|
||||||
|
|||||||
@@ -8,7 +8,9 @@
|
|||||||
apply plugin: 'java-library'
|
apply plugin: 'java-library'
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
maven {
|
||||||
|
url = 'https://maven-central.storage-download.googleapis.com/maven2/'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
https://repo.maven.apache.org/maven2/org/apache/commons/commons-math3/3.6.1/commons-math3-3.6.1.jar
|
https://maven-central.storage-download.googleapis.com/maven2/org/apache/commons/commons-math3/3.6.1/commons-math3-3.6.1.jar
|
||||||
https://repo.maven.apache.org/maven2/org/apiguardian/apiguardian-api/1.1.2/apiguardian-api-1.1.2.jar
|
https://maven-central.storage-download.googleapis.com/maven2/org/apiguardian/apiguardian-api/1.1.2/apiguardian-api-1.1.2.jar
|
||||||
https://repo.maven.apache.org/maven2/org/junit/jupiter/junit-jupiter-api/5.12.1/junit-jupiter-api-5.12.1.jar
|
https://maven-central.storage-download.googleapis.com/maven2/org/junit/jupiter/junit-jupiter-api/5.12.1/junit-jupiter-api-5.12.1.jar
|
||||||
https://repo.maven.apache.org/maven2/org/junit/platform/junit-platform-commons/1.12.1/junit-platform-commons-1.12.1.jar
|
https://maven-central.storage-download.googleapis.com/maven2/org/junit/platform/junit-platform-commons/1.12.1/junit-platform-commons-1.12.1.jar
|
||||||
https://repo.maven.apache.org/maven2/org/opentest4j/opentest4j/1.3.0/opentest4j-1.3.0.jar
|
https://maven-central.storage-download.googleapis.com/maven2/org/opentest4j/opentest4j/1.3.0/opentest4j-1.3.0.jar
|
||||||
|
|||||||
@@ -8,7 +8,9 @@
|
|||||||
apply plugin: 'java-library'
|
apply plugin: 'java-library'
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
maven {
|
||||||
|
url = 'https://maven-central.storage-download.googleapis.com/maven2/'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
https://repo.maven.apache.org/maven2/joda-time/joda-time/2.12.7/joda-time-2.12.7-no-tzdb.jar
|
https://maven-central.storage-download.googleapis.com/maven2/joda-time/joda-time/2.12.7/joda-time-2.12.7-no-tzdb.jar
|
||||||
https://repo.maven.apache.org/maven2/org/apache/commons/commons-math3/3.6.1/commons-math3-3.6.1.jar
|
https://maven-central.storage-download.googleapis.com/maven2/org/apache/commons/commons-math3/3.6.1/commons-math3-3.6.1.jar
|
||||||
|
|||||||
@@ -12,9 +12,9 @@ apply plugin: 'java'
|
|||||||
|
|
||||||
// In this section you declare where to find the dependencies of your project
|
// In this section you declare where to find the dependencies of your project
|
||||||
repositories {
|
repositories {
|
||||||
// Use 'jcenter' for resolving your dependencies.
|
maven {
|
||||||
// You can declare any Maven/Ivy/file repository here.
|
url = 'https://maven-central.storage-download.googleapis.com/maven2/'
|
||||||
jcenter()
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// In this section you declare the dependencies for your production and test code
|
// In this section you declare the dependencies for your production and test code
|
||||||
|
|||||||
@@ -8,7 +8,9 @@
|
|||||||
apply plugin: 'java-library'
|
apply plugin: 'java-library'
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
maven {
|
||||||
|
url = 'https://maven-central.storage-download.googleapis.com/maven2/'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
https://repo.maven.apache.org/maven2/org/apache/commons/commons-math3/3.6.1/commons-math3-3.6.1.jar
|
https://maven-central.storage-download.googleapis.com/maven2/org/apache/commons/commons-math3/3.6.1/commons-math3-3.6.1.jar
|
||||||
|
|||||||
@@ -8,7 +8,9 @@
|
|||||||
apply plugin: 'java-library'
|
apply plugin: 'java-library'
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
maven {
|
||||||
|
url = 'https://maven-central.storage-download.googleapis.com/maven2/'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
https://repo.maven.apache.org/maven2/org/apache/commons/commons-math3/3.6.1/commons-math3-3.6.1.jar
|
https://maven-central.storage-download.googleapis.com/maven2/org/apache/commons/commons-math3/3.6.1/commons-math3-3.6.1.jar
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
https://jcenter.bintray.com/junit/junit/4.12/junit-4.12.jar
|
https://maven-central.storage-download.googleapis.com/maven2/junit/junit/4.11/junit-4.11.jar
|
||||||
https://jcenter.bintray.com/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.jar
|
https://maven-central.storage-download.googleapis.com/maven2/junit/junit/4.12/junit-4.12.jar
|
||||||
https://jcenter.bintray.com/org/slf4j/slf4j-api/1.7.21/slf4j-api-1.7.21.jar
|
https://maven-central.storage-download.googleapis.com/maven2/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.jar
|
||||||
|
https://maven-central.storage-download.googleapis.com/maven2/org/slf4j/slf4j-api/1.7.21/slf4j-api-1.7.21.jar
|
||||||
https://repo.maven.apache.org/maven2/com/feiniaojin/naaf/naaf-graceful-response-example/1.0/naaf-graceful-response-example-1.0.jar
|
https://repo.maven.apache.org/maven2/com/feiniaojin/naaf/naaf-graceful-response-example/1.0/naaf-graceful-response-example-1.0.jar
|
||||||
https://repo.maven.apache.org/maven2/com/github/MoebiusSolutions/avro-registry-in-source/avro-registry-in-source-tests/1.8/avro-registry-in-source-tests-1.8.jar
|
https://repo.maven.apache.org/maven2/com/github/MoebiusSolutions/avro-registry-in-source/avro-registry-in-source-tests/1.8/avro-registry-in-source-tests-1.8.jar
|
||||||
https://repo.maven.apache.org/maven2/com/github/MoebiusSolutions/avro-registry-in-source/example-project/1.5/example-project-1.5.jar
|
https://repo.maven.apache.org/maven2/com/github/MoebiusSolutions/avro-registry-in-source/example-project/1.5/example-project-1.5.jar
|
||||||
@@ -12,7 +13,6 @@ https://repo.maven.apache.org/maven2/de/knutwalker/rx-redis-example_2.11/0.1.2/r
|
|||||||
https://repo.maven.apache.org/maven2/de/knutwalker/rx-redis-java-example_2.11/0.1.2/rx-redis-java-example_2.11-0.1.2.jar
|
https://repo.maven.apache.org/maven2/de/knutwalker/rx-redis-java-example_2.11/0.1.2/rx-redis-java-example_2.11-0.1.2.jar
|
||||||
https://repo.maven.apache.org/maven2/io/github/scrollsyou/example-spring-boot-starter/1.0.0/example-spring-boot-starter-1.0.0.jar
|
https://repo.maven.apache.org/maven2/io/github/scrollsyou/example-spring-boot-starter/1.0.0/example-spring-boot-starter-1.0.0.jar
|
||||||
https://repo.maven.apache.org/maven2/io/streamnative/com/example/maven-central-template/server/3.0.0/server-3.0.0.jar
|
https://repo.maven.apache.org/maven2/io/streamnative/com/example/maven-central-template/server/3.0.0/server-3.0.0.jar
|
||||||
https://repo.maven.apache.org/maven2/junit/junit/4.11/junit-4.11.jar
|
|
||||||
https://repo.maven.apache.org/maven2/no/nav/security/token-validation-ktor-demo/3.1.0/token-validation-ktor-demo-3.1.0.jar
|
https://repo.maven.apache.org/maven2/no/nav/security/token-validation-ktor-demo/3.1.0/token-validation-ktor-demo-3.1.0.jar
|
||||||
https://repo.maven.apache.org/maven2/org/minijax/minijax-example-fileupload/0.5.10/minijax-example-fileupload-0.5.10.jar
|
https://repo.maven.apache.org/maven2/org/minijax/minijax-example-fileupload/0.5.10/minijax-example-fileupload-0.5.10.jar
|
||||||
https://repo.maven.apache.org/maven2/org/minijax/minijax-example-inject/0.5.10/minijax-example-inject-0.5.10.jar
|
https://repo.maven.apache.org/maven2/org/minijax/minijax-example-inject/0.5.10/minijax-example-inject-0.5.10.jar
|
||||||
|
|||||||
@@ -12,9 +12,9 @@ apply plugin: 'java'
|
|||||||
|
|
||||||
// In this section you declare where to find the dependencies of your project
|
// In this section you declare where to find the dependencies of your project
|
||||||
repositories {
|
repositories {
|
||||||
// Use 'jcenter' for resolving your dependencies.
|
maven {
|
||||||
// You can declare any Maven/Ivy/file repository here.
|
url = 'https://maven-central.storage-download.googleapis.com/maven2/'
|
||||||
jcenter()
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// In this section you declare the dependencies for your production and test code
|
// In this section you declare the dependencies for your production and test code
|
||||||
|
|||||||
@@ -12,9 +12,9 @@ apply plugin: 'java'
|
|||||||
|
|
||||||
// In this section you declare where to find the dependencies of your project
|
// In this section you declare where to find the dependencies of your project
|
||||||
repositories {
|
repositories {
|
||||||
// Use 'jcenter' for resolving your dependencies.
|
maven {
|
||||||
// You can declare any Maven/Ivy/file repository here.
|
url = 'https://maven-central.storage-download.googleapis.com/maven2/'
|
||||||
jcenter()
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// In this section you declare the dependencies for your production and test code
|
// In this section you declare the dependencies for your production and test code
|
||||||
|
|||||||
@@ -0,0 +1,10 @@
|
|||||||
|
<settings>
|
||||||
|
<mirrors>
|
||||||
|
<mirror>
|
||||||
|
<id>google-maven-central</id>
|
||||||
|
<name>GCS Maven Central mirror</name>
|
||||||
|
<url>https://maven-central.storage-download.googleapis.com/maven2/</url>
|
||||||
|
<mirrorOf>central</mirrorOf>
|
||||||
|
</mirror>
|
||||||
|
</mirrors>
|
||||||
|
</settings>
|
||||||
@@ -26,4 +26,5 @@ maven-project-2/src/main/resources/my-app.properties
|
|||||||
maven-project-2/src/main/resources/page.xml
|
maven-project-2/src/main/resources/page.xml
|
||||||
maven-project-2/src/main/resources/struts.xml
|
maven-project-2/src/main/resources/struts.xml
|
||||||
maven-project-2/src/test/java/com/example/AppTest4.java
|
maven-project-2/src/test/java/com/example/AppTest4.java
|
||||||
|
settings.xml
|
||||||
test-db/working/settings.xml
|
test-db/working/settings.xml
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import os
|
||||||
|
|
||||||
def test(codeql, use_java_11, java, actions_toolchains_file, check_diagnostics_java):
|
def test(codeql, use_java_11, java, actions_toolchains_file, check_diagnostics_java):
|
||||||
# The version of gradle used doesn't work on java 17
|
# The version of gradle used doesn't work on java 17
|
||||||
codeql.database.create(
|
codeql.database.create(
|
||||||
@@ -5,5 +7,6 @@ def test(codeql, use_java_11, java, actions_toolchains_file, check_diagnostics_j
|
|||||||
"CODEQL_EXTRACTOR_JAVA_OPTION_BUILDLESS": "true",
|
"CODEQL_EXTRACTOR_JAVA_OPTION_BUILDLESS": "true",
|
||||||
"CODEQL_EXTRACTOR_JAVA_OPTION_BUILDLESS_CLASSPATH_FROM_BUILD_FILES": "true",
|
"CODEQL_EXTRACTOR_JAVA_OPTION_BUILDLESS_CLASSPATH_FROM_BUILD_FILES": "true",
|
||||||
"LGTM_INDEX_MAVEN_TOOLCHAINS_FILE": str(actions_toolchains_file),
|
"LGTM_INDEX_MAVEN_TOOLCHAINS_FILE": str(actions_toolchains_file),
|
||||||
|
"LGTM_INDEX_MAVEN_SETTINGS_FILE": os.path.join(os.path.dirname(os.path.realpath(__file__)), "settings.xml"),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -14,7 +14,9 @@ pluginManagement {
|
|||||||
repositories {
|
repositories {
|
||||||
gradlePluginPortal()
|
gradlePluginPortal()
|
||||||
google()
|
google()
|
||||||
mavenCentral()
|
maven {
|
||||||
|
url = 'https://maven-central.storage-download.googleapis.com/maven2/'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
dependencyResolutionManagement {
|
dependencyResolutionManagement {
|
||||||
@@ -33,7 +35,9 @@ dependencyResolutionManagement {
|
|||||||
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
|
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
|
||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
mavenCentral()
|
maven {
|
||||||
|
url = 'https://maven-central.storage-download.googleapis.com/maven2/'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
rootProject.name = "Android Sample"
|
rootProject.name = "Android Sample"
|
||||||
|
|||||||
@@ -12,9 +12,9 @@ apply plugin: 'java'
|
|||||||
|
|
||||||
// In this section you declare where to find the dependencies of your project
|
// In this section you declare where to find the dependencies of your project
|
||||||
repositories {
|
repositories {
|
||||||
// Use 'jcenter' for resolving your dependencies.
|
maven {
|
||||||
// You can declare any Maven/Ivy/file repository here.
|
url = 'https://maven-central.storage-download.googleapis.com/maven2/'
|
||||||
jcenter()
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// In this section you declare the dependencies for your production and test code
|
// In this section you declare the dependencies for your production and test code
|
||||||
|
|||||||
@@ -12,9 +12,9 @@ apply plugin: 'java'
|
|||||||
|
|
||||||
// In this section you declare where to find the dependencies of your project
|
// In this section you declare where to find the dependencies of your project
|
||||||
repositories {
|
repositories {
|
||||||
// Use 'jcenter' for resolving your dependencies.
|
maven {
|
||||||
// You can declare any Maven/Ivy/file repository here.
|
url = 'https://maven-central.storage-download.googleapis.com/maven2/'
|
||||||
jcenter()
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// In this section you declare the dependencies for your production and test code
|
// In this section you declare the dependencies for your production and test code
|
||||||
|
|||||||
@@ -12,8 +12,9 @@ plugins {
|
|||||||
}
|
}
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
// Use Maven Central for resolving dependencies.
|
maven {
|
||||||
mavenCentral()
|
url = uri("https://maven-central.storage-download.googleapis.com/maven2/")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
|||||||
@@ -12,9 +12,9 @@ apply plugin: 'java'
|
|||||||
|
|
||||||
// In this section you declare where to find the dependencies of your project
|
// In this section you declare where to find the dependencies of your project
|
||||||
repositories {
|
repositories {
|
||||||
// Use 'jcenter' for resolving your dependencies.
|
maven {
|
||||||
// You can declare any Maven/Ivy/file repository here.
|
url = 'https://maven-central.storage-download.googleapis.com/maven2/'
|
||||||
jcenter()
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// In this section you declare the dependencies for your production and test code
|
// In this section you declare the dependencies for your production and test code
|
||||||
|
|||||||
@@ -12,9 +12,9 @@ apply plugin: 'java'
|
|||||||
|
|
||||||
// In this section you declare where to find the dependencies of your project
|
// In this section you declare where to find the dependencies of your project
|
||||||
repositories {
|
repositories {
|
||||||
// Use 'jcenter' for resolving your dependencies.
|
maven {
|
||||||
// You can declare any Maven/Ivy/file repository here.
|
url = 'https://maven-central.storage-download.googleapis.com/maven2/'
|
||||||
jcenter()
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// In this section you declare the dependencies for your production and test code
|
// In this section you declare the dependencies for your production and test code
|
||||||
|
|||||||
@@ -12,9 +12,9 @@ apply plugin: 'java'
|
|||||||
|
|
||||||
// In this section you declare where to find the dependencies of your project
|
// In this section you declare where to find the dependencies of your project
|
||||||
repositories {
|
repositories {
|
||||||
// Use 'jcenter' for resolving your dependencies.
|
maven {
|
||||||
// You can declare any Maven/Ivy/file repository here.
|
url = 'https://maven-central.storage-download.googleapis.com/maven2/'
|
||||||
jcenter()
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// In this section you declare the dependencies for your production and test code
|
// In this section you declare the dependencies for your production and test code
|
||||||
|
|||||||
@@ -12,9 +12,9 @@ apply plugin: 'java'
|
|||||||
|
|
||||||
// In this section you declare where to find the dependencies of your project
|
// In this section you declare where to find the dependencies of your project
|
||||||
repositories {
|
repositories {
|
||||||
// Use 'jcenter' for resolving your dependencies.
|
maven {
|
||||||
// You can declare any Maven/Ivy/file repository here.
|
url = 'https://maven-central.storage-download.googleapis.com/maven2/'
|
||||||
jcenter()
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// In this section you declare the dependencies for your production and test code
|
// In this section you declare the dependencies for your production and test code
|
||||||
|
|||||||
@@ -11,7 +11,9 @@ version = '0.0.1-SNAPSHOT'
|
|||||||
// but I omit it to test we recognise the Spring Boot plugin version.
|
// but I omit it to test we recognise the Spring Boot plugin version.
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
maven {
|
||||||
|
url = 'https://maven-central.storage-download.googleapis.com/maven2/'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
|||||||
@@ -15,8 +15,9 @@ plugins {
|
|||||||
}
|
}
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
// Use Maven Central for resolving dependencies.
|
maven {
|
||||||
mavenCentral()
|
url = 'https://maven-central.storage-download.googleapis.com/maven2/'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
application {
|
application {
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
import pathlib
|
import pathlib
|
||||||
|
|
||||||
|
|
||||||
def test(codeql, java_full, kotlinc_2_3_20):
|
def test(codeql, java_full):
|
||||||
java_srcs = " ".join([str(s) for s in pathlib.Path().glob("*.java")])
|
java_srcs = " ".join([str(s) for s in pathlib.Path().glob("*.java")])
|
||||||
codeql.database.create(
|
codeql.database.create(
|
||||||
command=[
|
command=[
|
||||||
f"javac {java_srcs} -d build",
|
f"javac {java_srcs} -d build",
|
||||||
"kotlinc -language-version 1.9 user.kt -cp build",
|
"kotlinc -language-version 2.0 user.kt -cp build",
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import commands
|
import commands
|
||||||
|
|
||||||
|
|
||||||
def test(codeql, java_full, kotlinc_2_3_20):
|
def test(codeql, java_full):
|
||||||
commands.run("kotlinc -language-version 1.9 test.kt -d lib")
|
commands.run("kotlinc -language-version 2.0 test.kt -d lib")
|
||||||
codeql.database.create(command="kotlinc -language-version 1.9 user.kt -cp lib")
|
codeql.database.create(command="kotlinc -language-version 2.0 user.kt -cp lib")
|
||||||
|
|||||||
@@ -9,4 +9,4 @@
|
|||||||
| Percentage of calls with call target | 100 |
|
| Percentage of calls with call target | 100 |
|
||||||
| Total number of lines | 3 |
|
| Total number of lines | 3 |
|
||||||
| Total number of lines with extension kt | 3 |
|
| Total number of lines with extension kt | 3 |
|
||||||
| Uses Kotlin 2: false | 1 |
|
| Uses Kotlin 2: true | 1 |
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
def test(codeql, java_full, kotlinc_2_3_20):
|
def test(codeql, java_full):
|
||||||
codeql.database.create(command=f"kotlinc -J-Xmx2G -language-version 1.9 SomeClass.kt")
|
codeql.database.create(command="kotlinc -J-Xmx2G -language-version 2.0 SomeClass.kt")
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import commands
|
import commands
|
||||||
|
|
||||||
|
|
||||||
def test(codeql, java_full, kotlinc_2_3_20):
|
def test(codeql, java_full):
|
||||||
commands.run("kotlinc -language-version 1.9 A.kt")
|
commands.run("kotlinc -language-version 2.0 A.kt")
|
||||||
codeql.database.create(command="kotlinc -cp . -language-version 1.9 B.kt C.kt")
|
codeql.database.create(command="kotlinc -cp . -language-version 2.0 B.kt C.kt")
|
||||||
|
|||||||
@@ -15,8 +15,9 @@ plugins {
|
|||||||
}
|
}
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
// Use Maven Central for resolving dependencies.
|
maven {
|
||||||
mavenCentral()
|
url = 'https://maven-central.storage-download.googleapis.com/maven2/'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
application {
|
application {
|
||||||
|
|||||||
@@ -4,7 +4,9 @@ plugins {
|
|||||||
}
|
}
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
mavenCentral()
|
maven {
|
||||||
|
url = 'https://maven-central.storage-download.googleapis.com/maven2/'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import commands
|
import commands
|
||||||
|
|
||||||
|
|
||||||
def test(codeql, java_full, kotlinc_2_3_20):
|
def test(codeql, java_full):
|
||||||
commands.run(["javac", "Test.java", "-d", "bin"])
|
commands.run(["javac", "Test.java", "-d", "bin"])
|
||||||
codeql.database.create(command="kotlinc -language-version 1.9 user.kt -cp bin")
|
codeql.database.create(command="kotlinc -language-version 2.0 user.kt -cp bin")
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
import commands
|
import commands
|
||||||
|
|
||||||
|
|
||||||
def test(codeql, java_full, kotlinc_2_3_20):
|
def test(codeql, java_full):
|
||||||
# Compile the JavaDefns2 copy outside tracing, to make sure the Kotlin view of it matches the Java view seen by the traced javac compilation of JavaDefns.java below.
|
# Compile the JavaDefns2 copy outside tracing, to make sure the Kotlin view of it matches the Java view seen by the traced javac compilation of JavaDefns.java below.
|
||||||
commands.run(["javac", "JavaDefns2.java"])
|
commands.run(["javac", "JavaDefns2.java"])
|
||||||
codeql.database.create(
|
codeql.database.create(
|
||||||
command=[
|
command=[
|
||||||
"kotlinc kotlindefns.kt",
|
"kotlinc kotlindefns.kt",
|
||||||
"javac JavaUser.java JavaDefns.java -cp .",
|
"javac JavaUser.java JavaDefns.java -cp .",
|
||||||
"kotlinc -language-version 1.9 -cp . kotlinuser.kt",
|
"kotlinc -language-version 2.0 -cp . kotlinuser.kt",
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -15,8 +15,9 @@ plugins {
|
|||||||
}
|
}
|
||||||
|
|
||||||
repositories {
|
repositories {
|
||||||
// Use Maven Central for resolving dependencies.
|
maven {
|
||||||
mavenCentral()
|
url = 'https://maven-central.storage-download.googleapis.com/maven2/'
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
application {
|
application {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
name: codeql/java-all
|
name: codeql/java-all
|
||||||
version: 9.2.0
|
version: 9.2.1-dev
|
||||||
groups: java
|
groups: java
|
||||||
dbscheme: config/semmlecode.dbscheme
|
dbscheme: config/semmlecode.dbscheme
|
||||||
extractor: java
|
extractor: java
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
name: codeql/java-queries
|
name: codeql/java-queries
|
||||||
version: 1.11.5
|
version: 1.11.6-dev
|
||||||
groups:
|
groups:
|
||||||
- java
|
- java
|
||||||
- queries
|
- queries
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
---
|
||||||
|
category: minorAnalysis
|
||||||
|
---
|
||||||
|
* Added support for Angular's `@HostListener('window:message', ...)` and `@HostListener('document:message', ...)` decorators as `postMessage` event handlers. The decorated method's event parameter is now recognized as a client-side remote flow source, and is considered by the `js/missing-origin-check` query.
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
name: codeql/javascript-all
|
name: codeql/javascript-all
|
||||||
version: 2.8.0
|
version: 2.8.1-dev
|
||||||
groups: javascript
|
groups: javascript
|
||||||
dbscheme: semmlecode.javascript.dbscheme
|
dbscheme: semmlecode.javascript.dbscheme
|
||||||
extractor: javascript
|
extractor: javascript
|
||||||
|
|||||||
@@ -195,6 +195,18 @@ class PostMessageEventHandler extends Function {
|
|||||||
rhs = DataFlow::globalObjectRef().getAPropertyWrite("onmessage").getRhs() and
|
rhs = DataFlow::globalObjectRef().getAPropertyWrite("onmessage").getRhs() and
|
||||||
rhs.getABoundFunctionValue(paramIndex).getFunction() = this
|
rhs.getABoundFunctionValue(paramIndex).getFunction() = this
|
||||||
)
|
)
|
||||||
|
or
|
||||||
|
// Angular's `@HostListener('window:message', ['$event'])` decorator registers
|
||||||
|
// a method as a `message` event handler on the global `window` or `document`
|
||||||
|
// target. The decorated method receives the `MessageEvent` as its first
|
||||||
|
// parameter, so it is equivalent to `window.addEventListener('message', ...)`.
|
||||||
|
exists(MethodDefinition method, DataFlow::CallNode decorator |
|
||||||
|
decorator = DataFlow::moduleMember("@angular/core", "HostListener").getACall() and
|
||||||
|
decorator = method.getADecorator().getExpression().flow() and
|
||||||
|
decorator.getArgument(0).mayHaveStringValue(["window:message", "document:message"]) and
|
||||||
|
method.getBody() = this and
|
||||||
|
paramIndex = 0
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
name: codeql/javascript-queries
|
name: codeql/javascript-queries
|
||||||
version: 2.4.0
|
version: 2.4.1-dev
|
||||||
groups:
|
groups:
|
||||||
- javascript
|
- javascript
|
||||||
- queries
|
- queries
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
import { Component, HostListener } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({ selector: 'app-root' })
|
||||||
|
class AngularComponent {
|
||||||
|
// Angular registers this as a `window` message handler via the decorator,
|
||||||
|
// equivalent to `window.addEventListener('message', ...)`.
|
||||||
|
@HostListener('window:message', ['$event'])
|
||||||
|
onWindowMessage(event: MessageEvent): void { // $ Alert - no origin check
|
||||||
|
eval(event.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
@HostListener('document:message', ['$event'])
|
||||||
|
onDocumentMessage(event: MessageEvent): void { // $ Alert - no origin check
|
||||||
|
eval(event.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
@HostListener('window:message', ['$event'])
|
||||||
|
onCheckedMessage(event: MessageEvent): void { // OK - has an origin check
|
||||||
|
if (event.origin === 'https://www.example.com') {
|
||||||
|
eval(event.data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Not a message event, so it is not a postMessage handler.
|
||||||
|
@HostListener('window:resize', ['$event'])
|
||||||
|
onResize(event: MessageEvent): void { // OK - not a message handler
|
||||||
|
eval(event.data);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
| Angular.ts:8:19:8:23 | event | Postmessage handler has no origin check. |
|
||||||
|
| Angular.ts:13:21:13:25 | event | Postmessage handler has no origin check. |
|
||||||
| tst.js:11:20:11:24 | event | Postmessage handler has no origin check. |
|
| tst.js:11:20:11:24 | event | Postmessage handler has no origin check. |
|
||||||
| tst.js:24:27:24:27 | e | Postmessage handler has no origin check. |
|
| tst.js:24:27:24:27 | e | Postmessage handler has no origin check. |
|
||||||
| tst.js:40:27:40:27 | e | Postmessage handler has no origin check. |
|
| tst.js:40:27:40:27 | e | Postmessage handler has no origin check. |
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
name: codeql/suite-helpers
|
name: codeql/suite-helpers
|
||||||
version: 1.0.52
|
version: 1.0.53-dev
|
||||||
groups: shared
|
groups: shared
|
||||||
warnOnImplicitThis: true
|
warnOnImplicitThis: true
|
||||||
|
|||||||
@@ -70,7 +70,7 @@ No user-facing changes.
|
|||||||
|
|
||||||
### Minor Analysis Improvements
|
### Minor Analysis Improvements
|
||||||
|
|
||||||
* Added new full SSRF sanitization barrier from the new AntiSSRF library.
|
* Added new full SSRF sanitization barrier from the new AntiSSRF library.
|
||||||
* When a guard such as `isSafe(x)` is defined, we now also automatically handle `isSafe(x) == true` and `isSafe(x) != false`.
|
* When a guard such as `isSafe(x)` is defined, we now also automatically handle `isSafe(x) == true` and `isSafe(x) != false`.
|
||||||
|
|
||||||
## 6.1.1
|
## 6.1.1
|
||||||
@@ -169,7 +169,7 @@ No user-facing changes.
|
|||||||
### Minor Analysis Improvements
|
### Minor Analysis Improvements
|
||||||
|
|
||||||
- The modelling of Psycopg2 now supports the use of `psycopg2.pool` connection pools for handling database connections.
|
- The modelling of Psycopg2 now supports the use of `psycopg2.pool` connection pools for handling database connections.
|
||||||
* Removed `lxml` as an XML bomb sink. The underlying libxml2 library now includes [entity reference loop detection](https://github.com/lxml/lxml/blob/f33ac2c2f5f9c4c4c1fc47f363be96db308f2fa6/doc/FAQ.txt#L1077) that prevents XML bomb attacks.
|
* Removed `lxml` as an XML bomb sink. The underlying libxml2 library now includes [entity reference loop detection](https://github.com/lxml/lxml/blob/f33ac2c2f5f9c4c4c1fc47f363be96db308f2fa6/doc/FAQ.txt#L1077) that prevents XML bomb attacks.
|
||||||
|
|
||||||
## 4.0.13
|
## 4.0.13
|
||||||
|
|
||||||
@@ -262,7 +262,7 @@ No user-facing changes.
|
|||||||
### Minor Analysis Improvements
|
### Minor Analysis Improvements
|
||||||
|
|
||||||
* The sensitive data library has been improved so that `snake_case` style variable names are recognized more reliably. This may result in more sensitive data being identified, and more results from queries that use the sensitive data library.
|
* The sensitive data library has been improved so that `snake_case` style variable names are recognized more reliably. This may result in more sensitive data being identified, and more results from queries that use the sensitive data library.
|
||||||
- Additional taint steps through methods of `lxml.etree.Element` and `lxml.etree.ElementTree` objects from the `lxml` PyPI package have been modeled.
|
- Additional taint steps through methods of `lxml.etree.Element` and `lxml.etree.ElementTree` objects from the `lxml` PyPI package have been modeled.
|
||||||
|
|
||||||
## 3.1.0
|
## 3.1.0
|
||||||
|
|
||||||
@@ -316,7 +316,7 @@ No user-facing changes.
|
|||||||
|
|
||||||
### Minor Analysis Improvements
|
### Minor Analysis Improvements
|
||||||
|
|
||||||
* The common sanitizer guard `StringConstCompareBarrier` has been renamed to `ConstCompareBarrier` and expanded to cover comparisons with other constant values such as `None`. This may result in fewer false positive results for several queries.
|
* The common sanitizer guard `StringConstCompareBarrier` has been renamed to `ConstCompareBarrier` and expanded to cover comparisons with other constant values such as `None`. This may result in fewer false positive results for several queries.
|
||||||
|
|
||||||
## 2.0.0
|
## 2.0.0
|
||||||
|
|
||||||
@@ -545,7 +545,7 @@ No user-facing changes.
|
|||||||
|
|
||||||
### New Features
|
### New Features
|
||||||
|
|
||||||
* The `DataFlow::StateConfigSig` signature module has gained default implementations for `isBarrier/2` and `isAdditionalFlowStep/4`.
|
* The `DataFlow::StateConfigSig` signature module has gained default implementations for `isBarrier/2` and `isAdditionalFlowStep/4`.
|
||||||
Hence it is no longer needed to provide `none()` implementations of these predicates if they are not needed.
|
Hence it is no longer needed to provide `none()` implementations of these predicates if they are not needed.
|
||||||
|
|
||||||
### Minor Analysis Improvements
|
### Minor Analysis Improvements
|
||||||
@@ -572,7 +572,7 @@ No user-facing changes.
|
|||||||
* Deleted many deprecated predicates and classes with uppercase `API`, `HTTP`, `XSS`, `SQL`, etc. in their names. Use the PascalCased versions instead.
|
* Deleted many deprecated predicates and classes with uppercase `API`, `HTTP`, `XSS`, `SQL`, etc. in their names. Use the PascalCased versions instead.
|
||||||
* Deleted the deprecated `getName()` predicate from the `Container` class, use `getAbsolutePath()` instead.
|
* Deleted the deprecated `getName()` predicate from the `Container` class, use `getAbsolutePath()` instead.
|
||||||
* Deleted many deprecated module names that started with a lowercase letter, use the versions that start with an uppercase letter instead.
|
* Deleted many deprecated module names that started with a lowercase letter, use the versions that start with an uppercase letter instead.
|
||||||
* Deleted many deprecated predicates in `PointsTo.qll`.
|
* Deleted many deprecated predicates in `PointsTo.qll`.
|
||||||
* Deleted many deprecated files from the `semmle.python.security` package.
|
* Deleted many deprecated files from the `semmle.python.security` package.
|
||||||
* Deleted the deprecated `BottleRoutePointToExtension` class from `Extensions.qll`.
|
* Deleted the deprecated `BottleRoutePointToExtension` class from `Extensions.qll`.
|
||||||
* Type tracking is now aware of flow summaries. This leads to a richer API graph, and may lead to more results in some queries.
|
* Type tracking is now aware of flow summaries. This leads to a richer API graph, and may lead to more results in some queries.
|
||||||
@@ -729,7 +729,7 @@ No user-facing changes.
|
|||||||
### Deprecated APIs
|
### Deprecated APIs
|
||||||
|
|
||||||
* Some unused predicates in `SsaDefinitions.qll`, `TObject.qll`, `protocols.qll`, and the `pointsto/` folder have been deprecated.
|
* Some unused predicates in `SsaDefinitions.qll`, `TObject.qll`, `protocols.qll`, and the `pointsto/` folder have been deprecated.
|
||||||
* Some classes/modules with upper-case acronyms in their name have been renamed to follow our style-guide.
|
* Some classes/modules with upper-case acronyms in their name have been renamed to follow our style-guide.
|
||||||
The old name still exists as a deprecated alias.
|
The old name still exists as a deprecated alias.
|
||||||
|
|
||||||
### Minor Analysis Improvements
|
### Minor Analysis Improvements
|
||||||
@@ -748,9 +748,9 @@ No user-facing changes.
|
|||||||
|
|
||||||
### Deprecated APIs
|
### Deprecated APIs
|
||||||
|
|
||||||
* Many classes/predicates/modules with upper-case acronyms in their name have been renamed to follow our style-guide.
|
* Many classes/predicates/modules with upper-case acronyms in their name have been renamed to follow our style-guide.
|
||||||
The old name still exists as a deprecated alias.
|
The old name still exists as a deprecated alias.
|
||||||
* The utility files previously in the `semmle.python.security.performance` package have been moved to the `semmle.python.security.regexp` package.
|
* The utility files previously in the `semmle.python.security.performance` package have been moved to the `semmle.python.security.regexp` package.
|
||||||
The previous files still exist as deprecated aliases.
|
The previous files still exist as deprecated aliases.
|
||||||
|
|
||||||
### Minor Analysis Improvements
|
### Minor Analysis Improvements
|
||||||
@@ -843,9 +843,9 @@ No user-facing changes.
|
|||||||
|
|
||||||
### Deprecated APIs
|
### Deprecated APIs
|
||||||
|
|
||||||
* Many classes/predicates/modules that had upper-case acronyms have been renamed to follow our style-guide.
|
* Many classes/predicates/modules that had upper-case acronyms have been renamed to follow our style-guide.
|
||||||
The old name still exists as a deprecated alias.
|
The old name still exists as a deprecated alias.
|
||||||
* Some modules that started with a lowercase letter have been renamed to follow our style-guide.
|
* Some modules that started with a lowercase letter have been renamed to follow our style-guide.
|
||||||
The old name still exists as a deprecated alias.
|
The old name still exists as a deprecated alias.
|
||||||
|
|
||||||
### New Features
|
### New Features
|
||||||
|
|||||||
@@ -0,0 +1,4 @@
|
|||||||
|
---
|
||||||
|
category: minorAnalysis
|
||||||
|
---
|
||||||
|
* `Flask::FlaskApp::instance()` will now also return instances of subclasses defined in the source tree. Previously, these were filtered out. `Flask::FlaskApp::classRef()` has been deprecated in favor of `Flask::FlaskApp::subclassRef()` since it already returned some subclasses.
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
name: codeql/python-all
|
name: codeql/python-all
|
||||||
version: 7.2.0
|
version: 7.2.1-dev
|
||||||
groups: python
|
groups: python
|
||||||
dbscheme: semmlecode.python.dbscheme
|
dbscheme: semmlecode.python.dbscheme
|
||||||
extractor: python
|
extractor: python
|
||||||
|
|||||||
@@ -1138,9 +1138,7 @@ predicate clearsContent(Node n, ContentSet cs) {
|
|||||||
* Holds if the value that is being tracked is expected to be stored inside content `c`
|
* Holds if the value that is being tracked is expected to be stored inside content `c`
|
||||||
* at node `n`.
|
* at node `n`.
|
||||||
*/
|
*/
|
||||||
predicate expectsContent(Node n, ContentSet c) {
|
predicate expectsContent(Node n, ContentSet c) { none() }
|
||||||
FlowSummaryImpl::Private::Steps::summaryExpectsContent(n.(FlowSummaryNode).getSummaryNode(), c)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Holds if values stored inside attribute `c` are cleared at node `n`.
|
* Holds if values stored inside attribute `c` are cleared at node `n`.
|
||||||
|
|||||||
@@ -91,8 +91,6 @@ module Input implements InputSig<Location, DataFlowImplSpecific::PythonDataFlow>
|
|||||||
cs.isAnyTupleOrDictionaryElement() and result = "AnyTupleOrDictionaryElement" and arg = ""
|
cs.isAnyTupleOrDictionaryElement() and result = "AnyTupleOrDictionaryElement" and arg = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
string encodeWithContent(ContentSet c, string arg) { result = "With" + encodeContent(c, arg) }
|
|
||||||
|
|
||||||
bindingset[token]
|
bindingset[token]
|
||||||
ParameterPosition decodeUnknownParameterPosition(AccessPath::AccessPathTokenBase token) {
|
ParameterPosition decodeUnknownParameterPosition(AccessPath::AccessPathTokenBase token) {
|
||||||
// needed to support `Argument[x..y]` ranges
|
// needed to support `Argument[x..y]` ranges
|
||||||
|
|||||||
@@ -170,13 +170,7 @@ module TypeTrackingInput implements Shared::TypeTrackingInput<Location> {
|
|||||||
|
|
||||||
/** Holds if there is a level step from `nodeFrom` to `nodeTo`, which may depend on the call graph. */
|
/** Holds if there is a level step from `nodeFrom` to `nodeTo`, which may depend on the call graph. */
|
||||||
predicate levelStepCall(Node nodeFrom, LocalSourceNode nodeTo) {
|
predicate levelStepCall(Node nodeFrom, LocalSourceNode nodeTo) {
|
||||||
// HOTFIX: `instanceFieldStep` is temporarily disabled (via `and none()`).
|
instanceFieldStep(nodeFrom, nodeTo)
|
||||||
// It uses `classInstanceTracker(cls)` -- itself a type-tracker run --
|
|
||||||
// from inside `levelStepCall`, creating a structural mutual recursion
|
|
||||||
// that causes catastrophic query slowdowns on some OOP-heavy Python
|
|
||||||
// codebases (e.g. mypy and dask). The `and none()` should be removed
|
|
||||||
// once that recursion is redesigned.
|
|
||||||
instanceFieldStep(nodeFrom, nodeTo) and none()
|
|
||||||
or
|
or
|
||||||
inheritedFieldStep(nodeFrom, nodeTo)
|
inheritedFieldStep(nodeFrom, nodeTo)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -71,14 +71,21 @@ module Flask {
|
|||||||
* See https://flask.palletsprojects.com/en/1.1.x/api/#flask.Flask.
|
* See https://flask.palletsprojects.com/en/1.1.x/api/#flask.Flask.
|
||||||
*/
|
*/
|
||||||
module FlaskApp {
|
module FlaskApp {
|
||||||
/** Gets a reference to the `flask.Flask` class. */
|
/**
|
||||||
API::Node classRef() {
|
* Gets a reference to the `flask.Flask` class or any subclass.
|
||||||
result = API::moduleImport("flask").getMember("Flask") or
|
*
|
||||||
|
* Deprecated: Use `subclassRef()` instead, this predicate always returned some subclasses.
|
||||||
|
*/
|
||||||
|
deprecated API::Node classRef() { result = subclassRef() }
|
||||||
|
|
||||||
|
/** Gets a reference to the `flask.Flask` class or any subclass. */
|
||||||
|
API::Node subclassRef() {
|
||||||
|
result = API::moduleImport("flask").getMember("Flask").getASubclass*() or
|
||||||
result = ModelOutput::getATypeNode("flask.Flask~Subclass").getASubclass*()
|
result = ModelOutput::getATypeNode("flask.Flask~Subclass").getASubclass*()
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Gets a reference to an instance of `flask.Flask` (a flask application). */
|
/** Gets a reference to an instance of `flask.Flask` (a flask application). */
|
||||||
API::Node instance() { result = classRef().getReturn() }
|
API::Node instance() { result = subclassRef().getReturn() }
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -132,7 +139,7 @@ module Flask {
|
|||||||
API::Node classRef() {
|
API::Node classRef() {
|
||||||
result = API::moduleImport("flask").getMember("Response")
|
result = API::moduleImport("flask").getMember("Response")
|
||||||
or
|
or
|
||||||
result = [FlaskApp::classRef(), FlaskApp::instance()].getMember("response_class")
|
result = [FlaskApp::subclassRef(), FlaskApp::instance()].getMember("response_class")
|
||||||
or
|
or
|
||||||
result = ModelOutput::getATypeNode("flask.Response~Subclass").getASubclass*()
|
result = ModelOutput::getATypeNode("flask.Response~Subclass").getASubclass*()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4199,9 +4199,11 @@ module StdlibPrivate {
|
|||||||
// The positional argument contains a mapping.
|
// The positional argument contains a mapping.
|
||||||
// TODO: these values can be overwritten by keyword arguments
|
// TODO: these values can be overwritten by keyword arguments
|
||||||
// - dict mapping
|
// - dict mapping
|
||||||
input = "Argument[0].WithAnyDictionaryElement" and
|
exists(DataFlow::DictionaryElementContent dc, string key | key = dc.getKey() |
|
||||||
output = "ReturnValue" and
|
input = "Argument[0].DictionaryElement[" + key + "]" and
|
||||||
preservesValue = true
|
output = "ReturnValue.DictionaryElement[" + key + "]" and
|
||||||
|
preservesValue = true
|
||||||
|
)
|
||||||
or
|
or
|
||||||
// - list-of-pairs mapping
|
// - list-of-pairs mapping
|
||||||
input = "Argument[0].ListElement.TupleElement[1]" and
|
input = "Argument[0].ListElement.TupleElement[1]" and
|
||||||
@@ -4238,7 +4240,9 @@ module StdlibPrivate {
|
|||||||
or
|
or
|
||||||
input = "Argument[0].SetElement"
|
input = "Argument[0].SetElement"
|
||||||
or
|
or
|
||||||
input = "Argument[0].AnyTupleElement"
|
exists(DataFlow::TupleElementContent tc, int i | i = tc.getIndex() |
|
||||||
|
input = "Argument[0].TupleElement[" + i.toString() + "]"
|
||||||
|
)
|
||||||
// TODO: Once we have DictKeyContent, we need to transform that into ListElementContent
|
// TODO: Once we have DictKeyContent, we need to transform that into ListElementContent
|
||||||
) and
|
) and
|
||||||
// Element content is mutated into list element content
|
// Element content is mutated into list element content
|
||||||
@@ -4262,9 +4266,11 @@ module StdlibPrivate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override predicate propagatesFlow(string input, string output, boolean preservesValue) {
|
override predicate propagatesFlow(string input, string output, boolean preservesValue) {
|
||||||
input = "Argument[0].WithAnyTupleElement" and
|
exists(DataFlow::TupleElementContent tc, int i | i = tc.getIndex() |
|
||||||
output = "ReturnValue" and
|
input = "Argument[0].TupleElement[" + i.toString() + "]" and
|
||||||
preservesValue = true
|
output = "ReturnValue.TupleElement[" + i.toString() + "]" and
|
||||||
|
preservesValue = true
|
||||||
|
)
|
||||||
or
|
or
|
||||||
input = "Argument[0].ListElement" and
|
input = "Argument[0].ListElement" and
|
||||||
output = "ReturnValue" and
|
output = "ReturnValue" and
|
||||||
@@ -4288,7 +4294,9 @@ module StdlibPrivate {
|
|||||||
or
|
or
|
||||||
input = "Argument[0].SetElement"
|
input = "Argument[0].SetElement"
|
||||||
or
|
or
|
||||||
input = "Argument[0].AnyTupleElement"
|
exists(DataFlow::TupleElementContent tc, int i | i = tc.getIndex() |
|
||||||
|
input = "Argument[0].TupleElement[" + i.toString() + "]"
|
||||||
|
)
|
||||||
// TODO: Once we have DictKeyContent, we need to transform that into ListElementContent
|
// TODO: Once we have DictKeyContent, we need to transform that into ListElementContent
|
||||||
) and
|
) and
|
||||||
output = "ReturnValue.SetElement" and
|
output = "ReturnValue.SetElement" and
|
||||||
@@ -4334,7 +4342,9 @@ module StdlibPrivate {
|
|||||||
or
|
or
|
||||||
input = "Argument[0].SetElement"
|
input = "Argument[0].SetElement"
|
||||||
or
|
or
|
||||||
input = "Argument[0].AnyTupleElement"
|
exists(DataFlow::TupleElementContent tc, int i | i = tc.getIndex() |
|
||||||
|
input = "Argument[0].TupleElement[" + i.toString() + "]"
|
||||||
|
)
|
||||||
// TODO: Once we have DictKeyContent, we need to transform that into ListElementContent
|
// TODO: Once we have DictKeyContent, we need to transform that into ListElementContent
|
||||||
) and
|
) and
|
||||||
output = "ReturnValue.ListElement" and
|
output = "ReturnValue.ListElement" and
|
||||||
@@ -4362,7 +4372,9 @@ module StdlibPrivate {
|
|||||||
or
|
or
|
||||||
content = "SetElement"
|
content = "SetElement"
|
||||||
or
|
or
|
||||||
content = "AnyTupleElement"
|
exists(DataFlow::TupleElementContent tc, int i | i = tc.getIndex() |
|
||||||
|
content = "TupleElement[" + i.toString() + "]"
|
||||||
|
)
|
||||||
|
|
|
|
||||||
// TODO: Once we have DictKeyContent, we need to transform that into ListElementContent
|
// TODO: Once we have DictKeyContent, we need to transform that into ListElementContent
|
||||||
input = "Argument[0]." + content and
|
input = "Argument[0]." + content and
|
||||||
@@ -4392,7 +4404,9 @@ module StdlibPrivate {
|
|||||||
or
|
or
|
||||||
input = "Argument[0].SetElement"
|
input = "Argument[0].SetElement"
|
||||||
or
|
or
|
||||||
input = "Argument[0].AnyTupleElement"
|
exists(DataFlow::TupleElementContent tc, int i | i = tc.getIndex() |
|
||||||
|
input = "Argument[0].TupleElement[" + i.toString() + "]"
|
||||||
|
)
|
||||||
// TODO: Once we have DictKeyContent, we need to transform that into ListElementContent
|
// TODO: Once we have DictKeyContent, we need to transform that into ListElementContent
|
||||||
) and
|
) and
|
||||||
output = "ReturnValue.ListElement" and
|
output = "ReturnValue.ListElement" and
|
||||||
@@ -4420,7 +4434,9 @@ module StdlibPrivate {
|
|||||||
or
|
or
|
||||||
input = "Argument[0].SetElement"
|
input = "Argument[0].SetElement"
|
||||||
or
|
or
|
||||||
input = "Argument[0].AnyTupleElement"
|
exists(DataFlow::TupleElementContent tc, int i | i = tc.getIndex() |
|
||||||
|
input = "Argument[0].TupleElement[" + i.toString() + "]"
|
||||||
|
)
|
||||||
// TODO: Once we have DictKeyContent, we need to transform that into ListElementContent
|
// TODO: Once we have DictKeyContent, we need to transform that into ListElementContent
|
||||||
) and
|
) and
|
||||||
output = "ReturnValue" and
|
output = "ReturnValue" and
|
||||||
@@ -4452,7 +4468,9 @@ module StdlibPrivate {
|
|||||||
// We reduce generality slightly by not tracking tuple contents on list arguments beyond the first, for performance.
|
// We reduce generality slightly by not tracking tuple contents on list arguments beyond the first, for performance.
|
||||||
// TODO: Once we have TupleElementAny, this generality can be increased.
|
// TODO: Once we have TupleElementAny, this generality can be increased.
|
||||||
i = 0 and
|
i = 0 and
|
||||||
input = "Argument[1].AnyTupleElement"
|
exists(DataFlow::TupleElementContent tc, int j | j = tc.getIndex() |
|
||||||
|
input = "Argument[1].TupleElement[" + j.toString() + "]"
|
||||||
|
)
|
||||||
// TODO: Once we have DictKeyContent, we need to transform that into ListElementContent
|
// TODO: Once we have DictKeyContent, we need to transform that into ListElementContent
|
||||||
) and
|
) and
|
||||||
output = "Argument[0].Parameter[" + i.toString() + "]" and
|
output = "Argument[0].Parameter[" + i.toString() + "]" and
|
||||||
@@ -4481,7 +4499,9 @@ module StdlibPrivate {
|
|||||||
or
|
or
|
||||||
input = "Argument[1].SetElement"
|
input = "Argument[1].SetElement"
|
||||||
or
|
or
|
||||||
input = "Argument[1].AnyTupleElement"
|
exists(DataFlow::TupleElementContent tc, int i | i = tc.getIndex() |
|
||||||
|
input = "Argument[1].TupleElement[" + i.toString() + "]"
|
||||||
|
)
|
||||||
// TODO: Once we have DictKeyContent, we need to transform that into ListElementContent
|
// TODO: Once we have DictKeyContent, we need to transform that into ListElementContent
|
||||||
) and
|
) and
|
||||||
(output = "Argument[0].Parameter[0]" or output = "ReturnValue.ListElement") and
|
(output = "Argument[0].Parameter[0]" or output = "ReturnValue.ListElement") and
|
||||||
@@ -4505,7 +4525,9 @@ module StdlibPrivate {
|
|||||||
or
|
or
|
||||||
input = "Argument[0].SetElement"
|
input = "Argument[0].SetElement"
|
||||||
or
|
or
|
||||||
input = "Argument[0].AnyTupleElement"
|
exists(DataFlow::TupleElementContent tc, int i | i = tc.getIndex() |
|
||||||
|
input = "Argument[0].TupleElement[" + i.toString() + "]"
|
||||||
|
)
|
||||||
// TODO: Once we have DictKeyContent, we need to transform that into ListElementContent
|
// TODO: Once we have DictKeyContent, we need to transform that into ListElementContent
|
||||||
) and
|
) and
|
||||||
output = "ReturnValue.ListElement.TupleElement[1]" and
|
output = "ReturnValue.ListElement.TupleElement[1]" and
|
||||||
@@ -4530,7 +4552,12 @@ module StdlibPrivate {
|
|||||||
or
|
or
|
||||||
input = "Argument[" + i.toString() + "].SetElement"
|
input = "Argument[" + i.toString() + "].SetElement"
|
||||||
or
|
or
|
||||||
input = "Argument[" + i.toString() + "].AnyTupleElement"
|
// We reduce generality slightly by not tracking tuple contents on arguments beyond the first two, for performance.
|
||||||
|
// TODO: Once we have TupleElementAny, this generality can be increased.
|
||||||
|
i in [0 .. 1] and
|
||||||
|
exists(DataFlow::TupleElementContent tc, int j | j = tc.getIndex() |
|
||||||
|
input = "Argument[" + i.toString() + "].TupleElement[" + j.toString() + "]"
|
||||||
|
)
|
||||||
// TODO: Once we have DictKeyContent, we need to transform that into ListElementContent
|
// TODO: Once we have DictKeyContent, we need to transform that into ListElementContent
|
||||||
) and
|
) and
|
||||||
output = "ReturnValue.ListElement.TupleElement[" + i.toString() + "]" and
|
output = "ReturnValue.ListElement.TupleElement[" + i.toString() + "]" and
|
||||||
@@ -4553,6 +4580,12 @@ module StdlibPrivate {
|
|||||||
override DataFlow::ArgumentNode getACallback() { none() }
|
override DataFlow::ArgumentNode getACallback() { none() }
|
||||||
|
|
||||||
override predicate propagatesFlow(string input, string output, boolean preservesValue) {
|
override predicate propagatesFlow(string input, string output, boolean preservesValue) {
|
||||||
|
exists(DataFlow::Content c |
|
||||||
|
input = "Argument[self]." + c.getMaDRepresentation() and
|
||||||
|
output = "ReturnValue." + c.getMaDRepresentation() and
|
||||||
|
preservesValue = true
|
||||||
|
)
|
||||||
|
or
|
||||||
input = "Argument[self]" and
|
input = "Argument[self]" and
|
||||||
output = "ReturnValue" and
|
output = "ReturnValue" and
|
||||||
preservesValue = true
|
preservesValue = true
|
||||||
@@ -4708,10 +4741,12 @@ module StdlibPrivate {
|
|||||||
override DataFlow::ArgumentNode getACallback() { none() }
|
override DataFlow::ArgumentNode getACallback() { none() }
|
||||||
|
|
||||||
override predicate propagatesFlow(string input, string output, boolean preservesValue) {
|
override predicate propagatesFlow(string input, string output, boolean preservesValue) {
|
||||||
input = "Argument[self].AnyDictionaryElement" and
|
exists(DataFlow::DictionaryElementContent dc, string key | key = dc.getKey() |
|
||||||
output = "ReturnValue.TupleElement[1]" and
|
input = "Argument[self].DictionaryElement[" + key + "]" and
|
||||||
preservesValue = true
|
output = "ReturnValue.TupleElement[1]" and
|
||||||
// TODO: put `key` into "ReturnValue.TupleElement[0]"
|
preservesValue = true
|
||||||
|
// TODO: put `key` into "ReturnValue.TupleElement[0]"
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4790,9 +4825,11 @@ module StdlibPrivate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override predicate propagatesFlow(string input, string output, boolean preservesValue) {
|
override predicate propagatesFlow(string input, string output, boolean preservesValue) {
|
||||||
input = "Argument[self].AnyDictionaryElement" and
|
exists(DataFlow::DictionaryElementContent dc, string key | key = dc.getKey() |
|
||||||
output = "ReturnValue.ListElement" and
|
input = "Argument[self].DictionaryElement[" + key + "]" and
|
||||||
preservesValue = true
|
output = "ReturnValue.ListElement" and
|
||||||
|
preservesValue = true
|
||||||
|
)
|
||||||
or
|
or
|
||||||
input = "Argument[self]" and
|
input = "Argument[self]" and
|
||||||
output = "ReturnValue" and
|
output = "ReturnValue" and
|
||||||
@@ -4839,9 +4876,11 @@ module StdlibPrivate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override predicate propagatesFlow(string input, string output, boolean preservesValue) {
|
override predicate propagatesFlow(string input, string output, boolean preservesValue) {
|
||||||
input = "Argument[self].AnyDictionaryElement" and
|
exists(DataFlow::DictionaryElementContent dc, string key | key = dc.getKey() |
|
||||||
output = "ReturnValue.ListElement.TupleElement[1]" and
|
input = "Argument[self].DictionaryElement[" + key + "]" and
|
||||||
preservesValue = true
|
output = "ReturnValue.ListElement.TupleElement[1]" and
|
||||||
|
preservesValue = true
|
||||||
|
)
|
||||||
or
|
or
|
||||||
// TODO: Add the keys to output list
|
// TODO: Add the keys to output list
|
||||||
input = "Argument[self]" and
|
input = "Argument[self]" and
|
||||||
|
|||||||
@@ -351,7 +351,7 @@ class DjangoHttpRequest extends FindSubclassesSpec {
|
|||||||
class FlaskClass extends FindSubclassesSpec {
|
class FlaskClass extends FindSubclassesSpec {
|
||||||
FlaskClass() { this = "flask.Flask~Subclass" }
|
FlaskClass() { this = "flask.Flask~Subclass" }
|
||||||
|
|
||||||
override API::Node getAlreadyModeledClass() { result = Flask::FlaskApp::classRef() }
|
override API::Node getAlreadyModeledClass() { result = Flask::FlaskApp::subclassRef() }
|
||||||
}
|
}
|
||||||
|
|
||||||
class FlaskBlueprint extends FindSubclassesSpec {
|
class FlaskBlueprint extends FindSubclassesSpec {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
name: codeql/python-queries
|
name: codeql/python-queries
|
||||||
version: 1.8.5
|
version: 1.8.6-dev
|
||||||
groups:
|
groups:
|
||||||
- python
|
- python
|
||||||
- queries
|
- queries
|
||||||
|
|||||||
29
python/ql/test/experimental/meta/InlineInstanceTest.qll
Normal file
29
python/ql/test/experimental/meta/InlineInstanceTest.qll
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
/**
|
||||||
|
* Defines an InlineExpectationsTest for class instances, that is,
|
||||||
|
* for any API::Node that is an instance of a class (e.g. `Flask`).
|
||||||
|
*/
|
||||||
|
|
||||||
|
import python
|
||||||
|
import semmle.python.ApiGraphs
|
||||||
|
import utils.test.InlineExpectationsTest
|
||||||
|
private import semmle.python.dataflow.new.internal.PrintNode
|
||||||
|
|
||||||
|
signature API::Node getInstanceSig();
|
||||||
|
|
||||||
|
module MakeInlineInstanceTest<getInstanceSig/0 getInstance> {
|
||||||
|
private module InlineInstanceTest implements TestSig {
|
||||||
|
string getARelevantTag() { result = "instance" }
|
||||||
|
|
||||||
|
predicate hasActualResult(Location location, string element, string tag, string value) {
|
||||||
|
exists(location.getFile().getRelativePath()) and
|
||||||
|
exists(API::Node instance | instance = getInstance() |
|
||||||
|
location = instance.getLocation() and
|
||||||
|
element = prettyNode(instance.asSource()) and
|
||||||
|
value = "" and
|
||||||
|
tag = "instance"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
import MakeTest<InlineInstanceTest>
|
||||||
|
}
|
||||||
@@ -589,11 +589,11 @@ def test_zip_tuple():
|
|||||||
|
|
||||||
SINK(z[0][0]) # $ flow="SOURCE, l:-7 -> z[0][0]"
|
SINK(z[0][0]) # $ flow="SOURCE, l:-7 -> z[0][0]"
|
||||||
SINK(z[0][1]) # $ flow="SOURCE, l:-7 -> z[0][1]"
|
SINK(z[0][1]) # $ flow="SOURCE, l:-7 -> z[0][1]"
|
||||||
SINK_F(z[0][2]) # $ SPURIOUS: flow="SOURCE, l:-7 -> z[0][2]"
|
SINK_F(z[0][2])
|
||||||
SINK_F(z[0][3])
|
SINK_F(z[0][3])
|
||||||
SINK(z[1][0]) # $ flow="SOURCE, l:-11 -> z[1][0]"
|
SINK(z[1][0]) # $ flow="SOURCE, l:-11 -> z[1][0]"
|
||||||
SINK_F(z[1][1]) # $ SPURIOUS: flow="SOURCE, l:-11 -> z[1][1]"
|
SINK_F(z[1][1]) # $ SPURIOUS: flow="SOURCE, l:-11 -> z[1][1]"
|
||||||
SINK(z[1][2]) # $ flow="SOURCE, l:-11 -> z[1][2]"
|
SINK(z[1][2]) # $ MISSING: flow="SOURCE, l:-11 -> z[1][2]" # Tuple contents are not tracked beyond the first two arguments for performance.
|
||||||
SINK_F(z[1][3])
|
SINK_F(z[1][3])
|
||||||
|
|
||||||
@expects(4)
|
@expects(4)
|
||||||
|
|||||||
@@ -157,7 +157,7 @@ class MyClass2(object):
|
|||||||
print(self.foo) # $ tracked MISSING: tracked=foo
|
print(self.foo) # $ tracked MISSING: tracked=foo
|
||||||
|
|
||||||
instance = MyClass2()
|
instance = MyClass2()
|
||||||
print(instance.foo) # $ MISSING: tracked=foo tracked
|
print(instance.foo) # $ tracked MISSING: tracked=foo
|
||||||
instance.print_foo() # $ MISSING: tracked=foo
|
instance.print_foo() # $ MISSING: tracked=foo
|
||||||
|
|
||||||
|
|
||||||
@@ -195,7 +195,7 @@ class Sub1(Base1):
|
|||||||
|
|
||||||
sub1 = Sub1()
|
sub1 = Sub1()
|
||||||
sub1.read_foo()
|
sub1.read_foo()
|
||||||
print(sub1.foo) # $ MISSING: tracked=foo tracked
|
print(sub1.foo) # $ tracked MISSING: tracked=foo
|
||||||
|
|
||||||
|
|
||||||
# attribute written in a subclass method, read in an inherited base class method
|
# attribute written in a subclass method, read in an inherited base class method
|
||||||
@@ -210,7 +210,7 @@ class Sub2(Base2):
|
|||||||
|
|
||||||
sub2 = Sub2()
|
sub2 = Sub2()
|
||||||
sub2.read_bar()
|
sub2.read_bar()
|
||||||
print(sub2.bar) # $ MISSING: tracked=bar tracked
|
print(sub2.bar) # $ tracked MISSING: tracked=bar
|
||||||
|
|
||||||
|
|
||||||
# attribute written in a base class method, read on an instance of the subclass
|
# attribute written in a base class method, read on an instance of the subclass
|
||||||
@@ -223,4 +223,4 @@ class Sub3(Base3):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
sub3 = Sub3()
|
sub3 = Sub3()
|
||||||
print(sub3.baz) # $ MISSING: tracked=baz tracked
|
print(sub3.baz) # $ tracked MISSING: tracked=baz
|
||||||
|
|||||||
@@ -362,7 +362,7 @@ def test_load_in_bulk():
|
|||||||
# see https://docs.djangoproject.com/en/4.0/ref/models/querysets/#in-bulk
|
# see https://docs.djangoproject.com/en/4.0/ref/models/querysets/#in-bulk
|
||||||
d = TestLoad.objects.in_bulk([1])
|
d = TestLoad.objects.in_bulk([1])
|
||||||
for val in d.values():
|
for val in d.values():
|
||||||
SINK(val.text) # $ flow="SOURCE, l:-65 -> val.text"
|
SINK(val.text) # $ MISSING: flow
|
||||||
SINK(d[1].text) # $ flow="SOURCE, l:-66 -> d[1].text"
|
SINK(d[1].text) # $ flow="SOURCE, l:-66 -> d[1].text"
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,8 @@
|
|||||||
|
import python
|
||||||
|
import semmle.python.frameworks.Flask
|
||||||
|
import semmle.python.ApiGraphs
|
||||||
|
import experimental.meta.InlineInstanceTest
|
||||||
|
|
||||||
|
API::Node getInstance() { result = Flask::FlaskApp::instance() }
|
||||||
|
|
||||||
|
import MakeInlineInstanceTest<getInstance/0>
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
from flask import Flask
|
||||||
|
|
||||||
|
|
||||||
|
class Sub(Flask):
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
Flask.__init__(self, *args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
app = Sub(__name__) # $ instance
|
||||||
|
|
||||||
|
|
||||||
|
@app.route("/") # $ routeSetup="/"
|
||||||
|
def hello(): # $ requestHandler
|
||||||
|
return "world" # $ HttpResponse
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
import flask
|
import flask
|
||||||
|
|
||||||
from flask import Flask, request, make_response
|
from flask import Flask, request, make_response
|
||||||
app = Flask(__name__)
|
app = Flask(__name__) # $ instance
|
||||||
|
|
||||||
@app.route("/") # $ routeSetup="/"
|
@app.route("/") # $ routeSetup="/"
|
||||||
def hello_world(): # $ requestHandler
|
def hello_world(): # $ requestHandler
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ import json
|
|||||||
from flask import Flask, make_response, jsonify, Response, request, redirect
|
from flask import Flask, make_response, jsonify, Response, request, redirect
|
||||||
from werkzeug.datastructures import Headers
|
from werkzeug.datastructures import Headers
|
||||||
|
|
||||||
app = Flask(__name__)
|
app = Flask(__name__) # $ instance
|
||||||
|
|
||||||
|
|
||||||
@app.route("/html1") # $ routeSetup="/html1"
|
@app.route("/html1") # $ routeSetup="/html1"
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import flask
|
import flask
|
||||||
|
|
||||||
from flask import Flask, make_response
|
from flask import Flask, make_response
|
||||||
app = Flask(__name__)
|
app = Flask(__name__) # $ instance
|
||||||
|
|
||||||
|
|
||||||
SOME_ROUTE = "/some/route"
|
SOME_ROUTE = "/some/route"
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
from flask import Flask, request
|
from flask import Flask, request
|
||||||
app = Flask(__name__)
|
app = Flask(__name__) # $ instance
|
||||||
|
|
||||||
@app.route("/save-uploaded-file") # $ routeSetup="/save-uploaded-file"
|
@app.route("/save-uploaded-file") # $ routeSetup="/save-uploaded-file"
|
||||||
def test_taint(): # $ requestHandler
|
def test_taint(): # $ requestHandler
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
from flask import Flask, request, render_template_string, stream_template_string
|
from flask import Flask, request, render_template_string, stream_template_string
|
||||||
app = Flask(__name__)
|
app = Flask(__name__) # $ instance
|
||||||
|
|
||||||
@app.route("/test_taint/<name>/<int:number>") # $ routeSetup="/test_taint/<name>/<int:number>"
|
@app.route("/test_taint/<name>/<int:number>") # $ routeSetup="/test_taint/<name>/<int:number>"
|
||||||
def test_taint(name = "World!", number="0", foo="foo"): # $ requestHandler routedParameter=name routedParameter=number
|
def test_taint(name = "World!", number="0", foo="foo"): # $ requestHandler routedParameter=name routedParameter=number
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
from flask import Flask, Response, stream_with_context, render_template_string, stream_template_string
|
from flask import Flask, Response, stream_with_context, render_template_string, stream_template_string
|
||||||
app = Flask(__name__)
|
app = Flask(__name__) # $ instance
|
||||||
|
|
||||||
@app.route("/a") # $ routeSetup="/a"
|
@app.route("/a") # $ routeSetup="/a"
|
||||||
def a(): # $ requestHandler
|
def a(): # $ requestHandler
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
#select
|
#select
|
||||||
| app.py:23:20:23:24 | ControlFlowNode for query | app.py:20:18:20:21 | ControlFlowNode for name | app.py:23:20:23:24 | ControlFlowNode for query | This SQL query depends on a $@. | app.py:20:18:20:21 | ControlFlowNode for name | user-provided value |
|
| app.py:23:20:23:24 | ControlFlowNode for query | app.py:20:18:20:21 | ControlFlowNode for name | app.py:23:20:23:24 | ControlFlowNode for query | This SQL query depends on a $@. | app.py:20:18:20:21 | ControlFlowNode for name | user-provided value |
|
||||||
| app.py:30:20:30:24 | ControlFlowNode for query | app.py:27:19:27:22 | ControlFlowNode for name | app.py:30:20:30:24 | ControlFlowNode for query | This SQL query depends on a $@. | app.py:27:19:27:22 | ControlFlowNode for name | user-provided value |
|
| app.py:30:20:30:24 | ControlFlowNode for query | app.py:27:19:27:22 | ControlFlowNode for name | app.py:30:20:30:24 | ControlFlowNode for query | This SQL query depends on a $@. | app.py:27:19:27:22 | ControlFlowNode for name | user-provided value |
|
||||||
|
| app.py:37:20:37:24 | ControlFlowNode for query | app.py:34:19:34:22 | ControlFlowNode for name | app.py:37:20:37:24 | ControlFlowNode for query | This SQL query depends on a $@. | app.py:34:19:34:22 | ControlFlowNode for name | user-provided value |
|
||||||
| app.py:44:20:44:24 | ControlFlowNode for query | app.py:41:19:41:22 | ControlFlowNode for name | app.py:44:20:44:24 | ControlFlowNode for query | This SQL query depends on a $@. | app.py:41:19:41:22 | ControlFlowNode for name | user-provided value |
|
| app.py:44:20:44:24 | ControlFlowNode for query | app.py:41:19:41:22 | ControlFlowNode for name | app.py:44:20:44:24 | ControlFlowNode for query | This SQL query depends on a $@. | app.py:41:19:41:22 | ControlFlowNode for name | user-provided value |
|
||||||
| app.py:51:20:51:24 | ControlFlowNode for query | app.py:48:19:48:22 | ControlFlowNode for name | app.py:51:20:51:24 | ControlFlowNode for query | This SQL query depends on a $@. | app.py:48:19:48:22 | ControlFlowNode for name | user-provided value |
|
| app.py:51:20:51:24 | ControlFlowNode for query | app.py:48:19:48:22 | ControlFlowNode for name | app.py:51:20:51:24 | ControlFlowNode for query | This SQL query depends on a $@. | app.py:48:19:48:22 | ControlFlowNode for name | user-provided value |
|
||||||
| sql_injection.py:21:24:21:77 | ControlFlowNode for BinaryExpr | sql_injection.py:14:15:14:22 | ControlFlowNode for username | sql_injection.py:21:24:21:77 | ControlFlowNode for BinaryExpr | This SQL query depends on a $@. | sql_injection.py:14:15:14:22 | ControlFlowNode for username | user-provided value |
|
| sql_injection.py:21:24:21:77 | ControlFlowNode for BinaryExpr | sql_injection.py:14:15:14:22 | ControlFlowNode for username | sql_injection.py:21:24:21:77 | ControlFlowNode for BinaryExpr | This SQL query depends on a $@. | sql_injection.py:14:15:14:22 | ControlFlowNode for username | user-provided value |
|
||||||
@@ -24,6 +25,8 @@ edges
|
|||||||
| app.py:21:5:21:9 | ControlFlowNode for query | app.py:23:20:23:24 | ControlFlowNode for query | provenance | |
|
| app.py:21:5:21:9 | ControlFlowNode for query | app.py:23:20:23:24 | ControlFlowNode for query | provenance | |
|
||||||
| app.py:27:19:27:22 | ControlFlowNode for name | app.py:28:5:28:9 | ControlFlowNode for query | provenance | |
|
| app.py:27:19:27:22 | ControlFlowNode for name | app.py:28:5:28:9 | ControlFlowNode for query | provenance | |
|
||||||
| app.py:28:5:28:9 | ControlFlowNode for query | app.py:30:20:30:24 | ControlFlowNode for query | provenance | |
|
| app.py:28:5:28:9 | ControlFlowNode for query | app.py:30:20:30:24 | ControlFlowNode for query | provenance | |
|
||||||
|
| app.py:34:19:34:22 | ControlFlowNode for name | app.py:35:5:35:9 | ControlFlowNode for query | provenance | |
|
||||||
|
| app.py:35:5:35:9 | ControlFlowNode for query | app.py:37:20:37:24 | ControlFlowNode for query | provenance | |
|
||||||
| app.py:41:19:41:22 | ControlFlowNode for name | app.py:42:5:42:9 | ControlFlowNode for query | provenance | |
|
| app.py:41:19:41:22 | ControlFlowNode for name | app.py:42:5:42:9 | ControlFlowNode for query | provenance | |
|
||||||
| app.py:42:5:42:9 | ControlFlowNode for query | app.py:44:20:44:24 | ControlFlowNode for query | provenance | |
|
| app.py:42:5:42:9 | ControlFlowNode for query | app.py:44:20:44:24 | ControlFlowNode for query | provenance | |
|
||||||
| app.py:48:19:48:22 | ControlFlowNode for name | app.py:49:5:49:9 | ControlFlowNode for query | provenance | |
|
| app.py:48:19:48:22 | ControlFlowNode for name | app.py:49:5:49:9 | ControlFlowNode for query | provenance | |
|
||||||
@@ -51,6 +54,9 @@ nodes
|
|||||||
| app.py:27:19:27:22 | ControlFlowNode for name | semmle.label | ControlFlowNode for name |
|
| app.py:27:19:27:22 | ControlFlowNode for name | semmle.label | ControlFlowNode for name |
|
||||||
| app.py:28:5:28:9 | ControlFlowNode for query | semmle.label | ControlFlowNode for query |
|
| app.py:28:5:28:9 | ControlFlowNode for query | semmle.label | ControlFlowNode for query |
|
||||||
| app.py:30:20:30:24 | ControlFlowNode for query | semmle.label | ControlFlowNode for query |
|
| app.py:30:20:30:24 | ControlFlowNode for query | semmle.label | ControlFlowNode for query |
|
||||||
|
| app.py:34:19:34:22 | ControlFlowNode for name | semmle.label | ControlFlowNode for name |
|
||||||
|
| app.py:35:5:35:9 | ControlFlowNode for query | semmle.label | ControlFlowNode for query |
|
||||||
|
| app.py:37:20:37:24 | ControlFlowNode for query | semmle.label | ControlFlowNode for query |
|
||||||
| app.py:41:19:41:22 | ControlFlowNode for name | semmle.label | ControlFlowNode for name |
|
| app.py:41:19:41:22 | ControlFlowNode for name | semmle.label | ControlFlowNode for name |
|
||||||
| app.py:42:5:42:9 | ControlFlowNode for query | semmle.label | ControlFlowNode for query |
|
| app.py:42:5:42:9 | ControlFlowNode for query | semmle.label | ControlFlowNode for query |
|
||||||
| app.py:44:20:44:24 | ControlFlowNode for query | semmle.label | ControlFlowNode for query |
|
| app.py:44:20:44:24 | ControlFlowNode for query | semmle.label | ControlFlowNode for query |
|
||||||
|
|||||||
@@ -31,10 +31,10 @@ async def unsafe2(name: str): # $ Source
|
|||||||
cursor.close()
|
cursor.close()
|
||||||
|
|
||||||
@app.get("/unsafe3/")
|
@app.get("/unsafe3/")
|
||||||
async def unsafe3(name: str): # $ MISSING: Source
|
async def unsafe3(name: str): # $ Source
|
||||||
query = "select * from users where name=" + name
|
query = "select * from users where name=" + name
|
||||||
cursor = hdb_con3.cursor()
|
cursor = hdb_con3.cursor()
|
||||||
cursor.execute(query) # $ MISSING: Alert
|
cursor.execute(query) # $ Alert
|
||||||
cursor.close()
|
cursor.close()
|
||||||
|
|
||||||
@app.get("/unsafe4/")
|
@app.get("/unsafe4/")
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user